From fcdea621bfc714e3bdc58b60706e2c6612c88c10 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 25 Oct 2015 13:42:49 -0700 Subject: [PATCH 001/273] first commit --- LICENSE.md | 206 ++++++++++++++++++++++++++++++++++++++++++++++ priv_key.go | 77 +++++++++++++++++ pub_key.go | 91 ++++++++++++++++++++ signature.go | 34 ++++++++ signature_test.go | 68 +++++++++++++++ 5 files changed, 476 insertions(+) create mode 100644 LICENSE.md create mode 100644 priv_key.go create mode 100644 pub_key.go create mode 100644 signature.go create mode 100644 signature_test.go diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..25db84e64 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,206 @@ +Tendermint Go-Crypto +Copyright (C) 2015 Tendermint + +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 . + +//-------------------------------------------------------------------------------- + +GNU GENERAL PUBLIC LICENSE + +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. + +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 diff --git a/priv_key.go b/priv_key.go new file mode 100644 index 000000000..9a5c66163 --- /dev/null +++ b/priv_key.go @@ -0,0 +1,77 @@ +package account + +import ( + "github.com/tendermint/ed25519" + "github.com/tendermint/ed25519/extra25519" + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" +) + +// PrivKey is part of PrivAccount and state.PrivValidator. +type PrivKey interface { + Sign(msg []byte) Signature + PubKey() PubKey +} + +// Types of PrivKey implementations +const ( + PrivKeyTypeEd25519 = byte(0x01) +) + +// for wire.readReflect +var _ = wire.RegisterInterface( + struct{ PrivKey }{}, + wire.ConcreteType{PrivKeyEd25519{}, PrivKeyTypeEd25519}, +) + +//------------------------------------- + +// Implements PrivKey +type PrivKeyEd25519 [64]byte + +func (key PrivKeyEd25519) Sign(msg []byte) Signature { + privKeyBytes := [64]byte(key) + signatureBytes := ed25519.Sign(&privKeyBytes, msg) + return SignatureEd25519(*signatureBytes) +} + +func (privKey PrivKeyEd25519) PubKey() PubKey { + privKeyBytes := [64]byte(privKey) + return PubKeyEd25519(*ed25519.MakePublicKey(&privKeyBytes)) +} + +func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { + keyCurve25519 := new([32]byte) + privKeyBytes := [64]byte(privKey) + extra25519.PrivateKeyToCurve25519(keyCurve25519, &privKeyBytes) + return keyCurve25519 +} + +func (privKey PrivKeyEd25519) String() string { + return Fmt("PrivKeyEd25519{*****}") +} + +// Deterministically generates new priv-key bytes from key. +func (key PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { + newBytes := wire.BinarySha256(struct { + PrivKey [64]byte + Index int + }{key, index}) + var newKey [64]byte + copy(newKey[:], newBytes) + return PrivKeyEd25519(newKey) +} + +func GenPrivKeyEd25519() PrivKeyEd25519 { + privKeyBytes := new([64]byte) + copy(privKeyBytes[:32], CRandBytes(32)) + ed25519.MakePublicKey(privKeyBytes) + return PrivKeyEd25519(*privKeyBytes) +} + +func GenPrivKeyEd25519FromSecret(secret string) PrivKeyEd25519 { + privKey32 := wire.BinarySha256(secret) // Not Ripemd160 because we want 32 bytes. + privKeyBytes := new([64]byte) + copy(privKeyBytes[:32], privKey32) + return PrivKeyEd25519(*privKeyBytes) +} diff --git a/pub_key.go b/pub_key.go new file mode 100644 index 000000000..0e7d8fa0d --- /dev/null +++ b/pub_key.go @@ -0,0 +1,91 @@ + +package account + +import ( + "bytes" + + "github.com/tendermint/ed25519" + "github.com/tendermint/ed25519/extra25519" + "golang.org/x/crypto/ripemd160" + "github.com/tendermint/go-wire" + . "github.com/tendermint/go-common" +) + +// PubKey is part of Account and Validator. +type PubKey interface { + Address() []byte + VerifyBytes(msg []byte, sig Signature) bool +} + +// Types of PubKey implementations +const ( + PubKeyTypeEd25519 = byte(0x01) +) + +// for wire.readReflect +var _ = wire.RegisterInterface( + struct{ PubKey }{}, + wire.ConcreteType{PubKeyEd25519{}, PubKeyTypeEd25519}, +) + +//------------------------------------- + +// Implements PubKey +type PubKeyEd25519 [32]byte + +// TODO: Slicing the array gives us length prefixing but loses the type byte. +// Revisit if we add more pubkey types. +// For now, we artificially append the type byte in front to give us backwards +// compatibility for when the pubkey wasn't fixed length array +func (pubKey PubKeyEd25519) Address() []byte { + w, n, err := new(bytes.Buffer), new(int64), new(error) + wire.WriteBinary(pubKey[:], w, n, err) + if *err != nil { + PanicCrisis(*err) + } + // append type byte + encodedPubkey := append([]byte{1}, w.Bytes()...) + hasher := ripemd160.New() + hasher.Write(encodedPubkey) // does not error + return hasher.Sum(nil) +} + +// TODO: Consider returning a reason for failure, or logging a runtime type mismatch. +func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { + sig, ok := sig_.(SignatureEd25519) + if !ok { + return false + } + pubKeyBytes := [32]byte(pubKey) + sigBytes := [64]byte(sig) + return ed25519.Verify(&pubKeyBytes, msg, &sigBytes) +} + +// For use with golang/crypto/nacl/box +// If error, returns nil. +func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte { + keyCurve25519, pubKeyBytes := new([32]byte), [32]byte(pubKey) + ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes) + if !ok { + return nil + } + return keyCurve25519 +} + +func (pubKey PubKeyEd25519) String() string { + return Fmt("PubKeyEd25519{%X}", pubKey[:]) +} + +// Must return the full bytes in hex. +// Used for map keying, etc. +func (pubKey PubKeyEd25519) KeyString() string { + return Fmt("%X", pubKey[:]) +} + +func (pubKey PubKeyEd25519) Equals(other PubKey) bool { + if otherEd, ok := other.(PubKeyEd25519); ok { + return bytes.Equal(pubKey[:], otherEd[:]) + } else { + return false + } +} diff --git a/signature.go b/signature.go new file mode 100644 index 000000000..1224c5c99 --- /dev/null +++ b/signature.go @@ -0,0 +1,34 @@ +package account + +import ( + "fmt" + + "github.com/tendermint/go-wire" + . "github.com/tendermint/go-common" +) + +// Signature is a part of Txs and consensus Votes. +type Signature interface { + IsZero() bool + String() string +} + +// Types of Signature implementations +const ( + SignatureTypeEd25519 = byte(0x01) +) + +// for wire.readReflect +var _ = wire.RegisterInterface( + struct{ Signature }{}, + wire.ConcreteType{SignatureEd25519{}, SignatureTypeEd25519}, +) + +//------------------------------------- + +// Implements Signature +type SignatureEd25519 [64]byte + +func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } + +func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } diff --git a/signature_test.go b/signature_test.go new file mode 100644 index 000000000..8e603f97b --- /dev/null +++ b/signature_test.go @@ -0,0 +1,68 @@ +package account + +import ( + "bytes" + "testing" + + "github.com/tendermint/ed25519" + . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" +) + +func TestSignAndValidate(t *testing.T) { + + privKey := GenPrivKeyEd25519() + pubKey := privKey.PubKey() + + msg := CRandBytes(128) + sig := privKey.Sign(msg) + t.Logf("msg: %X, sig: %X", msg, sig) + + // Test the signature + if !pubKey.VerifyBytes(msg, sig) { + t.Errorf("Account message signature verification failed") + } + + // Mutate the signature, just one bit. + sigEd := sig.(SignatureEd25519) + sigEd[0] ^= byte(0x01) + sig = Signature(sigEd) + + if pubKey.VerifyBytes(msg, sig) { + t.Errorf("Account message signature verification should have failed but passed instead") + } +} + +func TestBinaryDecode(t *testing.T) { + + privKey := GenPrivKeyEd25519() + pubKey := privKey.PubKey() + + msg := CRandBytes(128) + sig := privKey.Sign(msg) + t.Logf("msg: %X, sig: %X", msg, sig) + + buf, n, err := new(bytes.Buffer), new(int64), new(error) + wire.WriteBinary(sig, buf, n, err) + if *err != nil { + t.Fatalf("Failed to write Signature: %v", err) + } + + if len(buf.Bytes()) != ed25519.SignatureSize+1 { + // 1 byte TypeByte, 64 bytes signature bytes + t.Fatalf("Unexpected signature write size: %v", len(buf.Bytes())) + } + if buf.Bytes()[0] != SignatureTypeEd25519 { + t.Fatalf("Unexpected signature type byte") + } + + sig2, ok := wire.ReadBinary(SignatureEd25519{}, buf, n, err).(SignatureEd25519) + if !ok || *err != nil { + t.Fatalf("Failed to read Signature: %v", err) + } + + // Test the signature + if !pubKey.VerifyBytes(msg, sig2) { + t.Errorf("Account message signature verification failed") + } +} From 31a456c8d403333639cf0b1d02e73037d4212cc4 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 25 Oct 2015 13:45:13 -0700 Subject: [PATCH 002/273] update package name --- priv_key.go | 2 +- pub_key.go | 7 +++---- signature.go | 4 ++-- signature_test.go | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/priv_key.go b/priv_key.go index 9a5c66163..f548172e4 100644 --- a/priv_key.go +++ b/priv_key.go @@ -1,4 +1,4 @@ -package account +package crypto import ( "github.com/tendermint/ed25519" diff --git a/pub_key.go b/pub_key.go index 0e7d8fa0d..6eeb4a86e 100644 --- a/pub_key.go +++ b/pub_key.go @@ -1,14 +1,13 @@ - -package account +package crypto import ( "bytes" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" - "golang.org/x/crypto/ripemd160" - "github.com/tendermint/go-wire" . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" + "golang.org/x/crypto/ripemd160" ) // PubKey is part of Account and Validator. diff --git a/signature.go b/signature.go index 1224c5c99..959258091 100644 --- a/signature.go +++ b/signature.go @@ -1,10 +1,10 @@ -package account +package crypto import ( "fmt" - "github.com/tendermint/go-wire" . "github.com/tendermint/go-common" + "github.com/tendermint/go-wire" ) // Signature is a part of Txs and consensus Votes. diff --git a/signature_test.go b/signature_test.go index 8e603f97b..1dbc58096 100644 --- a/signature_test.go +++ b/signature_test.go @@ -1,4 +1,4 @@ -package account +package crypto import ( "bytes" From 32b3a27a9a7a4c3c94c406cc10fc7749e639bdd3 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 10 Nov 2015 11:53:35 -0800 Subject: [PATCH 003/273] Conform to new go-wire 1.0 --- pub_key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pub_key.go b/pub_key.go index 6eeb4a86e..47eba9ed6 100644 --- a/pub_key.go +++ b/pub_key.go @@ -37,7 +37,7 @@ type PubKeyEd25519 [32]byte // For now, we artificially append the type byte in front to give us backwards // compatibility for when the pubkey wasn't fixed length array func (pubKey PubKeyEd25519) Address() []byte { - w, n, err := new(bytes.Buffer), new(int64), new(error) + w, n, err := new(bytes.Buffer), new(int), new(error) wire.WriteBinary(pubKey[:], w, n, err) if *err != nil { PanicCrisis(*err) From ea56ed5ea24c2d6928be62d9921ff99643dfe8db Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 23 Dec 2015 14:17:27 -0800 Subject: [PATCH 004/273] Change license to Apache2.0 --- LICENSE | 193 +++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE.md | 206 ----------------------------------------------------- 2 files changed, 193 insertions(+), 206 deletions(-) create mode 100644 LICENSE delete mode 100644 LICENSE.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..3beb77b13 --- /dev/null +++ b/LICENSE @@ -0,0 +1,193 @@ +Tendermint Go-Crypto +Copyright (C) 2015 Tendermint + + + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 25db84e64..000000000 --- a/LICENSE.md +++ /dev/null @@ -1,206 +0,0 @@ -Tendermint Go-Crypto -Copyright (C) 2015 Tendermint - -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 . - -//-------------------------------------------------------------------------------- - -GNU GENERAL PUBLIC LICENSE - -Version 3, 29 June 2007 - -Copyright © 2007 Free Software Foundation, Inc. - -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 From 1fb7234ff5138df3df93678dd62cc4bc892b2f06 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 16 Jan 2016 13:49:16 -0500 Subject: [PATCH 005/273] fix test --- signature_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/signature_test.go b/signature_test.go index 1dbc58096..6a803b697 100644 --- a/signature_test.go +++ b/signature_test.go @@ -42,8 +42,8 @@ func TestBinaryDecode(t *testing.T) { sig := privKey.Sign(msg) t.Logf("msg: %X, sig: %X", msg, sig) - buf, n, err := new(bytes.Buffer), new(int64), new(error) - wire.WriteBinary(sig, buf, n, err) + buf, n, err := new(bytes.Buffer), new(int), new(error) + wire.WriteBinary(struct{ Signature }{sig}, buf, n, err) if *err != nil { t.Fatalf("Failed to write Signature: %v", err) } @@ -56,13 +56,14 @@ func TestBinaryDecode(t *testing.T) { t.Fatalf("Unexpected signature type byte") } - sig2, ok := wire.ReadBinary(SignatureEd25519{}, buf, n, err).(SignatureEd25519) - if !ok || *err != nil { + sigStruct := struct{ Signature }{} + sig2 := wire.ReadBinary(sigStruct, buf, 0, n, err) + if *err != nil { t.Fatalf("Failed to read Signature: %v", err) } // Test the signature - if !pubKey.VerifyBytes(msg, sig2) { + if !pubKey.VerifyBytes(msg, sig2.(struct{ Signature }).Signature.(SignatureEd25519)) { t.Errorf("Account message signature verification failed") } } From 372191dd5fc888ac21629be55fddd4fa22db06d7 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 8 Feb 2016 00:50:52 -0800 Subject: [PATCH 006/273] KeyString() in PubKey; Fix tests --- pub_key.go | 1 + signature_test.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pub_key.go b/pub_key.go index 47eba9ed6..c5d3cadc2 100644 --- a/pub_key.go +++ b/pub_key.go @@ -13,6 +13,7 @@ import ( // PubKey is part of Account and Validator. type PubKey interface { Address() []byte + KeyString() string VerifyBytes(msg []byte, sig Signature) bool } diff --git a/signature_test.go b/signature_test.go index 1dbc58096..b7eec577f 100644 --- a/signature_test.go +++ b/signature_test.go @@ -42,7 +42,7 @@ func TestBinaryDecode(t *testing.T) { sig := privKey.Sign(msg) t.Logf("msg: %X, sig: %X", msg, sig) - buf, n, err := new(bytes.Buffer), new(int64), new(error) + buf, n, err := new(bytes.Buffer), new(int), new(error) wire.WriteBinary(sig, buf, n, err) if *err != nil { t.Fatalf("Failed to write Signature: %v", err) @@ -56,7 +56,7 @@ func TestBinaryDecode(t *testing.T) { t.Fatalf("Unexpected signature type byte") } - sig2, ok := wire.ReadBinary(SignatureEd25519{}, buf, n, err).(SignatureEd25519) + sig2, ok := wire.ReadBinary(SignatureEd25519{}, buf, 0, n, err).(SignatureEd25519) if !ok || *err != nil { t.Fatalf("Failed to read Signature: %v", err) } From 76ba23e4c0c627b8c66d1f97b6a18dc77f4f0297 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 8 Feb 2016 02:18:06 -0800 Subject: [PATCH 007/273] Fix bug in GenPrivKeyEd25519FromSecret --- priv_key.go | 1 + 1 file changed, 1 insertion(+) diff --git a/priv_key.go b/priv_key.go index f548172e4..5e93fbe11 100644 --- a/priv_key.go +++ b/priv_key.go @@ -73,5 +73,6 @@ func GenPrivKeyEd25519FromSecret(secret string) PrivKeyEd25519 { privKey32 := wire.BinarySha256(secret) // Not Ripemd160 because we want 32 bytes. privKeyBytes := new([64]byte) copy(privKeyBytes[:32], privKey32) + ed25519.MakePublicKey(privKeyBytes) return PrivKeyEd25519(*privKeyBytes) } From 264d2a3eef760ab171f253b738b7d5dad5cde1b9 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 13 Mar 2016 09:40:15 -0700 Subject: [PATCH 008/273] Add seed-able cryptographic random. --- hash.go | 18 +++++++++ pub_key.go | 1 + random.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++ signature_test.go | 1 - 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 hash.go create mode 100644 random.go diff --git a/hash.go b/hash.go new file mode 100644 index 000000000..165b1e153 --- /dev/null +++ b/hash.go @@ -0,0 +1,18 @@ +package crypto + +import ( + "crypto/sha256" + "golang.org/x/crypto/ripemd160" +) + +func Sha256(bytes []byte) []byte { + hasher := sha256.New() + hasher.Write(bytes) + return hasher.Sum(nil) +} + +func Ripemd160(bytes []byte) []byte { + hasher := ripemd160.New() + hasher.Write(bytes) + return hasher.Sum(nil) +} diff --git a/pub_key.go b/pub_key.go index c5d3cadc2..4cfe815ce 100644 --- a/pub_key.go +++ b/pub_key.go @@ -15,6 +15,7 @@ type PubKey interface { Address() []byte KeyString() string VerifyBytes(msg []byte, sig Signature) bool + Equals(PubKey) bool } // Types of PubKey implementations diff --git a/random.go b/random.go new file mode 100644 index 000000000..803386843 --- /dev/null +++ b/random.go @@ -0,0 +1,100 @@ +package crypto + +import ( + "crypto/aes" + "crypto/cipher" + crand "crypto/rand" + "encoding/hex" + "io" + "sync" + + . "github.com/tendermint/go-common" +) + +var gRandInfo *randInfo + +func init() { + gRandInfo = &randInfo{} + gRandInfo.AddSeed(randBytes(32)) // Init +} + +// Add additional bytes of randomness, e.g. from hardware, user-input, etc. +// It is OK to call it multiple times. It does not deminish security. +func Seed(seedBytes []byte) { + gRandInfo.AddSeed(seedBytes) +} + +// This only uses the OS's randomness +func randBytes(numBytes int) []byte { + b := make([]byte, numBytes) + _, err := crand.Read(b) + if err != nil { + PanicCrisis(err) + } + return b +} + +// This uses the OS and the Seed(s). +func CRandBytes(numBytes int) []byte { + b := make([]byte, numBytes) + _, err := gRandInfo.Read(b) + if err != nil { + PanicCrisis(err) + } + return b +} + +// RandHex(24) gives 96 bits of randomness, strong enough for most purposes. +func CRandHex(numDigits int) string { + return hex.EncodeToString(CRandBytes(numDigits / 2)) +} + +// Returns a crand.Reader mixed with user-supplied entropy +func CReader() io.Reader { + return gRandInfo +} + +//-------------------------------------------------------------------------------- + +type randInfo struct { + mtx sync.Mutex + seedBytes [32]byte + cipherAES256 cipher.Block + streamAES256 cipher.Stream + reader io.Reader +} + +// You can call this as many times as you'd like. +// XXX TODO review +func (ri *randInfo) AddSeed(seedBytes []byte) { + ri.mtx.Lock() + defer ri.mtx.Unlock() + // Make new ri.seedBytes + hashBytes := Sha256(seedBytes) + hashBytes32 := [32]byte{} + copy(hashBytes32[:], hashBytes) + ri.seedBytes = xorBytes32(ri.seedBytes, hashBytes32) + // Create new cipher.Block + var err error + ri.cipherAES256, err = aes.NewCipher(ri.seedBytes[:]) + if err != nil { + PanicSanity("Error creating AES256 cipher: " + err.Error()) + } + // Create new stream + ri.streamAES256 = cipher.NewCTR(ri.cipherAES256, randBytes(aes.BlockSize)) + // Create new reader + ri.reader = &cipher.StreamReader{S: ri.streamAES256, R: crand.Reader} +} + +func (ri *randInfo) Read(b []byte) (n int, err error) { + ri.mtx.Lock() + defer ri.mtx.Unlock() + return ri.reader.Read(b) +} + +func xorBytes32(bytesA [32]byte, bytesB [32]byte) (res [32]byte) { + for i, b := range bytesA { + res[i] = b ^ bytesB[i] + } + return res +} diff --git a/signature_test.go b/signature_test.go index 6a803b697..e4e72e48d 100644 --- a/signature_test.go +++ b/signature_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/tendermint/ed25519" - . "github.com/tendermint/go-common" "github.com/tendermint/go-wire" ) From f59fe0c8e0b45a2f7aca9ed3e4f18427a3493766 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 13 Mar 2016 10:14:24 -0700 Subject: [PATCH 009/273] s/Seed/MixEntropy/g --- random.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/random.go b/random.go index 803386843..edadeaab6 100644 --- a/random.go +++ b/random.go @@ -15,13 +15,13 @@ var gRandInfo *randInfo func init() { gRandInfo = &randInfo{} - gRandInfo.AddSeed(randBytes(32)) // Init + gRandInfo.MixEntropy(randBytes(32)) // Init } -// Add additional bytes of randomness, e.g. from hardware, user-input, etc. -// It is OK to call it multiple times. It does not deminish security. -func Seed(seedBytes []byte) { - gRandInfo.AddSeed(seedBytes) +// Mix additional bytes of randomness, e.g. from hardware, user-input, etc. +// It is OK to call it multiple times. It does not diminish security. +func MixEntropy(seedBytes []byte) { + gRandInfo.MixEntropy(seedBytes) } // This only uses the OS's randomness @@ -66,7 +66,7 @@ type randInfo struct { // You can call this as many times as you'd like. // XXX TODO review -func (ri *randInfo) AddSeed(seedBytes []byte) { +func (ri *randInfo) MixEntropy(seedBytes []byte) { ri.mtx.Lock() defer ri.mtx.Unlock() // Make new ri.seedBytes From 181aa56c8711c9dc40eb7d2f2b259b0d1ed5240e Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 13 Mar 2016 12:55:02 -0700 Subject: [PATCH 010/273] Added symmetric encrypt/decrypt methods --- encrypt.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ encrypt_test.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 encrypt.go create mode 100644 encrypt_test.go diff --git a/encrypt.go b/encrypt.go new file mode 100644 index 000000000..36bddd44c --- /dev/null +++ b/encrypt.go @@ -0,0 +1,51 @@ +package crypto + +import ( + "errors" + + . "github.com/tendermint/go-common" + "golang.org/x/crypto/nacl/secretbox" +) + +const nonceLen = 24 +const secretLen = 32 + +// secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) +// The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. +// NOTE: call crypto.MixEntropy() first. +func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte) { + if len(secret) != secretLen { + PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret))) + } + nonce := CRandBytes(nonceLen) + nonceArr := [nonceLen]byte{} + copy(nonceArr[:], nonce) + secretArr := [secretLen]byte{} + copy(secretArr[:], secret) + ciphertext = make([]byte, nonceLen+secretbox.Overhead+len(plaintext)) + copy(ciphertext, nonce) + secretbox.Seal(ciphertext[nonceLen:nonceLen], plaintext, &nonceArr, &secretArr) + return ciphertext +} + +// secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) +// The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. +func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error) { + if len(secret) != secretLen { + PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret))) + } + if len(ciphertext) <= secretbox.Overhead+nonceLen { + return nil, errors.New("Ciphertext is too short") + } + nonce := ciphertext[:nonceLen] + nonceArr := [nonceLen]byte{} + copy(nonceArr[:], nonce) + secretArr := [secretLen]byte{} + copy(secretArr[:], secret) + plaintext = make([]byte, len(ciphertext)-nonceLen-secretbox.Overhead) + _, ok := secretbox.Open(plaintext[:0], ciphertext[nonceLen:], &nonceArr, &secretArr) + if !ok { + return nil, errors.New("Ciphertext decryption failed") + } + return plaintext, nil +} diff --git a/encrypt_test.go b/encrypt_test.go new file mode 100644 index 000000000..f05c812b6 --- /dev/null +++ b/encrypt_test.go @@ -0,0 +1,51 @@ +package crypto + +import ( + "bytes" + "golang.org/x/crypto/bcrypt" + "testing" +) + +func TestSimple(t *testing.T) { + + MixEntropy([]byte("someentropy")) + + plaintext := []byte("sometext") + secret := []byte("somesecretoflengththirtytwo===32") + ciphertext := EncryptSymmetric(plaintext, secret) + + plaintext2, err := DecryptSymmetric(ciphertext, secret) + if err != nil { + t.Error(err) + } + + if !bytes.Equal(plaintext, plaintext2) { + t.Errorf("Decrypted plaintext was %X, expected %X", plaintext2, plaintext) + } + +} + +func TestSimpleWithKDF(t *testing.T) { + + MixEntropy([]byte("someentropy")) + + plaintext := []byte("sometext") + secretPass := []byte("somesecret") + secret, err := bcrypt.GenerateFromPassword(secretPass, 12) + if err != nil { + t.Error(err) + } + secret = Sha256(secret) + + ciphertext := EncryptSymmetric(plaintext, secret) + + plaintext2, err := DecryptSymmetric(ciphertext, secret) + if err != nil { + t.Error(err) + } + + if !bytes.Equal(plaintext, plaintext2) { + t.Errorf("Decrypted plaintext was %X, expected %X", plaintext2, plaintext) + } + +} From 185547efc1fe6e03fe22fcc2c00d001df8832071 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 13 Mar 2016 14:00:27 -0700 Subject: [PATCH 011/273] Add ascii armor support --- armor.go | 39 ++++++++++++++++++++++++++++ armor_test.go | 25 ++++++++++++++++++ encrypt.go => symmetric.go | 0 encrypt_test.go => symmetric_test.go | 3 ++- 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 armor.go create mode 100644 armor_test.go rename encrypt.go => symmetric.go (100%) rename encrypt_test.go => symmetric_test.go (99%) diff --git a/armor.go b/armor.go new file mode 100644 index 000000000..9343284e1 --- /dev/null +++ b/armor.go @@ -0,0 +1,39 @@ +package crypto + +import ( + "bytes" + "io/ioutil" + + . "github.com/tendermint/go-common" + "golang.org/x/crypto/openpgp/armor" +) + +func EncodeArmor(blockType string, headers map[string]string, data []byte) string { + buf := new(bytes.Buffer) + w, err := armor.Encode(buf, blockType, headers) + if err != nil { + PanicSanity("Error encoding ascii armor: " + err.Error()) + } + _, err = w.Write(data) + if err != nil { + PanicSanity("Error encoding ascii armor: " + err.Error()) + } + err = w.Close() + if err != nil { + PanicSanity("Error encoding ascii armor: " + err.Error()) + } + return string(buf.Bytes()) +} + +func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error) { + buf := bytes.NewBufferString(armorStr) + block, err := armor.Decode(buf) + if err != nil { + return "", nil, nil, err + } + data, err = ioutil.ReadAll(block.Body) + if err != nil { + return "", nil, nil, err + } + return block.Type, block.Header, data, nil +} diff --git a/armor_test.go b/armor_test.go new file mode 100644 index 000000000..3de37d7bc --- /dev/null +++ b/armor_test.go @@ -0,0 +1,25 @@ +package crypto + +import ( + "bytes" + "testing" +) + +func TestSimpleArmor(t *testing.T) { + blockType := "MINT TEST" + data := []byte("somedata") + armorStr := EncodeArmor(blockType, nil, data) + t.Log("Got armor: ", armorStr) + + // Decode armorStr and test for equivalence. + blockType2, _, data2, err := DecodeArmor(armorStr) + if err != nil { + t.Error(err) + } + if blockType != blockType2 { + t.Errorf("Expected block type %v but got %v", blockType, blockType2) + } + if !bytes.Equal(data, data2) { + t.Errorf("Expected data %X but got %X", data2, data) + } +} diff --git a/encrypt.go b/symmetric.go similarity index 100% rename from encrypt.go rename to symmetric.go diff --git a/encrypt_test.go b/symmetric_test.go similarity index 99% rename from encrypt_test.go rename to symmetric_test.go index f05c812b6..c8134742d 100644 --- a/encrypt_test.go +++ b/symmetric_test.go @@ -2,8 +2,9 @@ package crypto import ( "bytes" - "golang.org/x/crypto/bcrypt" "testing" + + "golang.org/x/crypto/bcrypt" ) func TestSimple(t *testing.T) { From 9a95e7b7a559340495c049a756804981b68a70a2 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 15 Mar 2016 11:11:54 -0700 Subject: [PATCH 012/273] Added Bytes() and *FromBytes() --- priv_key.go | 16 ++++++++++++++-- pub_key.go | 24 ++++++++++++------------ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/priv_key.go b/priv_key.go index 5e93fbe11..e9b43caa0 100644 --- a/priv_key.go +++ b/priv_key.go @@ -9,6 +9,7 @@ import ( // PrivKey is part of PrivAccount and state.PrivValidator. type PrivKey interface { + Bytes() []byte Sign(msg []byte) Signature PubKey() PubKey } @@ -24,11 +25,20 @@ var _ = wire.RegisterInterface( wire.ConcreteType{PrivKeyEd25519{}, PrivKeyTypeEd25519}, ) +func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { + err = wire.ReadBinaryBytes(privKeyBytes, &privKey) + return +} + //------------------------------------- // Implements PrivKey type PrivKeyEd25519 [64]byte +func (privKey PrivKeyEd25519) Bytes() []byte { + return wire.BinaryBytes(struct{ PrivKey }{privKey}) +} + func (key PrivKeyEd25519) Sign(msg []byte) Signature { privKeyBytes := [64]byte(key) signatureBytes := ed25519.Sign(&privKeyBytes, msg) @@ -69,8 +79,10 @@ func GenPrivKeyEd25519() PrivKeyEd25519 { return PrivKeyEd25519(*privKeyBytes) } -func GenPrivKeyEd25519FromSecret(secret string) PrivKeyEd25519 { - privKey32 := wire.BinarySha256(secret) // Not Ripemd160 because we want 32 bytes. +// NOTE: secret should be the output of a KDF like bcrypt, +// if it's derived from user input. +func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 { + privKey32 := Sha256(secret) // Not Ripemd160 because we want 32 bytes. privKeyBytes := new([64]byte) copy(privKeyBytes[:32], privKey32) ed25519.MakePublicKey(privKeyBytes) diff --git a/pub_key.go b/pub_key.go index 4cfe815ce..b9500741e 100644 --- a/pub_key.go +++ b/pub_key.go @@ -13,6 +13,7 @@ import ( // PubKey is part of Account and Validator. type PubKey interface { Address() []byte + Bytes() []byte KeyString() string VerifyBytes(msg []byte, sig Signature) bool Equals(PubKey) bool @@ -29,28 +30,27 @@ var _ = wire.RegisterInterface( wire.ConcreteType{PubKeyEd25519{}, PubKeyTypeEd25519}, ) +func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { + err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey) + return +} + //------------------------------------- // Implements PubKey type PubKeyEd25519 [32]byte -// TODO: Slicing the array gives us length prefixing but loses the type byte. -// Revisit if we add more pubkey types. -// For now, we artificially append the type byte in front to give us backwards -// compatibility for when the pubkey wasn't fixed length array func (pubKey PubKeyEd25519) Address() []byte { - w, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(pubKey[:], w, n, err) - if *err != nil { - PanicCrisis(*err) - } - // append type byte - encodedPubkey := append([]byte{1}, w.Bytes()...) + pubKeyBytes := pubKey.Bytes() hasher := ripemd160.New() - hasher.Write(encodedPubkey) // does not error + hasher.Write(pubKeyBytes) // does not error return hasher.Sum(nil) } +func (pubKey PubKeyEd25519) Bytes() []byte { + return wire.BinaryBytes(struct{ PubKey }{pubKey}) +} + // TODO: Consider returning a reason for failure, or logging a runtime type mismatch. func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { sig, ok := sig_.(SignatureEd25519) From 8152c18c355bb17e38292d9473e71d7998a72a43 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 15 Mar 2016 15:58:43 -0700 Subject: [PATCH 013/273] Revert Address() scheme change --- pub_key.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pub_key.go b/pub_key.go index b9500741e..6da13077f 100644 --- a/pub_key.go +++ b/pub_key.go @@ -41,9 +41,15 @@ func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { type PubKeyEd25519 [32]byte func (pubKey PubKeyEd25519) Address() []byte { - pubKeyBytes := pubKey.Bytes() + w, n, err := new(bytes.Buffer), new(int), new(error) + wire.WriteBinary(pubKey[:], w, n, err) + if *err != nil { + PanicCrisis(*err) + } + // append type byte + encodedPubkey := append([]byte{1}, w.Bytes()...) hasher := ripemd160.New() - hasher.Write(pubKeyBytes) // does not error + hasher.Write(encodedPubkey) // does not error return hasher.Sum(nil) } From eddde7f46aa3a02191c829149f83c09048c874cb Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 17 Mar 2016 20:37:30 -0700 Subject: [PATCH 014/273] Added customized bcrypt --- bcrypt/base64.go | 35 ++++++ bcrypt/bcrypt.go | 292 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 327 insertions(+) create mode 100644 bcrypt/base64.go create mode 100644 bcrypt/bcrypt.go diff --git a/bcrypt/base64.go b/bcrypt/base64.go new file mode 100644 index 000000000..fc3116090 --- /dev/null +++ b/bcrypt/base64.go @@ -0,0 +1,35 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bcrypt + +import "encoding/base64" + +const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +var bcEncoding = base64.NewEncoding(alphabet) + +func base64Encode(src []byte) []byte { + n := bcEncoding.EncodedLen(len(src)) + dst := make([]byte, n) + bcEncoding.Encode(dst, src) + for dst[n-1] == '=' { + n-- + } + return dst[:n] +} + +func base64Decode(src []byte) ([]byte, error) { + numOfEquals := 4 - (len(src) % 4) + for i := 0; i < numOfEquals; i++ { + src = append(src, '=') + } + + dst := make([]byte, bcEncoding.DecodedLen(len(src))) + n, err := bcEncoding.Decode(dst, src) + if err != nil { + return nil, err + } + return dst[:n], nil +} diff --git a/bcrypt/bcrypt.go b/bcrypt/bcrypt.go new file mode 100644 index 000000000..a6b4a2cf6 --- /dev/null +++ b/bcrypt/bcrypt.go @@ -0,0 +1,292 @@ +package bcrypt + +// MODIFIED BY TENDERMINT TO EXPOSE NONCE +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing +// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf + +// The code is a port of Provos and Mazières's C implementation. +import ( + "crypto/subtle" + "errors" + "fmt" + "strconv" + + "golang.org/x/crypto/blowfish" +) + +const ( + MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword + MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword + DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword +) + +// The error returned from CompareHashAndPassword when a password and hash do +// not match. +var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") + +// The error returned from CompareHashAndPassword when a hash is too short to +// be a bcrypt hash. +var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") + +// The error returned from CompareHashAndPassword when a hash was created with +// a bcrypt algorithm newer than this implementation. +type HashVersionTooNewError byte + +func (hv HashVersionTooNewError) Error() string { + return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) +} + +// The error returned from CompareHashAndPassword when a hash starts with something other than '$' +type InvalidHashPrefixError byte + +func (ih InvalidHashPrefixError) Error() string { + return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) +} + +type InvalidCostError int + +func (ic InvalidCostError) Error() string { + return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) +} + +const ( + majorVersion = '2' + minorVersion = 'a' + maxSaltSize = 16 + maxCryptedHashSize = 23 + encodedSaltSize = 22 + encodedHashSize = 31 + minHashSize = 59 +) + +// magicCipherData is an IV for the 64 Blowfish encryption calls in +// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. +var magicCipherData = []byte{ + 0x4f, 0x72, 0x70, 0x68, + 0x65, 0x61, 0x6e, 0x42, + 0x65, 0x68, 0x6f, 0x6c, + 0x64, 0x65, 0x72, 0x53, + 0x63, 0x72, 0x79, 0x44, + 0x6f, 0x75, 0x62, 0x74, +} + +type hashed struct { + hash []byte + salt []byte + cost int // allowed range is MinCost to MaxCost + major byte + minor byte +} + +// GenerateFromPassword returns the bcrypt hash of the password at the given +// cost. If the cost given is less than MinCost, the cost will be set to +// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, +// to compare the returned hashed password with its cleartext version. +func GenerateFromPassword(salt []byte, password []byte, cost int) ([]byte, error) { + if len(salt) != maxSaltSize { + return nil, fmt.Errorf("Salt len must be %v", maxSaltSize) + } + p, err := newFromPassword(salt, password, cost) + if err != nil { + return nil, err + } + return p.Hash(), nil +} + +// CompareHashAndPassword compares a bcrypt hashed password with its possible +// plaintext equivalent. Returns nil on success, or an error on failure. +func CompareHashAndPassword(hashedPassword, password []byte) error { + p, err := newFromHash(hashedPassword) + if err != nil { + return err + } + + otherHash, err := bcrypt(password, p.cost, p.salt) + if err != nil { + return err + } + + otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} + if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { + return nil + } + + return ErrMismatchedHashAndPassword +} + +// Cost returns the hashing cost used to create the given hashed +// password. When, in the future, the hashing cost of a password system needs +// to be increased in order to adjust for greater computational power, this +// function allows one to establish which passwords need to be updated. +func Cost(hashedPassword []byte) (int, error) { + p, err := newFromHash(hashedPassword) + if err != nil { + return 0, err + } + return p.cost, nil +} + +func newFromPassword(salt []byte, password []byte, cost int) (*hashed, error) { + if cost < MinCost { + cost = DefaultCost + } + p := new(hashed) + p.major = majorVersion + p.minor = minorVersion + + err := checkCost(cost) + if err != nil { + return nil, err + } + p.cost = cost + + p.salt = base64Encode(salt) + hash, err := bcrypt(password, p.cost, p.salt) + if err != nil { + return nil, err + } + p.hash = hash + return p, err +} + +func newFromHash(hashedSecret []byte) (*hashed, error) { + if len(hashedSecret) < minHashSize { + return nil, ErrHashTooShort + } + p := new(hashed) + n, err := p.decodeVersion(hashedSecret) + if err != nil { + return nil, err + } + hashedSecret = hashedSecret[n:] + n, err = p.decodeCost(hashedSecret) + if err != nil { + return nil, err + } + hashedSecret = hashedSecret[n:] + + // The "+2" is here because we'll have to append at most 2 '=' to the salt + // when base64 decoding it in expensiveBlowfishSetup(). + p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) + copy(p.salt, hashedSecret[:encodedSaltSize]) + + hashedSecret = hashedSecret[encodedSaltSize:] + p.hash = make([]byte, len(hashedSecret)) + copy(p.hash, hashedSecret) + + return p, nil +} + +func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { + cipherData := make([]byte, len(magicCipherData)) + copy(cipherData, magicCipherData) + + c, err := expensiveBlowfishSetup(password, uint32(cost), salt) + if err != nil { + return nil, err + } + + for i := 0; i < 24; i += 8 { + for j := 0; j < 64; j++ { + c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) + } + } + + // Bug compatibility with C bcrypt implementations. We only encode 23 of + // the 24 bytes encrypted. + hsh := base64Encode(cipherData[:maxCryptedHashSize]) + return hsh, nil +} + +func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { + + csalt, err := base64Decode(salt) + if err != nil { + return nil, err + } + + // Bug compatibility with C bcrypt implementations. They use the trailing + // NULL in the key string during expansion. + ckey := append(key, 0) + + c, err := blowfish.NewSaltedCipher(ckey, csalt) + if err != nil { + return nil, err + } + + var i, rounds uint64 + rounds = 1 << cost + for i = 0; i < rounds; i++ { + blowfish.ExpandKey(ckey, c) + blowfish.ExpandKey(csalt, c) + } + + return c, nil +} + +func (p *hashed) Hash() []byte { + arr := make([]byte, 60) + arr[0] = '$' + arr[1] = p.major + n := 2 + if p.minor != 0 { + arr[2] = p.minor + n = 3 + } + arr[n] = '$' + n += 1 + copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) + n += 2 + arr[n] = '$' + n += 1 + copy(arr[n:], p.salt) + n += encodedSaltSize + copy(arr[n:], p.hash) + n += encodedHashSize + return arr[:n] +} + +func (p *hashed) decodeVersion(sbytes []byte) (int, error) { + if sbytes[0] != '$' { + return -1, InvalidHashPrefixError(sbytes[0]) + } + if sbytes[1] > majorVersion { + return -1, HashVersionTooNewError(sbytes[1]) + } + p.major = sbytes[1] + n := 3 + if sbytes[2] != '$' { + p.minor = sbytes[2] + n++ + } + return n, nil +} + +// sbytes should begin where decodeVersion left off. +func (p *hashed) decodeCost(sbytes []byte) (int, error) { + cost, err := strconv.Atoi(string(sbytes[0:2])) + if err != nil { + return -1, err + } + err = checkCost(cost) + if err != nil { + return -1, err + } + p.cost = cost + return 3, nil +} + +func (p *hashed) String() string { + return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) +} + +func checkCost(cost int) error { + if cost < MinCost || cost > MaxCost { + return InvalidCostError(cost) + } + return nil +} From 3f0d9b3f29f30e5d0cbc2cef04fa45e5a606c622 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 22 Mar 2016 15:21:18 -0700 Subject: [PATCH 015/273] Signature bytes --- signature.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/signature.go b/signature.go index 959258091..8eafab7cf 100644 --- a/signature.go +++ b/signature.go @@ -9,6 +9,7 @@ import ( // Signature is a part of Txs and consensus Votes. type Signature interface { + Bytes() []byte IsZero() bool String() string } @@ -29,6 +30,10 @@ var _ = wire.RegisterInterface( // Implements Signature type SignatureEd25519 [64]byte +func (sig SignatureEd25519) Bytes() []byte { + return wire.BinaryBytes(struct{ Signature }{sig}) +} + func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } From 8b34fd2e51ab2b5c368b81e4aa82f7bd2a0b5381 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 19 Apr 2016 01:02:31 -0700 Subject: [PATCH 016/273] Add secp256k1 support --- priv_key.go | 73 +++++++++++++++++++++++++++++++++++++++++++---- pub_key.go | 64 +++++++++++++++++++++++++++++++++++++++-- signature.go | 17 ++++++++++- signature_test.go | 59 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 202 insertions(+), 11 deletions(-) diff --git a/priv_key.go b/priv_key.go index e9b43caa0..2806e24f7 100644 --- a/priv_key.go +++ b/priv_key.go @@ -1,6 +1,7 @@ package crypto import ( + secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" . "github.com/tendermint/go-common" @@ -16,13 +17,15 @@ type PrivKey interface { // Types of PrivKey implementations const ( - PrivKeyTypeEd25519 = byte(0x01) + PrivKeyTypeEd25519 = byte(0x01) + PrivKeyTypeSecp256k1 = byte(0x02) ) // for wire.readReflect var _ = wire.RegisterInterface( struct{ PrivKey }{}, wire.ConcreteType{PrivKeyEd25519{}, PrivKeyTypeEd25519}, + wire.ConcreteType{PrivKeySecp256k1{}, PrivKeyTypeSecp256k1}, ) func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { @@ -39,8 +42,8 @@ func (privKey PrivKeyEd25519) Bytes() []byte { return wire.BinaryBytes(struct{ PrivKey }{privKey}) } -func (key PrivKeyEd25519) Sign(msg []byte) Signature { - privKeyBytes := [64]byte(key) +func (privKey PrivKeyEd25519) Sign(msg []byte) Signature { + privKeyBytes := [64]byte(privKey) signatureBytes := ed25519.Sign(&privKeyBytes, msg) return SignatureEd25519(*signatureBytes) } @@ -62,11 +65,11 @@ func (privKey PrivKeyEd25519) String() string { } // Deterministically generates new priv-key bytes from key. -func (key PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { +func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { newBytes := wire.BinarySha256(struct { PrivKey [64]byte Index int - }{key, index}) + }{privKey, index}) var newKey [64]byte copy(newKey[:], newBytes) return PrivKeyEd25519(newKey) @@ -88,3 +91,63 @@ func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 { ed25519.MakePublicKey(privKeyBytes) return PrivKeyEd25519(*privKeyBytes) } + +//------------------------------------- + +// Implements PrivKey +type PrivKeySecp256k1 [32]byte + +func (privKey PrivKeySecp256k1) Bytes() []byte { + return wire.BinaryBytes(struct{ PrivKey }{privKey}) +} + +func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature { + priv__, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) + sig__, err := priv__.Sign(Sha256(msg)) + if err != nil { + PanicSanity(err) + } + return SignatureSecp256k1(sig__.Serialize()) +} + +func (privKey PrivKeySecp256k1) PubKey() PubKey { + _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) + pub := [65]byte{} + copy(pub[:], pub__.SerializeUncompressed()) + return PubKeySecp256k1(pub) +} + +func (privKey PrivKeySecp256k1) String() string { + return Fmt("PrivKeySecp256k1{*****}") +} + +/* +// Deterministically generates new priv-key bytes from key. +func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 { + newBytes := wire.BinarySha256(struct { + PrivKey [64]byte + Index int + }{key, index}) + var newKey [64]byte + copy(newKey[:], newBytes) + return PrivKeySecp256k1(newKey) +} +*/ + +func GenPrivKeySecp256k1() PrivKeySecp256k1 { + privKeyBytes := [32]byte{} + copy(privKeyBytes[:], CRandBytes(32)) + priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKeyBytes[:]) + copy(privKeyBytes[:], priv.Serialize()) + return PrivKeySecp256k1(privKeyBytes) +} + +// NOTE: secret should be the output of a KDF like bcrypt, +// if it's derived from user input. +func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1 { + privKey32 := Sha256(secret) // Not Ripemd160 because we want 32 bytes. + priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey32) + privKeyBytes := [32]byte{} + copy(privKeyBytes[:], priv.Serialize()) + return PrivKeySecp256k1(privKeyBytes) +} diff --git a/pub_key.go b/pub_key.go index 6da13077f..1162a1ef3 100644 --- a/pub_key.go +++ b/pub_key.go @@ -3,6 +3,7 @@ package crypto import ( "bytes" + secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" . "github.com/tendermint/go-common" @@ -21,13 +22,15 @@ type PubKey interface { // Types of PubKey implementations const ( - PubKeyTypeEd25519 = byte(0x01) + PubKeyTypeEd25519 = byte(0x01) + PubKeyTypeSecp256k1 = byte(0x02) ) // for wire.readReflect var _ = wire.RegisterInterface( struct{ PubKey }{}, wire.ConcreteType{PubKeyEd25519{}, PubKeyTypeEd25519}, + wire.ConcreteType{PubKeySecp256k1{}, PubKeyTypeSecp256k1}, ) func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { @@ -47,7 +50,7 @@ func (pubKey PubKeyEd25519) Address() []byte { PanicCrisis(*err) } // append type byte - encodedPubkey := append([]byte{1}, w.Bytes()...) + encodedPubkey := append([]byte{PubKeyTypeEd25519}, w.Bytes()...) hasher := ripemd160.New() hasher.Write(encodedPubkey) // does not error return hasher.Sum(nil) @@ -57,7 +60,6 @@ func (pubKey PubKeyEd25519) Bytes() []byte { return wire.BinaryBytes(struct{ PubKey }{pubKey}) } -// TODO: Consider returning a reason for failure, or logging a runtime type mismatch. func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { sig, ok := sig_.(SignatureEd25519) if !ok { @@ -96,3 +98,59 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool { return false } } + +//------------------------------------- + +// Implements PubKey +type PubKeySecp256k1 [65]byte + +func (pubKey PubKeySecp256k1) Address() []byte { + w, n, err := new(bytes.Buffer), new(int), new(error) + wire.WriteBinary(pubKey[:], w, n, err) + if *err != nil { + PanicCrisis(*err) + } + // append type byte + encodedPubkey := append([]byte{PubKeyTypeSecp256k1}, w.Bytes()...) + hasher := ripemd160.New() + hasher.Write(encodedPubkey) // does not error + return hasher.Sum(nil) +} + +func (pubKey PubKeySecp256k1) Bytes() []byte { + return wire.BinaryBytes(struct{ PubKey }{pubKey}) +} + +func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { + pub__, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256()) + if err != nil { + return false + } + sig, ok := sig_.(SignatureSecp256k1) + if !ok { + return false + } + sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256()) + if err != nil { + return false + } + return sig__.Verify(Sha256(msg), pub__) +} + +func (pubKey PubKeySecp256k1) String() string { + return Fmt("PubKeySecp256k1{%X}", pubKey[:]) +} + +// Must return the full bytes in hex. +// Used for map keying, etc. +func (pubKey PubKeySecp256k1) KeyString() string { + return Fmt("%X", pubKey[:]) +} + +func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { + if otherEd, ok := other.(PubKeySecp256k1); ok { + return bytes.Equal(pubKey[:], otherEd[:]) + } else { + return false + } +} diff --git a/signature.go b/signature.go index 8eafab7cf..e4921ccf7 100644 --- a/signature.go +++ b/signature.go @@ -16,13 +16,15 @@ type Signature interface { // Types of Signature implementations const ( - SignatureTypeEd25519 = byte(0x01) + SignatureTypeEd25519 = byte(0x01) + SignatureTypeSecp256k1 = byte(0x02) ) // for wire.readReflect var _ = wire.RegisterInterface( struct{ Signature }{}, wire.ConcreteType{SignatureEd25519{}, SignatureTypeEd25519}, + wire.ConcreteType{SignatureSecp256k1{}, SignatureTypeSecp256k1}, ) //------------------------------------- @@ -37,3 +39,16 @@ func (sig SignatureEd25519) Bytes() []byte { func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } + +//------------------------------------- + +// Implements Signature +type SignatureSecp256k1 []byte + +func (sig SignatureSecp256k1) Bytes() []byte { + return wire.BinaryBytes(struct{ Signature }{sig}) +} + +func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } + +func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } diff --git a/signature_test.go b/signature_test.go index e4e72e48d..88c490f39 100644 --- a/signature_test.go +++ b/signature_test.go @@ -8,7 +8,7 @@ import ( "github.com/tendermint/go-wire" ) -func TestSignAndValidate(t *testing.T) { +func TestSignAndValidateEd25519(t *testing.T) { privKey := GenPrivKeyEd25519() pubKey := privKey.PubKey() @@ -32,7 +32,31 @@ func TestSignAndValidate(t *testing.T) { } } -func TestBinaryDecode(t *testing.T) { +func TestSignAndValidateSecp256k1(t *testing.T) { + + privKey := GenPrivKeySecp256k1() + pubKey := privKey.PubKey() + + msg := CRandBytes(128) + sig := privKey.Sign(msg) + t.Logf("msg: %X, sig: %X", msg, sig) + + // Test the signature + if !pubKey.VerifyBytes(msg, sig) { + t.Errorf("Account message signature verification failed") + } + + // Mutate the signature, just one bit. + sigEd := sig.(SignatureSecp256k1) + sigEd[0] ^= byte(0x01) + sig = Signature(sigEd) + + if pubKey.VerifyBytes(msg, sig) { + t.Errorf("Account message signature verification should have failed but passed instead") + } +} + +func TestBinaryDecodeEd25519(t *testing.T) { privKey := GenPrivKeyEd25519() pubKey := privKey.PubKey() @@ -66,3 +90,34 @@ func TestBinaryDecode(t *testing.T) { t.Errorf("Account message signature verification failed") } } + +func TestBinaryDecodeSecp256k1(t *testing.T) { + + privKey := GenPrivKeySecp256k1() + pubKey := privKey.PubKey() + + msg := CRandBytes(128) + sig := privKey.Sign(msg) + t.Logf("msg: %X, sig: %X", msg, sig) + + buf, n, err := new(bytes.Buffer), new(int), new(error) + wire.WriteBinary(struct{ Signature }{sig}, buf, n, err) + if *err != nil { + t.Fatalf("Failed to write Signature: %v", err) + } + + if buf.Bytes()[0] != SignatureTypeSecp256k1 { + t.Fatalf("Unexpected signature type byte") + } + + sigStruct := struct{ Signature }{} + sig2 := wire.ReadBinary(sigStruct, buf, 0, n, err) + if *err != nil { + t.Fatalf("Failed to read Signature: %v", err) + } + + // Test the signature + if !pubKey.VerifyBytes(msg, sig2.(struct{ Signature }).Signature.(SignatureSecp256k1)) { + t.Errorf("Account message signature verification failed") + } +} From d57d5ff3c925149e62f3a3c3f6ecaf4c8250d678 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 19 Apr 2016 01:26:40 -0700 Subject: [PATCH 017/273] PrivKey.Equals --- priv_key.go | 19 +++++++++++++++++++ pub_key.go | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/priv_key.go b/priv_key.go index 2806e24f7..42f932ba1 100644 --- a/priv_key.go +++ b/priv_key.go @@ -1,6 +1,8 @@ package crypto import ( + "bytes" + secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" @@ -13,6 +15,7 @@ type PrivKey interface { Bytes() []byte Sign(msg []byte) Signature PubKey() PubKey + Equals(PrivKey) bool } // Types of PrivKey implementations @@ -53,6 +56,14 @@ func (privKey PrivKeyEd25519) PubKey() PubKey { return PubKeyEd25519(*ed25519.MakePublicKey(&privKeyBytes)) } +func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { + if otherEd, ok := other.(PrivKeyEd25519); ok { + return bytes.Equal(privKey[:], otherEd[:]) + } else { + return false + } +} + func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { keyCurve25519 := new([32]byte) privKeyBytes := [64]byte(privKey) @@ -117,6 +128,14 @@ func (privKey PrivKeySecp256k1) PubKey() PubKey { return PubKeySecp256k1(pub) } +func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { + if otherSecp, ok := other.(PrivKeySecp256k1); ok { + return bytes.Equal(privKey[:], otherSecp[:]) + } else { + return false + } +} + func (privKey PrivKeySecp256k1) String() string { return Fmt("PrivKeySecp256k1{*****}") } diff --git a/pub_key.go b/pub_key.go index 1162a1ef3..de56c8122 100644 --- a/pub_key.go +++ b/pub_key.go @@ -148,8 +148,8 @@ func (pubKey PubKeySecp256k1) KeyString() string { } func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { - if otherEd, ok := other.(PubKeySecp256k1); ok { - return bytes.Equal(pubKey[:], otherEd[:]) + if otherSecp, ok := other.(PubKeySecp256k1); ok { + return bytes.Equal(pubKey[:], otherSecp[:]) } else { return false } From c121163635a0a36ddfa242c737e13dbab5edb587 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 19 Apr 2016 08:49:41 -0700 Subject: [PATCH 018/273] ReadSignature* --- signature.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/signature.go b/signature.go index e4921ccf7..40f269f34 100644 --- a/signature.go +++ b/signature.go @@ -40,6 +40,15 @@ func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } +func ReadSignatureEd25519(bz []byte) (SignatureEd25519, error) { + sig := struct{ Signature }{} + err := wire.ReadBinaryBytes(bz, &sig) + if err != nil { + return SignatureEd25519{}, err + } + return sig.Signature.(SignatureEd25519), nil +} + //------------------------------------- // Implements Signature @@ -52,3 +61,12 @@ func (sig SignatureSecp256k1) Bytes() []byte { func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } + +func ReadSignatureSecp256k1(bz []byte) (SignatureSecp256k1, error) { + sig := struct{ Signature }{} + err := wire.ReadBinaryBytes(bz, &sig) + if err != nil { + return nil, err + } + return sig.Signature.(SignatureSecp256k1), nil +} From 7e767e95485d0907a694057103ebc018660a6573 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 20 Apr 2016 08:46:07 -0700 Subject: [PATCH 019/273] Secp256k1 pubkeys are 64 bytes. Strip btcec prefix byte --- priv_key.go | 4 ++-- pub_key.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/priv_key.go b/priv_key.go index 42f932ba1..8b7dc117f 100644 --- a/priv_key.go +++ b/priv_key.go @@ -123,8 +123,8 @@ func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature { func (privKey PrivKeySecp256k1) PubKey() PubKey { _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) - pub := [65]byte{} - copy(pub[:], pub__.SerializeUncompressed()) + pub := [64]byte{} + copy(pub[:], pub__.SerializeUncompressed()[1:]) return PubKeySecp256k1(pub) } diff --git a/pub_key.go b/pub_key.go index de56c8122..a3a259795 100644 --- a/pub_key.go +++ b/pub_key.go @@ -102,7 +102,7 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool { //------------------------------------- // Implements PubKey -type PubKeySecp256k1 [65]byte +type PubKeySecp256k1 [64]byte func (pubKey PubKeySecp256k1) Address() []byte { w, n, err := new(bytes.Buffer), new(int), new(error) @@ -122,7 +122,7 @@ func (pubKey PubKeySecp256k1) Bytes() []byte { } func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { - pub__, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256()) + pub__, err := secp256k1.ParsePubKey(append([]byte{0x04}, pubKey[:]...), secp256k1.S256()) if err != nil { return false } From 41cfb7b677f4e16cdfd22b6ce0946c89919fbc7b Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Thu, 21 Apr 2016 18:05:15 -0700 Subject: [PATCH 020/273] Remove ReadSignature* methods --- signature.go | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/signature.go b/signature.go index 40f269f34..bb4a2e327 100644 --- a/signature.go +++ b/signature.go @@ -27,6 +27,11 @@ var _ = wire.RegisterInterface( wire.ConcreteType{SignatureSecp256k1{}, SignatureTypeSecp256k1}, ) +func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { + err = wire.ReadBinaryBytes(sigBytes, &sig) + return +} + //------------------------------------- // Implements Signature @@ -40,15 +45,6 @@ func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } -func ReadSignatureEd25519(bz []byte) (SignatureEd25519, error) { - sig := struct{ Signature }{} - err := wire.ReadBinaryBytes(bz, &sig) - if err != nil { - return SignatureEd25519{}, err - } - return sig.Signature.(SignatureEd25519), nil -} - //------------------------------------- // Implements Signature @@ -61,12 +57,3 @@ func (sig SignatureSecp256k1) Bytes() []byte { func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } - -func ReadSignatureSecp256k1(bz []byte) (SignatureSecp256k1, error) { - sig := struct{ Signature }{} - err := wire.ReadBinaryBytes(bz, &sig) - if err != nil { - return nil, err - } - return sig.Signature.(SignatureSecp256k1), nil -} From 4b11d62bdb324027ea01554e5767b71174680ba0 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 24 Jul 2016 13:21:57 -0700 Subject: [PATCH 021/273] Add Signature.Equals --- signature.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/signature.go b/signature.go index bb4a2e327..b0049da8d 100644 --- a/signature.go +++ b/signature.go @@ -1,6 +1,7 @@ package crypto import ( + "bytes" "fmt" . "github.com/tendermint/go-common" @@ -12,6 +13,7 @@ type Signature interface { Bytes() []byte IsZero() bool String() string + Equals(Signature) bool } // Types of Signature implementations @@ -45,6 +47,14 @@ func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } +func (sig SignatureEd25519) Equals(other Signature) bool { + if otherEd, ok := other.(SignatureEd25519); ok { + return bytes.Equal(sig[:], otherEd[:]) + } else { + return false + } +} + //------------------------------------- // Implements Signature @@ -57,3 +67,11 @@ func (sig SignatureSecp256k1) Bytes() []byte { func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } + +func (sig SignatureSecp256k1) Equals(other Signature) bool { + if otherEd, ok := other.(SignatureSecp256k1); ok { + return bytes.Equal(sig[:], otherEd[:]) + } else { + return false + } +} From e6d35ee6416f0e234ae39ce01aab5922b7ff3b5d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 22 Feb 2017 23:15:10 +0100 Subject: [PATCH 022/273] Add structs for go-data support --- Makefile | 9 +++++++++ priv_key.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++------ pub_key.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++------ signature.go | 47 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 149 insertions(+), 19 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..0cd05448a --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +.PHONY: docs +REPO:=github.com/tendermint/go-crypto + +docs: + @go get github.com/davecheney/godoc2md + godoc2md $(REPO) > README.md + +test: + go test ./... diff --git a/priv_key.go b/priv_key.go index 8b7dc117f..ac4760c7c 100644 --- a/priv_key.go +++ b/priv_key.go @@ -7,6 +7,7 @@ import ( "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" . "github.com/tendermint/go-common" + data "github.com/tendermint/go-data" "github.com/tendermint/go-wire" ) @@ -22,14 +23,35 @@ type PrivKey interface { const ( PrivKeyTypeEd25519 = byte(0x01) PrivKeyTypeSecp256k1 = byte(0x02) + PrivKeyNameEd25519 = "ed25519" + PrivKeyNameSecp256k1 = "secp256k1" ) -// for wire.readReflect -var _ = wire.RegisterInterface( - struct{ PrivKey }{}, - wire.ConcreteType{PrivKeyEd25519{}, PrivKeyTypeEd25519}, - wire.ConcreteType{PrivKeySecp256k1{}, PrivKeyTypeSecp256k1}, -) +var privKeyMapper data.Mapper + +// register both private key types with go-data (and thus go-wire) +func init() { + privKeyMapper = data.NewMapper(PrivKeyS{}). + RegisterInterface(PrivKeyEd25519{}, PrivKeyNameEd25519, PrivKeyTypeEd25519). + RegisterInterface(PrivKeySecp256k1{}, PrivKeyNameSecp256k1, PrivKeyTypeSecp256k1) +} + +// PrivKeyS add json serialization to PrivKey +type PrivKeyS struct { + PrivKey +} + +func (p PrivKeyS) MarshalJSON() ([]byte, error) { + return privKeyMapper.ToJSON(p.PrivKey) +} + +func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error) { + parsed, err := privKeyMapper.FromJSON(data) + if err == nil { + p.PrivKey = parsed.(PrivKey) + } + return +} func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { err = wire.ReadBinaryBytes(privKeyBytes, &privKey) @@ -64,6 +86,17 @@ func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { } } +func (p PrivKeyEd25519) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { keyCurve25519 := new([32]byte) privKeyBytes := [64]byte(privKey) @@ -136,6 +169,17 @@ func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { } } +func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + func (privKey PrivKeySecp256k1) String() string { return Fmt("PrivKeySecp256k1{*****}") } diff --git a/pub_key.go b/pub_key.go index a3a259795..54d1173eb 100644 --- a/pub_key.go +++ b/pub_key.go @@ -7,6 +7,7 @@ import ( "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" . "github.com/tendermint/go-common" + data "github.com/tendermint/go-data" "github.com/tendermint/go-wire" "golang.org/x/crypto/ripemd160" ) @@ -24,14 +25,35 @@ type PubKey interface { const ( PubKeyTypeEd25519 = byte(0x01) PubKeyTypeSecp256k1 = byte(0x02) + PubKeyNameEd25519 = "ed25519" + PubKeyNameSecp256k1 = "secp256k1" ) -// for wire.readReflect -var _ = wire.RegisterInterface( - struct{ PubKey }{}, - wire.ConcreteType{PubKeyEd25519{}, PubKeyTypeEd25519}, - wire.ConcreteType{PubKeySecp256k1{}, PubKeyTypeSecp256k1}, -) +var pubKeyMapper data.Mapper + +// register both public key types with go-data (and thus go-wire) +func init() { + pubKeyMapper = data.NewMapper(PubKeyS{}). + RegisterInterface(PubKeyEd25519{}, PubKeyNameEd25519, PubKeyTypeEd25519). + RegisterInterface(PubKeySecp256k1{}, PubKeyNameSecp256k1, PubKeyTypeSecp256k1) +} + +// PubKeyS add json serialization to PubKey +type PubKeyS struct { + PubKey +} + +func (p PubKeyS) MarshalJSON() ([]byte, error) { + return pubKeyMapper.ToJSON(p.PubKey) +} + +func (p *PubKeyS) UnmarshalJSON(data []byte) (err error) { + parsed, err := pubKeyMapper.FromJSON(data) + if err == nil { + p.PubKey = parsed.(PubKey) + } + return +} func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey) @@ -70,6 +92,17 @@ func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { return ed25519.Verify(&pubKeyBytes, msg, &sigBytes) } +func (p PubKeyEd25519) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + // For use with golang/crypto/nacl/box // If error, returns nil. func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte { @@ -137,6 +170,17 @@ func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { return sig__.Verify(Sha256(msg), pub__) } +func (p PubKeySecp256k1) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + func (pubKey PubKeySecp256k1) String() string { return Fmt("PubKeySecp256k1{%X}", pubKey[:]) } diff --git a/signature.go b/signature.go index b0049da8d..3960088bd 100644 --- a/signature.go +++ b/signature.go @@ -5,6 +5,7 @@ import ( "fmt" . "github.com/tendermint/go-common" + data "github.com/tendermint/go-data" "github.com/tendermint/go-wire" ) @@ -20,14 +21,35 @@ type Signature interface { const ( SignatureTypeEd25519 = byte(0x01) SignatureTypeSecp256k1 = byte(0x02) + SignatureNameEd25519 = "ed25519" + SignatureNameSecp256k1 = "secp256k1" ) -// for wire.readReflect -var _ = wire.RegisterInterface( - struct{ Signature }{}, - wire.ConcreteType{SignatureEd25519{}, SignatureTypeEd25519}, - wire.ConcreteType{SignatureSecp256k1{}, SignatureTypeSecp256k1}, -) +var sigMapper data.Mapper + +// register both public key types with go-data (and thus go-wire) +func init() { + sigMapper = data.NewMapper(SignatureS{}). + RegisterInterface(SignatureEd25519{}, SignatureNameEd25519, SignatureTypeEd25519). + RegisterInterface(SignatureSecp256k1{}, SignatureNameSecp256k1, SignatureTypeSecp256k1) +} + +// SignatureS add json serialization to Signature +type SignatureS struct { + Signature +} + +func (p SignatureS) MarshalJSON() ([]byte, error) { + return sigMapper.ToJSON(p.Signature) +} + +func (p *SignatureS) UnmarshalJSON(data []byte) (err error) { + parsed, err := sigMapper.FromJSON(data) + if err == nil { + p.Signature = parsed.(Signature) + } + return +} func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { err = wire.ReadBinaryBytes(sigBytes, &sig) @@ -55,10 +77,21 @@ func (sig SignatureEd25519) Equals(other Signature) bool { } } +func (p SignatureEd25519) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p[:]) +} + +func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error { + var ref []byte + err := data.Encoder.Unmarshal(&ref, enc) + copy(p[:], ref) + return err +} + //------------------------------------- // Implements Signature -type SignatureSecp256k1 []byte +type SignatureSecp256k1 data.Bytes func (sig SignatureSecp256k1) Bytes() []byte { return wire.BinaryBytes(struct{ Signature }{sig}) From 1bc1947e3f94e628778a38d36256bce8a66a6779 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 22 Feb 2017 23:43:26 +0100 Subject: [PATCH 023/273] First tests of go-data encoding --- pub_key.go | 17 +++++-- signature.go | 9 +++- signature_test.go | 121 ++++++++++++++++++++++------------------------ 3 files changed, 80 insertions(+), 67 deletions(-) diff --git a/pub_key.go b/pub_key.go index 54d1173eb..0c7f4663e 100644 --- a/pub_key.go +++ b/pub_key.go @@ -83,6 +83,11 @@ func (pubKey PubKeyEd25519) Bytes() []byte { } func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { + // unwrap if needed + if wrap, ok := sig_.(SignatureS); ok { + sig_ = wrap.Signature + } + // make sure we use the same algorithm to sign sig, ok := sig_.(SignatureEd25519) if !ok { return false @@ -155,14 +160,20 @@ func (pubKey PubKeySecp256k1) Bytes() []byte { } func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { - pub__, err := secp256k1.ParsePubKey(append([]byte{0x04}, pubKey[:]...), secp256k1.S256()) - if err != nil { - return false + // unwrap if needed + if wrap, ok := sig_.(SignatureS); ok { + sig_ = wrap.Signature } + // and assert same algorithm to sign and verify sig, ok := sig_.(SignatureSecp256k1) if !ok { return false } + + pub__, err := secp256k1.ParsePubKey(append([]byte{0x04}, pubKey[:]...), secp256k1.S256()) + if err != nil { + return false + } sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256()) if err != nil { return false diff --git a/signature.go b/signature.go index 3960088bd..fcef20a43 100644 --- a/signature.go +++ b/signature.go @@ -91,7 +91,7 @@ func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error { //------------------------------------- // Implements Signature -type SignatureSecp256k1 data.Bytes +type SignatureSecp256k1 []byte func (sig SignatureSecp256k1) Bytes() []byte { return wire.BinaryBytes(struct{ Signature }{sig}) @@ -108,3 +108,10 @@ func (sig SignatureSecp256k1) Equals(other Signature) bool { return false } } +func (p SignatureSecp256k1) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(p) +} + +func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error { + return data.Encoder.Unmarshal((*[]byte)(p), enc) +} diff --git a/signature_test.go b/signature_test.go index 88c490f39..ac631eac5 100644 --- a/signature_test.go +++ b/signature_test.go @@ -1,11 +1,14 @@ package crypto import ( - "bytes" + "fmt" + "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/tendermint/ed25519" - "github.com/tendermint/go-wire" + data "github.com/tendermint/go-data" ) func TestSignAndValidateEd25519(t *testing.T) { @@ -56,68 +59,60 @@ func TestSignAndValidateSecp256k1(t *testing.T) { } } -func TestBinaryDecodeEd25519(t *testing.T) { - - privKey := GenPrivKeyEd25519() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) - - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(struct{ Signature }{sig}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write Signature: %v", err) - } - - if len(buf.Bytes()) != ed25519.SignatureSize+1 { - // 1 byte TypeByte, 64 bytes signature bytes - t.Fatalf("Unexpected signature write size: %v", len(buf.Bytes())) - } - if buf.Bytes()[0] != SignatureTypeEd25519 { - t.Fatalf("Unexpected signature type byte") - } - - sigStruct := struct{ Signature }{} - sig2 := wire.ReadBinary(sigStruct, buf, 0, n, err) - if *err != nil { - t.Fatalf("Failed to read Signature: %v", err) - } - - // Test the signature - if !pubKey.VerifyBytes(msg, sig2.(struct{ Signature }).Signature.(SignatureEd25519)) { - t.Errorf("Account message signature verification failed") +func TestSignatureEncodings(t *testing.T) { + cases := []struct { + privKey PrivKeyS + sigSize int + sigType byte + sigName string + }{ + { + privKey: PrivKeyS{GenPrivKeyEd25519()}, + sigSize: ed25519.SignatureSize, + sigType: SignatureTypeEd25519, + sigName: SignatureNameEd25519, + }, + { + privKey: PrivKeyS{GenPrivKeySecp256k1()}, + sigSize: 0, // unknown + sigType: SignatureTypeSecp256k1, + sigName: SignatureNameSecp256k1, + }, } -} - -func TestBinaryDecodeSecp256k1(t *testing.T) { - - privKey := GenPrivKeySecp256k1() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) - buf, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(struct{ Signature }{sig}, buf, n, err) - if *err != nil { - t.Fatalf("Failed to write Signature: %v", err) - } - - if buf.Bytes()[0] != SignatureTypeSecp256k1 { - t.Fatalf("Unexpected signature type byte") - } - - sigStruct := struct{ Signature }{} - sig2 := wire.ReadBinary(sigStruct, buf, 0, n, err) - if *err != nil { - t.Fatalf("Failed to read Signature: %v", err) - } - - // Test the signature - if !pubKey.VerifyBytes(msg, sig2.(struct{ Signature }).Signature.(SignatureSecp256k1)) { - t.Errorf("Account message signature verification failed") + for _, tc := range cases { + // note we embed them from the beginning.... + pubKey := PubKeyS{tc.privKey.PubKey()} + + msg := CRandBytes(128) + sig := SignatureS{tc.privKey.Sign(msg)} + + // store as wire + bin, err := data.ToWire(sig) + require.Nil(t, err, "%+v", err) + if tc.sigSize != 0 { + assert.Equal(t, tc.sigSize+1, len(bin)) + } + assert.Equal(t, tc.sigType, bin[0]) + + // and back + sig2 := SignatureS{} + err = data.FromWire(bin, &sig2) + require.Nil(t, err, "%+v", err) + assert.EqualValues(t, sig, sig2) + assert.True(t, pubKey.VerifyBytes(msg, sig2)) + + // store as json + js, err := data.ToJSON(sig) + require.Nil(t, err, "%+v", err) + assert.True(t, strings.Contains(string(js), tc.sigName)) + fmt.Println(string(js)) + + // and back + sig3 := SignatureS{} + err = data.FromJSON(js, &sig3) + require.Nil(t, err, "%+v", err) + assert.EqualValues(t, sig, sig3) + assert.True(t, pubKey.VerifyBytes(msg, sig3)) } } From 6c2bf8c24bcccbe4093b5cfb7fbe54427a527027 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Feb 2017 13:20:30 +0100 Subject: [PATCH 024/273] Clean up test cases -> testify --- armor_test.go | 17 ++++++----------- signature_test.go | 27 +++++++++------------------ symmetric_test.go | 24 +++++++----------------- 3 files changed, 22 insertions(+), 46 deletions(-) diff --git a/armor_test.go b/armor_test.go index 3de37d7bc..5eae87c00 100644 --- a/armor_test.go +++ b/armor_test.go @@ -1,25 +1,20 @@ package crypto import ( - "bytes" "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestSimpleArmor(t *testing.T) { blockType := "MINT TEST" data := []byte("somedata") armorStr := EncodeArmor(blockType, nil, data) - t.Log("Got armor: ", armorStr) // Decode armorStr and test for equivalence. blockType2, _, data2, err := DecodeArmor(armorStr) - if err != nil { - t.Error(err) - } - if blockType != blockType2 { - t.Errorf("Expected block type %v but got %v", blockType, blockType2) - } - if !bytes.Equal(data, data2) { - t.Errorf("Expected data %X but got %X", data2, data) - } + require.Nil(t, err, "%+v", err) + assert.Equal(t, blockType, blockType2) + assert.Equal(t, data, data2) } diff --git a/signature_test.go b/signature_test.go index ac631eac5..e0e30b780 100644 --- a/signature_test.go +++ b/signature_test.go @@ -1,7 +1,6 @@ package crypto import ( - "fmt" "strings" "testing" @@ -18,45 +17,33 @@ func TestSignAndValidateEd25519(t *testing.T) { msg := CRandBytes(128) sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) // Test the signature - if !pubKey.VerifyBytes(msg, sig) { - t.Errorf("Account message signature verification failed") - } + assert.True(t, pubKey.VerifyBytes(msg, sig)) // Mutate the signature, just one bit. sigEd := sig.(SignatureEd25519) sigEd[0] ^= byte(0x01) sig = Signature(sigEd) - if pubKey.VerifyBytes(msg, sig) { - t.Errorf("Account message signature verification should have failed but passed instead") - } + assert.False(t, pubKey.VerifyBytes(msg, sig)) } func TestSignAndValidateSecp256k1(t *testing.T) { - privKey := GenPrivKeySecp256k1() pubKey := privKey.PubKey() msg := CRandBytes(128) sig := privKey.Sign(msg) - t.Logf("msg: %X, sig: %X", msg, sig) - // Test the signature - if !pubKey.VerifyBytes(msg, sig) { - t.Errorf("Account message signature verification failed") - } + assert.True(t, pubKey.VerifyBytes(msg, sig)) // Mutate the signature, just one bit. sigEd := sig.(SignatureSecp256k1) sigEd[0] ^= byte(0x01) sig = Signature(sigEd) - if pubKey.VerifyBytes(msg, sig) { - t.Errorf("Account message signature verification should have failed but passed instead") - } + assert.False(t, pubKey.VerifyBytes(msg, sig)) } func TestSignatureEncodings(t *testing.T) { @@ -106,7 +93,6 @@ func TestSignatureEncodings(t *testing.T) { js, err := data.ToJSON(sig) require.Nil(t, err, "%+v", err) assert.True(t, strings.Contains(string(js), tc.sigName)) - fmt.Println(string(js)) // and back sig3 := SignatureS{} @@ -114,5 +100,10 @@ func TestSignatureEncodings(t *testing.T) { require.Nil(t, err, "%+v", err) assert.EqualValues(t, sig, sig3) assert.True(t, pubKey.VerifyBytes(msg, sig3)) + + // and make sure we can textify it + text, err := data.ToText(sig) + require.Nil(t, err, "%+v", err) + assert.True(t, strings.HasPrefix(text, tc.sigName)) } } diff --git a/symmetric_test.go b/symmetric_test.go index c8134742d..d92bff1aa 100644 --- a/symmetric_test.go +++ b/symmetric_test.go @@ -1,9 +1,11 @@ package crypto import ( - "bytes" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/crypto/bcrypt" ) @@ -14,16 +16,10 @@ func TestSimple(t *testing.T) { plaintext := []byte("sometext") secret := []byte("somesecretoflengththirtytwo===32") ciphertext := EncryptSymmetric(plaintext, secret) - plaintext2, err := DecryptSymmetric(ciphertext, secret) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(plaintext, plaintext2) { - t.Errorf("Decrypted plaintext was %X, expected %X", plaintext2, plaintext) - } + require.Nil(t, err, "%+v", err) + assert.Equal(t, plaintext, plaintext2) } func TestSimpleWithKDF(t *testing.T) { @@ -39,14 +35,8 @@ func TestSimpleWithKDF(t *testing.T) { secret = Sha256(secret) ciphertext := EncryptSymmetric(plaintext, secret) - plaintext2, err := DecryptSymmetric(ciphertext, secret) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(plaintext, plaintext2) { - t.Errorf("Decrypted plaintext was %X, expected %X", plaintext2, plaintext) - } + require.Nil(t, err, "%+v", err) + assert.Equal(t, plaintext, plaintext2) } From cbe35e07d1a40dde7245ef926bd47090bba914f7 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Feb 2017 14:56:25 +0100 Subject: [PATCH 025/273] Add more tests for de/en-coding public and private keys --- encode_test.go | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 encode_test.go diff --git a/encode_test.go b/encode_test.go new file mode 100644 index 000000000..224f413c1 --- /dev/null +++ b/encode_test.go @@ -0,0 +1,88 @@ +package crypto + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + data "github.com/tendermint/go-data" +) + +type byter interface { + Bytes() []byte +} + +// go to wire encoding and back +func checkWire(t *testing.T, in byter, reader interface{}, typ byte) { + // test to and from binary + bin, err := data.ToWire(in) + require.Nil(t, err, "%+v", err) + assert.Equal(t, typ, bin[0]) + // make sure this is compatible with current (Bytes()) encoding + assert.Equal(t, in.Bytes(), bin) + + err = data.FromWire(bin, reader) + require.Nil(t, err, "%+v", err) +} + +// go to json encoding and back +func checkJSON(t *testing.T, in interface{}, reader interface{}, typ string) { + // test to and from binary + js, err := data.ToJSON(in) + require.Nil(t, err, "%+v", err) + styp := `"` + typ + `"` + assert.True(t, strings.Contains(string(js), styp)) + + err = data.FromJSON(js, reader) + require.Nil(t, err, "%+v", err) + + // also check text format + text, err := data.ToText(in) + require.Nil(t, err, "%+v", err) + parts := strings.Split(text, ":") + require.Equal(t, 2, len(parts)) + // make sure the first part is the typ string + assert.Equal(t, typ, parts[0]) + // and the data is also present in the json + assert.True(t, strings.Contains(string(js), parts[1])) +} + +func TestKeyEncodings(t *testing.T) { + cases := []struct { + privKey PrivKeyS + keyType byte + keyName string + }{ + { + privKey: PrivKeyS{GenPrivKeyEd25519()}, + keyType: PrivKeyTypeEd25519, + keyName: PrivKeyNameEd25519, + }, + { + privKey: PrivKeyS{GenPrivKeySecp256k1()}, + keyType: PrivKeyTypeSecp256k1, + keyName: PrivKeyNameSecp256k1, + }, + } + + for _, tc := range cases { + // check (de/en)codings of private key + priv2 := PrivKeyS{} + checkWire(t, tc.privKey, &priv2, tc.keyType) + assert.EqualValues(t, tc.privKey, priv2) + priv3 := PrivKeyS{} + checkJSON(t, tc.privKey, &priv3, tc.keyName) + assert.EqualValues(t, tc.privKey, priv3) + + // check (de/en)codings of public key + pubKey := PubKeyS{tc.privKey.PubKey()} + pub2 := PubKeyS{} + checkWire(t, pubKey, &pub2, tc.keyType) + assert.EqualValues(t, pubKey, pub2) + pub3 := PubKeyS{} + checkJSON(t, pubKey, &pub3, tc.keyName) + assert.EqualValues(t, pubKey, pub3) + } + +} From b6a2c5949f7ea1d064cbb9dc638eb0a3dca9af34 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Feb 2017 15:35:04 +0100 Subject: [PATCH 026/273] Add helper methods for nil checks in structs --- priv_key.go | 4 ++++ pub_key.go | 4 ++++ signature.go | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/priv_key.go b/priv_key.go index ac4760c7c..60a82636d 100644 --- a/priv_key.go +++ b/priv_key.go @@ -53,6 +53,10 @@ func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error) { return } +func (p PrivKeyS) Empty() bool { + return p.PrivKey == nil +} + func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { err = wire.ReadBinaryBytes(privKeyBytes, &privKey) return diff --git a/pub_key.go b/pub_key.go index 0c7f4663e..e5fe5209a 100644 --- a/pub_key.go +++ b/pub_key.go @@ -55,6 +55,10 @@ func (p *PubKeyS) UnmarshalJSON(data []byte) (err error) { return } +func (p PubKeyS) Empty() bool { + return p.PubKey == nil +} + func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey) return diff --git a/signature.go b/signature.go index fcef20a43..376a535d6 100644 --- a/signature.go +++ b/signature.go @@ -51,6 +51,10 @@ func (p *SignatureS) UnmarshalJSON(data []byte) (err error) { return } +func (p SignatureS) Empty() bool { + return p.Signature == nil +} + func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { err = wire.ReadBinaryBytes(sigBytes, &sig) return From 8c9b889ccfe1f891ce8ab36c843f15794ce8f30f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Feb 2017 18:11:20 +0100 Subject: [PATCH 027/273] Support json encode/decode for nil values in S structs --- encode_test.go | 24 ++++++++++++++++++++++++ priv_key.go | 2 +- pub_key.go | 2 +- signature.go | 2 +- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/encode_test.go b/encode_test.go index 224f413c1..8f2eebbaa 100644 --- a/encode_test.go +++ b/encode_test.go @@ -84,5 +84,29 @@ func TestKeyEncodings(t *testing.T) { checkJSON(t, pubKey, &pub3, tc.keyName) assert.EqualValues(t, pubKey, pub3) } +} + +func toFromJSON(t *testing.T, in interface{}, recvr interface{}) { + js, err := data.ToJSON(in) + require.Nil(t, err, "%+v", err) + err = data.FromJSON(js, recvr) + require.Nil(t, err, "%+v", err) +} + +func TestNilEncodings(t *testing.T) { + // make sure sigs are okay with nil + a, b := SignatureS{}, SignatureS{} + toFromJSON(t, a, &b) + assert.EqualValues(t, a, b) + + // make sure sigs are okay with nil + c, d := PubKeyS{}, PubKeyS{} + toFromJSON(t, c, &d) + assert.EqualValues(t, c, d) + + // make sure sigs are okay with nil + e, f := PrivKeyS{}, PrivKeyS{} + toFromJSON(t, e, &f) + assert.EqualValues(t, e, f) } diff --git a/priv_key.go b/priv_key.go index 60a82636d..81edfb3f6 100644 --- a/priv_key.go +++ b/priv_key.go @@ -47,7 +47,7 @@ func (p PrivKeyS) MarshalJSON() ([]byte, error) { func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error) { parsed, err := privKeyMapper.FromJSON(data) - if err == nil { + if err == nil && parsed != nil { p.PrivKey = parsed.(PrivKey) } return diff --git a/pub_key.go b/pub_key.go index e5fe5209a..77ce74a97 100644 --- a/pub_key.go +++ b/pub_key.go @@ -49,7 +49,7 @@ func (p PubKeyS) MarshalJSON() ([]byte, error) { func (p *PubKeyS) UnmarshalJSON(data []byte) (err error) { parsed, err := pubKeyMapper.FromJSON(data) - if err == nil { + if err == nil && parsed != nil { p.PubKey = parsed.(PubKey) } return diff --git a/signature.go b/signature.go index 376a535d6..076358879 100644 --- a/signature.go +++ b/signature.go @@ -45,7 +45,7 @@ func (p SignatureS) MarshalJSON() ([]byte, error) { func (p *SignatureS) UnmarshalJSON(data []byte) (err error) { parsed, err := sigMapper.FromJSON(data) - if err == nil { + if err == nil && parsed != nil { p.Signature = parsed.(Signature) } return From 0e92dd5bb557c6530e906e414893f05dda66cf80 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 24 Feb 2017 00:31:43 +0100 Subject: [PATCH 028/273] One name, type byte per algorithm --- encode_test.go | 8 ++++---- priv_key.go | 14 +++++++------- pub_key.go | 16 ++++------------ signature.go | 12 ++---------- signature_test.go | 8 ++++---- 5 files changed, 21 insertions(+), 37 deletions(-) diff --git a/encode_test.go b/encode_test.go index 8f2eebbaa..977cc64cf 100644 --- a/encode_test.go +++ b/encode_test.go @@ -56,13 +56,13 @@ func TestKeyEncodings(t *testing.T) { }{ { privKey: PrivKeyS{GenPrivKeyEd25519()}, - keyType: PrivKeyTypeEd25519, - keyName: PrivKeyNameEd25519, + keyType: TypeEd25519, + keyName: NameEd25519, }, { privKey: PrivKeyS{GenPrivKeySecp256k1()}, - keyType: PrivKeyTypeSecp256k1, - keyName: PrivKeyNameSecp256k1, + keyType: TypeSecp256k1, + keyName: NameSecp256k1, }, } diff --git a/priv_key.go b/priv_key.go index 81edfb3f6..54fa36a3a 100644 --- a/priv_key.go +++ b/priv_key.go @@ -19,12 +19,12 @@ type PrivKey interface { Equals(PrivKey) bool } -// Types of PrivKey implementations +// Types of implementations const ( - PrivKeyTypeEd25519 = byte(0x01) - PrivKeyTypeSecp256k1 = byte(0x02) - PrivKeyNameEd25519 = "ed25519" - PrivKeyNameSecp256k1 = "secp256k1" + TypeEd25519 = byte(0x01) + TypeSecp256k1 = byte(0x02) + NameEd25519 = "ed25519" + NameSecp256k1 = "secp256k1" ) var privKeyMapper data.Mapper @@ -32,8 +32,8 @@ var privKeyMapper data.Mapper // register both private key types with go-data (and thus go-wire) func init() { privKeyMapper = data.NewMapper(PrivKeyS{}). - RegisterInterface(PrivKeyEd25519{}, PrivKeyNameEd25519, PrivKeyTypeEd25519). - RegisterInterface(PrivKeySecp256k1{}, PrivKeyNameSecp256k1, PrivKeyTypeSecp256k1) + RegisterInterface(PrivKeyEd25519{}, NameEd25519, TypeEd25519). + RegisterInterface(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } // PrivKeyS add json serialization to PrivKey diff --git a/pub_key.go b/pub_key.go index 77ce74a97..9067a0363 100644 --- a/pub_key.go +++ b/pub_key.go @@ -21,21 +21,13 @@ type PubKey interface { Equals(PubKey) bool } -// Types of PubKey implementations -const ( - PubKeyTypeEd25519 = byte(0x01) - PubKeyTypeSecp256k1 = byte(0x02) - PubKeyNameEd25519 = "ed25519" - PubKeyNameSecp256k1 = "secp256k1" -) - var pubKeyMapper data.Mapper // register both public key types with go-data (and thus go-wire) func init() { pubKeyMapper = data.NewMapper(PubKeyS{}). - RegisterInterface(PubKeyEd25519{}, PubKeyNameEd25519, PubKeyTypeEd25519). - RegisterInterface(PubKeySecp256k1{}, PubKeyNameSecp256k1, PubKeyTypeSecp256k1) + RegisterInterface(PubKeyEd25519{}, NameEd25519, TypeEd25519). + RegisterInterface(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } // PubKeyS add json serialization to PubKey @@ -76,7 +68,7 @@ func (pubKey PubKeyEd25519) Address() []byte { PanicCrisis(*err) } // append type byte - encodedPubkey := append([]byte{PubKeyTypeEd25519}, w.Bytes()...) + encodedPubkey := append([]byte{TypeEd25519}, w.Bytes()...) hasher := ripemd160.New() hasher.Write(encodedPubkey) // does not error return hasher.Sum(nil) @@ -153,7 +145,7 @@ func (pubKey PubKeySecp256k1) Address() []byte { PanicCrisis(*err) } // append type byte - encodedPubkey := append([]byte{PubKeyTypeSecp256k1}, w.Bytes()...) + encodedPubkey := append([]byte{TypeSecp256k1}, w.Bytes()...) hasher := ripemd160.New() hasher.Write(encodedPubkey) // does not error return hasher.Sum(nil) diff --git a/signature.go b/signature.go index 076358879..b5fc36bf3 100644 --- a/signature.go +++ b/signature.go @@ -17,21 +17,13 @@ type Signature interface { Equals(Signature) bool } -// Types of Signature implementations -const ( - SignatureTypeEd25519 = byte(0x01) - SignatureTypeSecp256k1 = byte(0x02) - SignatureNameEd25519 = "ed25519" - SignatureNameSecp256k1 = "secp256k1" -) - var sigMapper data.Mapper // register both public key types with go-data (and thus go-wire) func init() { sigMapper = data.NewMapper(SignatureS{}). - RegisterInterface(SignatureEd25519{}, SignatureNameEd25519, SignatureTypeEd25519). - RegisterInterface(SignatureSecp256k1{}, SignatureNameSecp256k1, SignatureTypeSecp256k1) + RegisterInterface(SignatureEd25519{}, NameEd25519, TypeEd25519). + RegisterInterface(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1) } // SignatureS add json serialization to Signature diff --git a/signature_test.go b/signature_test.go index e0e30b780..f6c8c37be 100644 --- a/signature_test.go +++ b/signature_test.go @@ -56,14 +56,14 @@ func TestSignatureEncodings(t *testing.T) { { privKey: PrivKeyS{GenPrivKeyEd25519()}, sigSize: ed25519.SignatureSize, - sigType: SignatureTypeEd25519, - sigName: SignatureNameEd25519, + sigType: TypeEd25519, + sigName: NameEd25519, }, { privKey: PrivKeyS{GenPrivKeySecp256k1()}, sigSize: 0, // unknown - sigType: SignatureTypeSecp256k1, - sigName: SignatureNameSecp256k1, + sigType: TypeSecp256k1, + sigName: NameSecp256k1, }, } From f80957ad3c78170a166180eb05f7ea9c674835a5 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 16:30:15 +0100 Subject: [PATCH 029/273] Basic cobra/viper cli framework --- LICENSE | 202 +++++++++++++++++++++++++++++++++++++++++++++++ cmd/keys/main.go | 21 +++++ cmd/list.go | 49 ++++++++++++ cmd/new.go | 49 ++++++++++++ cmd/root.go | 84 ++++++++++++++++++++ cmd/serve.go | 50 ++++++++++++ cmd/update.go | 39 +++++++++ keys.yaml | 2 + 8 files changed, 496 insertions(+) create mode 100644 LICENSE create mode 100644 cmd/keys/main.go create mode 100644 cmd/list.go create mode 100644 cmd/new.go create mode 100644 cmd/root.go create mode 100644 cmd/serve.go create mode 100644 cmd/update.go create mode 100644 keys.yaml diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/cmd/keys/main.go b/cmd/keys/main.go new file mode 100644 index 000000000..8c880ea03 --- /dev/null +++ b/cmd/keys/main.go @@ -0,0 +1,21 @@ +// Copyright © 2017 Ethan Frey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import "github.com/tendermint/go-keys/cmd" + +func main() { + cmd.Execute() +} diff --git a/cmd/list.go b/cmd/list.go new file mode 100644 index 000000000..e2c8a7631 --- /dev/null +++ b/cmd/list.go @@ -0,0 +1,49 @@ +// Copyright © 2017 Ethan Frey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// listCmd represents the list command +var listCmd = &cobra.Command{ + Use: "list", + Short: "List all keys", + Long: `Return a list of all public keys stored by this key manager +along with their associated name and address.`, + Run: func(cmd *cobra.Command, args []string) { + // TODO: Work your own magic here + fmt.Println("list called") + fmt.Println(viper.Get("format")) + }, +} + +func init() { + RootCmd.AddCommand(listCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // listCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + listCmd.Flags().StringP("format", "f", "text", "Format to display (text|json)") +} diff --git a/cmd/new.go b/cmd/new.go new file mode 100644 index 000000000..40462e686 --- /dev/null +++ b/cmd/new.go @@ -0,0 +1,49 @@ +// Copyright © 2017 Ethan Frey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// newCmd represents the new command +var newCmd = &cobra.Command{ + Use: "new", + Short: "Create a new public/private key pair", + Long: `Add a public/private key pair to the key store. +The password muts be entered in the terminal and not +passed as a command line argument for security.`, + Run: func(cmd *cobra.Command, args []string) { + // TODO: Work your own magic here + fmt.Println("new called") + }, +} + +func init() { + RootCmd.AddCommand(newCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // newCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // newCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 000000000..896b7c666 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,84 @@ +// Copyright © 2017 Ethan Frey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "os" + "strings" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + rootDir string +) + +// RootCmd represents the base command when called without any subcommands +var RootCmd = &cobra.Command{ + Use: "keys", + Short: "Key manager for tendermint clients", + Long: `Keys allows you to manage your local keystore for tendermint. + +These keys may be in any format supported by go-crypto and can be +used by light-clients, full nodes, or any other application that +needs to sign with a private key.`, + PersistentPreRunE: bindFlags, + // Uncomment the following line if your bare application + // has an action associated with it: + // Run: func(cmd *cobra.Command, args []string) { }, +} + +// Execute adds all child commands to the root command sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := RootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(-1) + } +} + +func init() { + cobra.OnInitialize(initEnv) + RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data (default is $HOME/.tlc)") +} + +// initEnv sets to use ENV variables if set. +func initEnv() { + // env variables with TM prefix (eg. TM_ROOT) + viper.SetEnvPrefix("TM") + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + viper.AutomaticEnv() +} + +func bindFlags(cmd *cobra.Command, args []string) error { + // cmd.Flags() includes flags from this command and all persistent flags from the parent + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + + // rootDir is command line flag, env variable, or default $HOME/.tlc + rootDir = viper.GetString("root") + viper.SetConfigName("keys") // name of config file (without extension) + viper.AddConfigPath(rootDir) // search root directory + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } + + return nil +} diff --git a/cmd/serve.go b/cmd/serve.go new file mode 100644 index 000000000..06e923c7b --- /dev/null +++ b/cmd/serve.go @@ -0,0 +1,50 @@ +// Copyright © 2017 Ethan Frey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// serveCmd represents the serve command +var serveCmd = &cobra.Command{ + Use: "serve", + Short: "Run the key manager as an http server", + Long: `Launch an http server with a rest api to manage the +private keys much more in depth than the cli can perform. +In particular, this will allow you to sign transactions with +the private keys in the store.`, + Run: func(cmd *cobra.Command, args []string) { + // TODO: Work your own magic here + fmt.Println("serve called") + }, +} + +func init() { + RootCmd.AddCommand(serveCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // serveCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // serveCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + +} diff --git a/cmd/update.go b/cmd/update.go new file mode 100644 index 000000000..c36bcf25a --- /dev/null +++ b/cmd/update.go @@ -0,0 +1,39 @@ +// Copyright © 2017 Ethan Frey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// updateCmd represents the update command +var updateCmd = &cobra.Command{ + Use: "update", + Short: "Change the password for a private key", + Long: `Change the password for a private key.`, + Run: func(cmd *cobra.Command, args []string) { + // TODO: Work your own magic here + fmt.Println(viper.Get("name")) + fmt.Println("update called") + }, +} + +func init() { + RootCmd.AddCommand(updateCmd) + updateCmd.Flags().StringP("name", "n", "", "Name of key to update") +} diff --git a/keys.yaml b/keys.yaml new file mode 100644 index 000000000..3aec88a7b --- /dev/null +++ b/keys.yaml @@ -0,0 +1,2 @@ +format: super +name: george From d979bfc49ea930134ddedba28eb087716f5c25f8 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 16:56:17 +0100 Subject: [PATCH 030/273] Add flag validation --- cmd/root.go | 21 ++++++++++++++++----- keys.yaml | 1 - 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 896b7c666..05fffd489 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -19,12 +19,14 @@ import ( "os" "strings" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" ) var ( rootDir string + format string ) // RootCmd represents the base command when called without any subcommands @@ -37,9 +39,6 @@ These keys may be in any format supported by go-crypto and can be used by light-clients, full nodes, or any other application that needs to sign with a private key.`, PersistentPreRunE: bindFlags, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, } // Execute adds all child commands to the root command sets flags appropriately. @@ -53,7 +52,8 @@ func Execute() { func init() { cobra.OnInitialize(initEnv) - RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data (default is $HOME/.tlc)") + RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data (default is TM_ROOT or $HOME/.tlc)") + RootCmd.PersistentFlags().StringP("format", "f", "text", "Output format (text|json)") } // initEnv sets to use ENV variables if set. @@ -80,5 +80,16 @@ func bindFlags(cmd *cobra.Command, args []string) error { fmt.Println("Using config file:", viper.ConfigFileUsed()) } - return nil + return validateFlags(cmd) +} + +// validateFlags asserts all RootCmd flags are valid +func validateFlags(cmd *cobra.Command) error { + format = viper.GetString("format") + switch format { + case "text", "json": + return nil + default: + return errors.Errorf("Unsupported format: %s", format) + } } diff --git a/keys.yaml b/keys.yaml index 3aec88a7b..812adb72a 100644 --- a/keys.yaml +++ b/keys.yaml @@ -1,2 +1 @@ -format: super name: george From 78bb9f9cd8ac4dacbb28efe1db37566f88e75209 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 18:07:59 +0100 Subject: [PATCH 031/273] Import keystore logic from light-client --- Makefile | 2 + cryptostore/docs.go | 25 ++++ cryptostore/enc_storage.go | 47 ++++++ cryptostore/encoder.go | 54 +++++++ cryptostore/encoder_test.go | 59 ++++++++ cryptostore/generator.go | 30 ++++ cryptostore/holder.go | 120 +++++++++++++++ cryptostore/holder_test.go | 241 +++++++++++++++++++++++++++++++ cryptostore/storage_test.go | 41 ++++++ keys.toml | 1 + keys.yaml | 1 - storage.go | 10 ++ storage/filestorage/main.go | 171 ++++++++++++++++++++++ storage/filestorage/main_test.go | 95 ++++++++++++ storage/memstorage/main.go | 70 +++++++++ storage/memstorage/main_test.go | 67 +++++++++ transactions.go | 61 ++++++++ 17 files changed, 1094 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 cryptostore/docs.go create mode 100644 cryptostore/enc_storage.go create mode 100644 cryptostore/encoder.go create mode 100644 cryptostore/encoder_test.go create mode 100644 cryptostore/generator.go create mode 100644 cryptostore/holder.go create mode 100644 cryptostore/holder_test.go create mode 100644 cryptostore/storage_test.go create mode 100644 keys.toml delete mode 100644 keys.yaml create mode 100644 storage.go create mode 100644 storage/filestorage/main.go create mode 100644 storage/filestorage/main_test.go create mode 100644 storage/memstorage/main.go create mode 100644 storage/memstorage/main_test.go create mode 100644 transactions.go diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..7a1f90fd4 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +test: + go test ./... diff --git a/cryptostore/docs.go b/cryptostore/docs.go new file mode 100644 index 000000000..5c66fba2d --- /dev/null +++ b/cryptostore/docs.go @@ -0,0 +1,25 @@ +/* +package cryptostore maintains everything needed for doing public-key signing and +key management in software, based on the go-crypto library from tendermint. + +It is flexible, and allows the user to provide a key generation algorithm +(currently Ed25519 or Secp256k1), an encoder to passphrase-encrypt our keys +when storing them (currently SecretBox from NaCl), and a method to persist +the keys (currently FileStorage like ssh, or MemStorage for tests). +It should be relatively simple to write your own implementation of these +interfaces to match your specific security requirements. + +Note that the private keys are never exposed outside the package, and the +interface of Manager could be implemented by an HSM in the future for +enhanced security. It would require a completely different implementation +however. + +This Manager aims to implement Signer and KeyManager interfaces, along +with some extensions to allow importing/exporting keys and updating the +passphrase. + +Encoder and Generator implementations are currently in this package, +keys.Storage implementations exist as subpackages of +keys/storage +*/ +package cryptostore diff --git a/cryptostore/enc_storage.go b/cryptostore/enc_storage.go new file mode 100644 index 000000000..0a935075f --- /dev/null +++ b/cryptostore/enc_storage.go @@ -0,0 +1,47 @@ +package cryptostore + +import ( + crypto "github.com/tendermint/go-crypto" + keys "github.com/tendermint/go-keys" +) + +// encryptedStorage needs passphrase to get private keys +type encryptedStorage struct { + coder Encoder + store keys.Storage +} + +func (es encryptedStorage) Put(name, pass string, key crypto.PrivKey) error { + secret, err := es.coder.Encrypt(key, pass) + if err != nil { + return err + } + + ki := info(name, key) + return es.store.Put(name, secret, ki) +} + +func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.KeyInfo, error) { + secret, info, err := es.store.Get(name) + if err != nil { + return nil, info, err + } + key, err := es.coder.Decrypt(secret, pass) + return key, info, err +} + +func (es encryptedStorage) List() ([]keys.KeyInfo, error) { + return es.store.List() +} + +func (es encryptedStorage) Delete(name string) error { + return es.store.Delete(name) +} + +// info hardcodes the encoding of keys +func info(name string, key crypto.PrivKey) keys.KeyInfo { + return keys.KeyInfo{ + Name: name, + PubKey: crypto.PubKeyS{key.PubKey()}, + } +} diff --git a/cryptostore/encoder.go b/cryptostore/encoder.go new file mode 100644 index 000000000..03bc1e4e8 --- /dev/null +++ b/cryptostore/encoder.go @@ -0,0 +1,54 @@ +package cryptostore + +import ( + "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" +) + +var ( + // SecretBox uses the algorithm from NaCL to store secrets securely + SecretBox Encoder = secretbox{} + // Noop doesn't do any encryption, should only be used in test code + Noop Encoder = noop{} +) + +// Encoder is used to encrypt any key with a passphrase for storage. +// +// This should use a well-designed symetric encryption algorithm +type Encoder interface { + Encrypt(key crypto.PrivKey, pass string) ([]byte, error) + Decrypt(data []byte, pass string) (crypto.PrivKey, error) +} + +func secret(passphrase string) []byte { + // TODO: Sha256(Bcrypt(passphrase)) + return crypto.Sha256([]byte(passphrase)) +} + +type secretbox struct{} + +func (e secretbox) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { + s := secret(pass) + cipher := crypto.EncryptSymmetric(key.Bytes(), s) + return cipher, nil +} + +func (e secretbox) Decrypt(data []byte, pass string) (crypto.PrivKey, error) { + s := secret(pass) + private, err := crypto.DecryptSymmetric(data, s) + if err != nil { + return nil, errors.Wrap(err, "Invalid Passphrase") + } + key, err := crypto.PrivKeyFromBytes(private) + return key, errors.Wrap(err, "Invalid Passphrase") +} + +type noop struct{} + +func (n noop) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { + return key.Bytes(), nil +} + +func (n noop) Decrypt(data []byte, pass string) (crypto.PrivKey, error) { + return crypto.PrivKeyFromBytes(data) +} diff --git a/cryptostore/encoder_test.go b/cryptostore/encoder_test.go new file mode 100644 index 000000000..8b72509ed --- /dev/null +++ b/cryptostore/encoder_test.go @@ -0,0 +1,59 @@ +package cryptostore_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tendermint/go-keys/cryptostore" +) + +func TestNoopEncoder(t *testing.T) { + assert, require := assert.New(t), require.New(t) + noop := cryptostore.Noop + + key := cryptostore.GenEd25519.Generate() + key2 := cryptostore.GenSecp256k1.Generate() + + b, err := noop.Encrypt(key, "encode") + require.Nil(err) + assert.NotEmpty(b) + + b2, err := noop.Encrypt(key2, "encode") + require.Nil(err) + assert.NotEmpty(b2) + assert.NotEqual(b, b2) + + // note the decode with a different password works - not secure! + pk, err := noop.Decrypt(b, "decode") + require.Nil(err) + require.NotNil(pk) + assert.Equal(key, pk) + + pk2, err := noop.Decrypt(b2, "kggugougp") + require.Nil(err) + require.NotNil(pk2) + assert.Equal(key2, pk2) +} + +func TestSecretBox(t *testing.T) { + assert, require := assert.New(t), require.New(t) + enc := cryptostore.SecretBox + + key := cryptostore.GenEd25519.Generate() + pass := "some-special-secret" + + b, err := enc.Encrypt(key, pass) + require.Nil(err) + assert.NotEmpty(b) + + // decoding with a different pass is an error + pk, err := enc.Decrypt(b, "decode") + require.NotNil(err) + require.Nil(pk) + + // but decoding with the same passphrase gets us our key + pk, err = enc.Decrypt(b, pass) + require.Nil(err) + assert.Equal(key, pk) +} diff --git a/cryptostore/generator.go b/cryptostore/generator.go new file mode 100644 index 000000000..c6661fb34 --- /dev/null +++ b/cryptostore/generator.go @@ -0,0 +1,30 @@ +package cryptostore + +import crypto "github.com/tendermint/go-crypto" + +var ( + // GenEd25519 produces Ed25519 private keys + GenEd25519 Generator = GenFunc(genEd25519) + // GenSecp256k1 produces Secp256k1 private keys + GenSecp256k1 Generator = GenFunc(genSecp256) +) + +// Generator determines the type of private key the keystore creates +type Generator interface { + Generate() crypto.PrivKey +} + +// GenFunc is a helper to transform a function into a Generator +type GenFunc func() crypto.PrivKey + +func (f GenFunc) Generate() crypto.PrivKey { + return f() +} + +func genEd25519() crypto.PrivKey { + return crypto.GenPrivKeyEd25519() +} + +func genSecp256() crypto.PrivKey { + return crypto.GenPrivKeySecp256k1() +} diff --git a/cryptostore/holder.go b/cryptostore/holder.go new file mode 100644 index 000000000..4beb64160 --- /dev/null +++ b/cryptostore/holder.go @@ -0,0 +1,120 @@ +package cryptostore + +import keys "github.com/tendermint/go-keys" + +// Manager combines encyption and storage implementation to provide +// a full-featured key manager +type Manager struct { + gen Generator + es encryptedStorage +} + +func New(gen Generator, coder Encoder, store keys.Storage) Manager { + return Manager{ + gen: gen, + es: encryptedStorage{ + coder: coder, + store: store, + }, + } +} + +// exists just to make sure we fulfill the Signer interface +func (s Manager) assertSigner() keys.Signer { + return s +} + +// exists just to make sure we fulfill the KeyManager interface +func (s Manager) assertKeyManager() keys.KeyManager { + return s +} + +// Create adds a new key to the storage engine, returning error if +// another key already stored under this name +func (s Manager) Create(name, passphrase string) error { + key := s.gen.Generate() + return s.es.Put(name, passphrase, key) +} + +// List loads the keys from the storage and enforces alphabetical order +func (s Manager) List() (keys.KeyInfos, error) { + k, err := s.es.List() + res := keys.KeyInfos(k) + res.Sort() + return res, err +} + +// Get returns the public information about one key +func (s Manager) Get(name string) (keys.KeyInfo, error) { + _, info, err := s.es.store.Get(name) + return info, err +} + +// Sign will modify the Signable in order to attach a valid signature with +// this public key +// +// If no key for this name, or the passphrase doesn't match, returns an error +func (s Manager) Sign(name, passphrase string, tx keys.Signable) error { + key, _, err := s.es.Get(name, passphrase) + if err != nil { + return err + } + sig := key.Sign(tx.SignBytes()) + pubkey := key.PubKey() + return tx.Sign(pubkey, sig) +} + +// Export decodes the private key with the current password, encodes +// it with a secure one-time password and generates a sequence that can be +// Imported by another Manager +// +// This is designed to copy from one device to another, or provide backups +// during version updates. +func (s Manager) Export(name, oldpass, transferpass string) ([]byte, error) { + key, _, err := s.es.Get(name, oldpass) + if err != nil { + return nil, err + } + + res, err := s.es.coder.Encrypt(key, transferpass) + return res, err +} + +// Import accepts bytes generated by Export along with the same transferpass +// If they are valid, it stores the password under the given name with the +// new passphrase. +func (s Manager) Import(name, newpass, transferpass string, data []byte) error { + key, err := s.es.coder.Decrypt(data, transferpass) + if err != nil { + return err + } + + return s.es.Put(name, newpass, key) +} + +// Delete removes key forever, but we must present the +// proper passphrase before deleting it (for security) +func (s Manager) Delete(name, passphrase string) error { + // verify we have the proper password before deleting + _, _, err := s.es.Get(name, passphrase) + if err != nil { + return err + } + return s.es.Delete(name) +} + +// Update changes the passphrase with which a already stored key is encoded. +// +// oldpass must be the current passphrase used for encoding, newpass will be +// the only valid passphrase from this time forward +func (s Manager) Update(name, oldpass, newpass string) error { + key, _, err := s.es.Get(name, oldpass) + if err != nil { + return err + } + + // we must delete first, as Putting over an existing name returns an error + s.Delete(name, oldpass) + + return s.es.Put(name, newpass, key) +} diff --git a/cryptostore/holder_test.go b/cryptostore/holder_test.go new file mode 100644 index 000000000..fb5ef854f --- /dev/null +++ b/cryptostore/holder_test.go @@ -0,0 +1,241 @@ +package cryptostore_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tendermint/go-keys/cryptostore" + "github.com/tendermint/go-keys/storage/memstorage" +) + +// TestKeyManagement makes sure we can manipulate these keys well +func TestKeyManagement(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + // make the storage with reasonable defaults + cstore := cryptostore.New( + cryptostore.GenSecp256k1, + cryptostore.SecretBox, + memstorage.New(), + ) + + n1, n2, n3 := "personal", "business", "other" + p1, p2 := "1234", "really-secure!@#$" + + // Check empty state + l, err := cstore.List() + require.Nil(err) + assert.Empty(l) + + // create some keys + _, err = cstore.Get(n1) + assert.NotNil(err) + err = cstore.Create(n1, p1) + require.Nil(err) + err = cstore.Create(n2, p2) + require.Nil(err) + + // we can get these keys + i2, err := cstore.Get(n2) + assert.Nil(err) + _, err = cstore.Get(n3) + assert.NotNil(err) + + // list shows them in order + keys, err := cstore.List() + require.Nil(err) + require.Equal(2, len(keys)) + // note these are in alphabetical order + assert.Equal(n2, keys[0].Name) + assert.Equal(n1, keys[1].Name) + assert.Equal(i2.PubKey, keys[0].PubKey) + + // deleting a key removes it + err = cstore.Delete("bad name", "foo") + require.NotNil(err) + err = cstore.Delete(n1, p1) + require.Nil(err) + keys, err = cstore.List() + require.Nil(err) + assert.Equal(1, len(keys)) + _, err = cstore.Get(n1) + assert.NotNil(err) + + // make sure that it only signs with the right password + // tx := mock.NewSig([]byte("mytransactiondata")) + // err = cstore.Sign(n2, p1, tx) + // assert.NotNil(err) + // err = cstore.Sign(n2, p2, tx) + // assert.Nil(err, "%+v", err) + // sigs, err := tx.Signers() + // assert.Nil(err, "%+v", err) + // if assert.Equal(1, len(sigs)) { + // assert.Equal(i2.PubKey, sigs[0]) + // } +} + +// TestSignVerify does some detailed checks on how we sign and validate +// signatures +// func TestSignVerify(t *testing.T) { +// assert, require := assert.New(t), require.New(t) + +// // make the storage with reasonable defaults +// cstore := cryptostore.New( +// cryptostore.GenSecp256k1, +// cryptostore.SecretBox, +// memstorage.New(), +// ) + +// n1, n2 := "some dude", "a dudette" +// p1, p2 := "1234", "foobar" + +// // create two users and get their info +// err := cstore.Create(n1, p1) +// require.Nil(err) +// i1, err := cstore.Get(n1) +// require.Nil(err) + +// err = cstore.Create(n2, p2) +// require.Nil(err) +// i2, err := cstore.Get(n2) +// require.Nil(err) + +// // let's try to sign some messages +// d1 := []byte("my first message") +// d2 := []byte("some other important info!") + +// // try signing both data with both keys... +// s11, err := cstore.Signature(n1, p1, d1) +// require.Nil(err) +// s12, err := cstore.Signature(n1, p1, d2) +// require.Nil(err) +// s21, err := cstore.Signature(n2, p2, d1) +// require.Nil(err) +// s22, err := cstore.Signature(n2, p2, d2) +// require.Nil(err) + +// // let's try to validate and make sure it only works when everything is proper +// keys := [][]byte{i1.PubKey, i2.PubKey} +// data := [][]byte{d1, d2} +// sigs := [][]byte{s11, s12, s21, s22} + +// // loop over keys and data +// for k := 0; k < 2; k++ { +// for d := 0; d < 2; d++ { +// // make sure only the proper sig works +// good := 2*k + d +// for s := 0; s < 4; s++ { +// err = cstore.Verify(data[d], sigs[s], keys[k]) +// if s == good { +// assert.Nil(err, "%+v", err) +// } else { +// assert.NotNil(err) +// } +// } +// } +// } +// } + +func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, pass, badpass string) { + err := cstore.Update(name, badpass, pass) + assert.NotNil(err) + err = cstore.Update(name, pass, pass) + assert.Nil(err, "%+v", err) +} + +// TestAdvancedKeyManagement verifies update, import, export functionality +func TestAdvancedKeyManagement(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + // make the storage with reasonable defaults + cstore := cryptostore.New( + cryptostore.GenSecp256k1, + cryptostore.SecretBox, + memstorage.New(), + ) + + n1, n2 := "old-name", "new name" + p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$" + + // make sure key works with initial password + err := cstore.Create(n1, p1) + require.Nil(err, "%+v", err) + assertPassword(assert, cstore, n1, p1, p2) + + // update password requires the existing password + err = cstore.Update(n1, "jkkgkg", p2) + assert.NotNil(err) + assertPassword(assert, cstore, n1, p1, p2) + + // then it changes the password when correct + err = cstore.Update(n1, p1, p2) + assert.Nil(err) + // p2 is now the proper one! + assertPassword(assert, cstore, n1, p2, p1) + + // exporting requires the proper name and passphrase + _, err = cstore.Export(n2, p2, pt) + assert.NotNil(err) + _, err = cstore.Export(n1, p1, pt) + assert.NotNil(err) + exported, err := cstore.Export(n1, p2, pt) + require.Nil(err, "%+v", err) + + // import fails on bad transfer pass + err = cstore.Import(n2, p3, p2, exported) + assert.NotNil(err) + // import cannot overwrite existing keys + err = cstore.Import(n1, p3, pt, exported) + assert.NotNil(err) + // we can now import under another name + err = cstore.Import(n2, p3, pt, exported) + require.Nil(err, "%+v", err) + + // make sure both passwords are now properly set (not to the transfer pass) + assertPassword(assert, cstore, n1, p2, pt) + assertPassword(assert, cstore, n2, p3, pt) +} + +// func ExampleStore() { +// // Select the encryption and storage for your cryptostore +// cstore := cryptostore.New( +// cryptostore.GenEd25519, +// cryptostore.SecretBox, +// // Note: use filestorage.New(dir) for real data +// memstorage.New(), +// ) + +// // Add keys and see they return in alphabetical order +// cstore.Create("Bob", "friend") +// cstore.Create("Alice", "secret") +// cstore.Create("Carl", "mitm") +// info, _ := cstore.List() +// for _, i := range info { +// fmt.Println(i.Name) +// } + +// // We need to use passphrase to generate a signature +// tx := mock.NewSig([]byte("deadbeef")) +// err := cstore.Sign("Bob", "friend", tx) +// if err != nil { +// fmt.Println("don't accept real passphrase") +// } + +// // and we can validate the signature with publically available info +// binfo, _ := cstore.Get("Bob") +// sigs, err := tx.Signers() +// if err != nil { +// fmt.Println("badly signed") +// } else if bytes.Equal(sigs[0].Bytes(), binfo.PubKey.Bytes()) { +// fmt.Println("signed by Bob") +// } else { +// fmt.Println("signed by someone else") +// } + +// // Output: +// // Alice +// // Bob +// // Carl +// // signed by Bob +// } diff --git a/cryptostore/storage_test.go b/cryptostore/storage_test.go new file mode 100644 index 000000000..6c6ea5e2c --- /dev/null +++ b/cryptostore/storage_test.go @@ -0,0 +1,41 @@ +package cryptostore + +import ( + "testing" + + "github.com/stretchr/testify/assert" + keys "github.com/tendermint/go-keys" +) + +func TestSortKeys(t *testing.T) { + assert := assert.New(t) + + gen := GenEd25519.Generate + assert.NotEqual(gen(), gen()) + + // alphabetical order is n3, n1, n2 + n1, n2, n3 := "john", "mike", "alice" + infos := keys.KeyInfos{ + info(n1, gen()), + info(n2, gen()), + info(n3, gen()), + } + + // make sure they are initialized unsorted + assert.Equal(n1, infos[0].Name) + assert.Equal(n2, infos[1].Name) + assert.Equal(n3, infos[2].Name) + + // now they are sorted + infos.Sort() + assert.Equal(n3, infos[0].Name) + assert.Equal(n1, infos[1].Name) + assert.Equal(n2, infos[2].Name) + + // make sure info put some real data there... + assert.NotEmpty(infos[0].PubKey) + assert.NotEmpty(infos[0].PubKey.Address()) + assert.NotEmpty(infos[1].PubKey) + assert.NotEmpty(infos[1].PubKey.Address()) + assert.NotEqual(infos[0].PubKey, infos[1].PubKey) +} diff --git a/keys.toml b/keys.toml new file mode 100644 index 000000000..41f4d5286 --- /dev/null +++ b/keys.toml @@ -0,0 +1 @@ +format = "text" diff --git a/keys.yaml b/keys.yaml deleted file mode 100644 index 812adb72a..000000000 --- a/keys.yaml +++ /dev/null @@ -1 +0,0 @@ -name: george diff --git a/storage.go b/storage.go new file mode 100644 index 000000000..519ce1aa8 --- /dev/null +++ b/storage.go @@ -0,0 +1,10 @@ +package keys + +// Storage has many implementation, based on security and sharing requirements +// like disk-backed, mem-backed, vault, db, etc. +type Storage interface { + Put(name string, key []byte, info KeyInfo) error + Get(name string) ([]byte, KeyInfo, error) + List() ([]KeyInfo, error) + Delete(name string) error +} diff --git a/storage/filestorage/main.go b/storage/filestorage/main.go new file mode 100644 index 000000000..554a36540 --- /dev/null +++ b/storage/filestorage/main.go @@ -0,0 +1,171 @@ +/* +package filestorage provides a secure on-disk storage of private keys and +metadata. Security is enforced by file and directory permissions, much +like standard ssh key storage. +*/ +package filestorage + +import ( + "fmt" + "io/ioutil" + "os" + "path" + "strings" + + "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" + keys "github.com/tendermint/go-keys" +) + +const ( + BlockType = "Tendermint Light Client" + PrivExt = "tlc" + PubExt = "pub" + keyPerm = os.FileMode(0600) + pubPerm = os.FileMode(0644) + dirPerm = os.FileMode(0700) +) + +type FileStore struct { + keyDir string +} + +// New creates an instance of file-based key storage with tight permissions +// +// dir should be an absolute path of a directory owner by this user. It will +// be created if it doesn't exist already. +func New(dir string) FileStore { + err := os.Mkdir(dir, dirPerm) + if err != nil && !os.IsExist(err) { + panic(err) + } + return FileStore{dir} +} + +// assertStorage just makes sure we implement the proper Storage interface +func (s FileStore) assertStorage() keys.Storage { + return s +} + +// Put creates two files, one with the public info as json, the other +// with the (encoded) private key as gpg ascii-armor style +func (s FileStore) Put(name string, key []byte, info keys.KeyInfo) error { + pub, priv := s.nameToPaths(name) + + // write public info + err := writeInfo(pub, info) + if err != nil { + return err + } + + // write private info + return write(priv, name, key) +} + +// Get loads the keyinfo and (encoded) private key from the directory +// It uses `name` to generate the filename, and returns an error if the +// files don't exist or are in the incorrect format +func (s FileStore) Get(name string) ([]byte, keys.KeyInfo, error) { + pub, priv := s.nameToPaths(name) + + info, err := readInfo(pub) + if err != nil { + return nil, info, err + } + + key, _, err := read(priv) + return key, info, err +} + +// List parses the key directory for public info and returns a list of +// KeyInfo for all keys located in this directory. +func (s FileStore) List() ([]keys.KeyInfo, error) { + dir, err := os.Open(s.keyDir) + if err != nil { + return nil, errors.Wrap(err, "List Keys") + } + names, err := dir.Readdirnames(0) + if err != nil { + return nil, errors.Wrap(err, "List Keys") + } + + // filter names for .pub ending and load them one by one + // half the files is a good guess for pre-allocating the slice + infos := make([]keys.KeyInfo, 0, len(names)/2) + for _, name := range names { + if strings.HasSuffix(name, PubExt) { + p := path.Join(s.keyDir, name) + info, err := readInfo(p) + if err != nil { + return nil, err + } + infos = append(infos, info) + } + } + + return infos, nil +} + +// Delete permanently removes the public and private info for the named key +// The calling function should provide some security checks first. +func (s FileStore) Delete(name string) error { + pub, priv := s.nameToPaths(name) + err := os.Remove(priv) + if err != nil { + return errors.Wrap(err, "Deleting Private Key") + } + err = os.Remove(pub) + return errors.Wrap(err, "Deleting Public Key") +} + +func (s FileStore) nameToPaths(name string) (pub, priv string) { + privName := fmt.Sprintf("%s.%s", name, PrivExt) + pubName := fmt.Sprintf("%s.%s", name, PubExt) + return path.Join(s.keyDir, pubName), path.Join(s.keyDir, privName) +} + +func writeInfo(path string, info keys.KeyInfo) error { + return write(path, info.Name, info.PubKey.Bytes()) +} + +func readInfo(path string) (info keys.KeyInfo, err error) { + var data []byte + data, info.Name, err = read(path) + if err != nil { + return + } + pk, err := crypto.PubKeyFromBytes(data) + info.PubKey = crypto.PubKeyS{pk} + return +} + +func read(path string) ([]byte, string, error) { + f, err := os.Open(path) + if err != nil { + return nil, "", errors.Wrap(err, "Reading data") + } + d, err := ioutil.ReadAll(f) + if err != nil { + return nil, "", errors.Wrap(err, "Reading data") + } + block, headers, key, err := crypto.DecodeArmor(string(d)) + if err != nil { + return nil, "", errors.Wrap(err, "Invalid Armor") + } + if block != BlockType { + return nil, "", errors.Errorf("Unknown key type: %s", block) + } + return key, headers["name"], nil +} + +func write(path, name string, key []byte) error { + f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) + if err != nil { + return errors.Wrap(err, "Writing data") + } + defer f.Close() + headers := map[string]string{"name": name} + text := crypto.EncodeArmor(BlockType, headers, key) + _, err = f.WriteString(text) + return errors.Wrap(err, "Writing data") +} diff --git a/storage/filestorage/main_test.go b/storage/filestorage/main_test.go new file mode 100644 index 000000000..f81ba7198 --- /dev/null +++ b/storage/filestorage/main_test.go @@ -0,0 +1,95 @@ +package filestorage + +import ( + "io/ioutil" + "os" + "path" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" + keys "github.com/tendermint/go-keys" +) + +func TestBasicCRUD(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + dir, err := ioutil.TempDir("", "filestorage-test") + assert.Nil(err) + defer os.RemoveAll(dir) + store := New(dir) + + name := "bar" + key := []byte("secret-key-here") + pubkey := crypto.GenPrivKeyEd25519().PubKey() + info := keys.KeyInfo{ + Name: name, + PubKey: crypto.PubKeyS{pubkey}, + } + + // No data: Get and Delete return nothing + _, _, err = store.Get(name) + assert.NotNil(err) + err = store.Delete(name) + assert.NotNil(err) + // List returns empty list + l, err := store.List() + assert.Nil(err) + assert.Empty(l) + + // Putting the key in the store must work + err = store.Put(name, key, info) + assert.Nil(err) + // But a second time is a failure + err = store.Put(name, key, info) + assert.NotNil(err) + + // Now, we can get and list properly + k, i, err := store.Get(name) + require.Nil(err, "%+v", err) + assert.Equal(key, k) + assert.Equal(info, i) + l, err = store.List() + require.Nil(err, "%+v", err) + assert.Equal(1, len(l)) + assert.Equal(info, l[0]) + + // querying a non-existent key fails + _, _, err = store.Get("badname") + assert.NotNil(err) + + // We can only delete once + err = store.Delete(name) + assert.Nil(err) + err = store.Delete(name) + assert.NotNil(err) + + // and then Get and List don't work + _, _, err = store.Get(name) + assert.NotNil(err) + // List returns empty list + l, err = store.List() + assert.Nil(err) + assert.Empty(l) +} + +func TestDirectoryHandling(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + // prepare a temp dir and make sure it is not there + newDir := path.Join(os.TempDir(), "file-test-dir") + _, err := os.Open(newDir) + assert.True(os.IsNotExist(err)) + + // create a new storage, and verify it creates the directory with good permissions + New(newDir) + defer os.RemoveAll(newDir) + d, err := os.Open(newDir) + require.Nil(err) + defer d.Close() + + stat, err := d.Stat() + require.Nil(err) + assert.Equal(dirPerm, stat.Mode()&os.ModePerm) +} diff --git a/storage/memstorage/main.go b/storage/memstorage/main.go new file mode 100644 index 000000000..e6573eb9f --- /dev/null +++ b/storage/memstorage/main.go @@ -0,0 +1,70 @@ +/* +package memstorage provides a simple in-memory key store designed for +use in test cases, particularly to isolate them from the filesystem, +concurrency, and cleanup issues. +*/ +package memstorage + +import ( + "github.com/pkg/errors" + keys "github.com/tendermint/go-keys" +) + +type data struct { + info keys.KeyInfo + key []byte +} + +type MemStore map[string]data + +// New creates an instance of file-based key storage with tight permissions +func New() MemStore { + return MemStore{} +} + +// assertStorage just makes sure we implement the Storage interface +func (s MemStore) assertStorage() keys.Storage { + return s +} + +// Put adds the given key, returns an error if it another key +// is already stored under this name +func (s MemStore) Put(name string, key []byte, info keys.KeyInfo) error { + if _, ok := s[name]; ok { + return errors.Errorf("Key named '%s' already exists", name) + } + s[name] = data{info, key} + return nil +} + +// Get returns the key stored under the name, or returns an error if not present +func (s MemStore) Get(name string) ([]byte, keys.KeyInfo, error) { + var err error + d, ok := s[name] + if !ok { + err = errors.Errorf("Key named '%s' doesn't exist", name) + } + return d.key, d.info, err +} + +// List returns the public info of all keys in the MemStore in unsorted order +func (s MemStore) List() ([]keys.KeyInfo, error) { + res := make([]keys.KeyInfo, len(s)) + i := 0 + for _, d := range s { + res[i] = d.info + i++ + } + return res, nil +} + +// Delete removes the named key from the MemStore, raising an error if it +// wasn't present yet. +func (s MemStore) Delete(name string) error { + _, ok := s[name] + if !ok { + return errors.Errorf("Key named '%s' doesn't exist", name) + } + delete(s, name) + return nil +} diff --git a/storage/memstorage/main_test.go b/storage/memstorage/main_test.go new file mode 100644 index 000000000..01c015a15 --- /dev/null +++ b/storage/memstorage/main_test.go @@ -0,0 +1,67 @@ +package memstorage + +import ( + "testing" + + "github.com/stretchr/testify/assert" + crypto "github.com/tendermint/go-crypto" + keys "github.com/tendermint/go-keys" +) + +func TestBasicCRUD(t *testing.T) { + assert := assert.New(t) + store := New() + + name := "foo" + key := []byte("secret-key-here") + pubkey := crypto.GenPrivKeyEd25519().PubKey() + info := keys.KeyInfo{ + Name: name, + PubKey: crypto.PubKeyS{pubkey}, + } + + // No data: Get and Delete return nothing + _, _, err := store.Get(name) + assert.NotNil(err) + err = store.Delete(name) + assert.NotNil(err) + // List returns empty list + l, err := store.List() + assert.Nil(err) + assert.Empty(l) + + // Putting the key in the store must work + err = store.Put(name, key, info) + assert.Nil(err) + // But a second time is a failure + err = store.Put(name, key, info) + assert.NotNil(err) + + // Now, we can get and list properly + k, i, err := store.Get(name) + assert.Nil(err) + assert.Equal(key, k) + assert.Equal(info, i) + l, err = store.List() + assert.Nil(err) + assert.Equal(1, len(l)) + assert.Equal(info, l[0]) + + // querying a non-existent key fails + _, _, err = store.Get("badname") + assert.NotNil(err) + + // We can only delete once + err = store.Delete(name) + assert.Nil(err) + err = store.Delete(name) + assert.NotNil(err) + + // and then Get and List don't work + _, _, err = store.Get(name) + assert.NotNil(err) + // List returns empty list + l, err = store.List() + assert.Nil(err) + assert.Empty(l) +} diff --git a/transactions.go b/transactions.go new file mode 100644 index 000000000..f22719f7e --- /dev/null +++ b/transactions.go @@ -0,0 +1,61 @@ +package keys + +import ( + "sort" + + crypto "github.com/tendermint/go-crypto" +) + +// KeyInfo is the public information about a key +type KeyInfo struct { + Name string + PubKey crypto.PubKeyS +} + +// KeyInfos is a wrapper to allows alphabetical sorting of the keys +type KeyInfos []KeyInfo + +func (k KeyInfos) Len() int { return len(k) } +func (k KeyInfos) Less(i, j int) bool { return k[i].Name < k[j].Name } +func (k KeyInfos) Swap(i, j int) { k[i], k[j] = k[j], k[i] } +func (k KeyInfos) Sort() { + if k != nil { + sort.Sort(k) + } +} + +// Signable represents any transaction we wish to send to tendermint core +// These methods allow us to sign arbitrary Tx with the KeyStore +type Signable interface { + // SignBytes is the immutable data, which needs to be signed + SignBytes() []byte + + // Sign will add a signature and pubkey. + // + // Depending on the Signable, one may be able to call this multiple times for multisig + // Returns error if called with invalid data or too many times + Sign(pubkey crypto.PubKey, sig crypto.Signature) error + + // Signers will return the public key(s) that signed if the signature + // is valid, or an error if there is any issue with the signature, + // including if there are no signatures + Signers() ([]crypto.PubKey, error) + + // TxBytes returns the transaction data as well as all signatures + // It should return an error if Sign was never called + TxBytes() ([]byte, error) +} + +// Signer allows one to use a keystore to sign transactions +type Signer interface { + Sign(name, passphrase string, tx Signable) error +} + +// KeyManager allows simple CRUD on a keystore, as an aid to signing +type KeyManager interface { + Create(name, passphrase string) error + List() (KeyInfos, error) + Get(name string) (KeyInfo, error) + Update(name, oldpass, newpass string) error + Delete(name, passphrase string) error +} From 506ff7d85a09b03b2dc726d7a4b466e325c55ec2 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 18:52:52 +0100 Subject: [PATCH 032/273] Expose new and list via cli --- Makefile | 3 ++ cmd/list.go | 21 ++++-------- cmd/new.go | 42 +++++++++++++++++------- cmd/root.go | 33 +++++++++++++++---- cmd/utils.go | 56 ++++++++++++++++++++++++++++++++ cryptostore/enc_storage.go | 8 ++--- cryptostore/holder.go | 16 ++++----- cryptostore/holder_test.go | 7 ++-- cryptostore/storage_test.go | 2 +- keys.toml | 3 +- storage.go | 6 ++-- storage/filestorage/main.go | 16 ++++----- storage/filestorage/main_test.go | 2 +- storage/memstorage/main.go | 10 +++--- storage/memstorage/main_test.go | 2 +- transactions.go | 26 +++++++-------- 16 files changed, 173 insertions(+), 80 deletions(-) create mode 100644 cmd/utils.go diff --git a/Makefile b/Makefile index 7a1f90fd4..b15317b25 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,5 @@ test: go test ./... + +install: + go install ./cmd/keys diff --git a/cmd/list.go b/cmd/list.go index e2c8a7631..44fefb8d6 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -18,7 +18,6 @@ import ( "fmt" "github.com/spf13/cobra" - "github.com/spf13/viper" ) // listCmd represents the list command @@ -28,22 +27,16 @@ var listCmd = &cobra.Command{ Long: `Return a list of all public keys stored by this key manager along with their associated name and address.`, Run: func(cmd *cobra.Command, args []string) { - // TODO: Work your own magic here - fmt.Println("list called") - fmt.Println(viper.Get("format")) + infos, err := manager.List() + if err != nil { + fmt.Println(err.Error()) + return + } + + printInfos(infos) }, } func init() { RootCmd.AddCommand(listCmd) - - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // listCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - listCmd.Flags().StringP("format", "f", "text", "Format to display (text|json)") } diff --git a/cmd/new.go b/cmd/new.go index 40462e686..38d9762f9 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -22,28 +22,46 @@ import ( // newCmd represents the new command var newCmd = &cobra.Command{ - Use: "new", + Use: "new ", Short: "Create a new public/private key pair", Long: `Add a public/private key pair to the key store. The password muts be entered in the terminal and not passed as a command line argument for security.`, - Run: func(cmd *cobra.Command, args []string) { - // TODO: Work your own magic here - fmt.Println("new called") - }, + Run: newPassword, } func init() { RootCmd.AddCommand(newCmd) +} - // Here you will define your flags and configuration settings. +func newPassword(cmd *cobra.Command, args []string) { + if len(args) != 1 || len(args[0]) == 0 { + fmt.Print("You must provide a name for the key") + return + } + name := args[0] - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // newCmd.PersistentFlags().String("foo", "", "A help for foo") + // TODO: own function??? + pass, err := getPassword("Enter a passphrase:") + if err != nil { + fmt.Println(err.Error()) + return + } + pass2, err := getPassword("Repeat the passphrase:") + if err != nil { + fmt.Println(err.Error()) + return + } + if pass != pass2 { + fmt.Println("Passphrases don't match") + return + } - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // newCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + info, err := manager.Create(name, pass) + if err != nil { + fmt.Println(err.Error()) + return + } + printInfo(info) } diff --git a/cmd/root.go b/cmd/root.go index 05fffd489..9d7ae9a9e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,16 +17,22 @@ package cmd import ( "fmt" "os" + "path/filepath" "strings" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" + keys "github.com/tendermint/go-keys" + "github.com/tendermint/go-keys/cryptostore" + "github.com/tendermint/go-keys/storage/filestorage" ) var ( rootDir string - format string + output string + keyDir string + manager keys.Manager ) // RootCmd represents the base command when called without any subcommands @@ -53,7 +59,8 @@ func Execute() { func init() { cobra.OnInitialize(initEnv) RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data (default is TM_ROOT or $HOME/.tlc)") - RootCmd.PersistentFlags().StringP("format", "f", "text", "Output format (text|json)") + RootCmd.PersistentFlags().StringP("output", "o", "text", "Output format (text|json)") + RootCmd.PersistentFlags().StringP("keydir", "", "keys", "Directory to store private keys (subdir of root)") } // initEnv sets to use ENV variables if set. @@ -85,11 +92,25 @@ func bindFlags(cmd *cobra.Command, args []string) error { // validateFlags asserts all RootCmd flags are valid func validateFlags(cmd *cobra.Command) error { - format = viper.GetString("format") - switch format { + // validate output format + output = viper.GetString("output") + switch output { case "text", "json": - return nil default: - return errors.Errorf("Unsupported format: %s", format) + return errors.Errorf("Unsupported output format: %s", output) } + + // store the keys directory + keyDir = viper.GetString("keydir") + if !filepath.IsAbs(keyDir) { + keyDir = filepath.Join(rootDir, keyDir) + } + // and construct the key manager + manager = cryptostore.New( + cryptostore.GenEd25519, // TODO - cli switch??? + cryptostore.SecretBox, + filestorage.New(keyDir), + ) + + return nil } diff --git a/cmd/utils.go b/cmd/utils.go new file mode 100644 index 000000000..bd067f9ca --- /dev/null +++ b/cmd/utils.go @@ -0,0 +1,56 @@ +package cmd + +import ( + "fmt" + + "github.com/bgentry/speakeasy" + "github.com/pkg/errors" + data "github.com/tendermint/go-data" + keys "github.com/tendermint/go-keys" +) + +const PassLength = 10 + +func getPassword(prompt string) (string, error) { + pass, err := speakeasy.Ask(prompt) + if err != nil { + return "", err + } + if len(pass) < PassLength { + return "", errors.Errorf("Password must be at least %d characters", PassLength) + } + return pass, nil +} + +func printInfo(info keys.Info) { + switch output { + case "text": + key, err := data.ToText(info.PubKey) + if err != nil { + panic(err) // really shouldn't happen... + } + fmt.Printf("%s\t%s\n", info.Name, key) + case "json": + json, err := data.ToJSON(info) + if err != nil { + panic(err) // really shouldn't happen... + } + fmt.Println(string(json)) + } +} + +func printInfos(infos keys.Infos) { + switch output { + case "text": + fmt.Println("All keys:") + for _, i := range infos { + printInfo(i) + } + case "json": + json, err := data.ToJSON(infos) + if err != nil { + panic(err) // really shouldn't happen... + } + fmt.Println(string(json)) + } +} diff --git a/cryptostore/enc_storage.go b/cryptostore/enc_storage.go index 0a935075f..759ca90e9 100644 --- a/cryptostore/enc_storage.go +++ b/cryptostore/enc_storage.go @@ -21,7 +21,7 @@ func (es encryptedStorage) Put(name, pass string, key crypto.PrivKey) error { return es.store.Put(name, secret, ki) } -func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.KeyInfo, error) { +func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.Info, error) { secret, info, err := es.store.Get(name) if err != nil { return nil, info, err @@ -30,7 +30,7 @@ func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.KeyInfo, return key, info, err } -func (es encryptedStorage) List() ([]keys.KeyInfo, error) { +func (es encryptedStorage) List() (keys.Infos, error) { return es.store.List() } @@ -39,8 +39,8 @@ func (es encryptedStorage) Delete(name string) error { } // info hardcodes the encoding of keys -func info(name string, key crypto.PrivKey) keys.KeyInfo { - return keys.KeyInfo{ +func info(name string, key crypto.PrivKey) keys.Info { + return keys.Info{ Name: name, PubKey: crypto.PubKeyS{key.PubKey()}, } diff --git a/cryptostore/holder.go b/cryptostore/holder.go index 4beb64160..29682a87d 100644 --- a/cryptostore/holder.go +++ b/cryptostore/holder.go @@ -24,28 +24,28 @@ func (s Manager) assertSigner() keys.Signer { return s } -// exists just to make sure we fulfill the KeyManager interface -func (s Manager) assertKeyManager() keys.KeyManager { +// exists just to make sure we fulfill the Manager interface +func (s Manager) assertKeyManager() keys.Manager { return s } // Create adds a new key to the storage engine, returning error if // another key already stored under this name -func (s Manager) Create(name, passphrase string) error { +func (s Manager) Create(name, passphrase string) (keys.Info, error) { key := s.gen.Generate() - return s.es.Put(name, passphrase, key) + err := s.es.Put(name, passphrase, key) + return info(name, key), err } // List loads the keys from the storage and enforces alphabetical order -func (s Manager) List() (keys.KeyInfos, error) { - k, err := s.es.List() - res := keys.KeyInfos(k) +func (s Manager) List() (keys.Infos, error) { + res, err := s.es.List() res.Sort() return res, err } // Get returns the public information about one key -func (s Manager) Get(name string) (keys.KeyInfo, error) { +func (s Manager) Get(name string) (keys.Info, error) { _, info, err := s.es.store.Get(name) return info, err } diff --git a/cryptostore/holder_test.go b/cryptostore/holder_test.go index fb5ef854f..116b92c4e 100644 --- a/cryptostore/holder_test.go +++ b/cryptostore/holder_test.go @@ -31,9 +31,10 @@ func TestKeyManagement(t *testing.T) { // create some keys _, err = cstore.Get(n1) assert.NotNil(err) - err = cstore.Create(n1, p1) + i, err := cstore.Create(n1, p1) + require.Equal(n1, i.Name) require.Nil(err) - err = cstore.Create(n2, p2) + _, err = cstore.Create(n2, p2) require.Nil(err) // we can get these keys @@ -159,7 +160,7 @@ func TestAdvancedKeyManagement(t *testing.T) { p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$" // make sure key works with initial password - err := cstore.Create(n1, p1) + _, err := cstore.Create(n1, p1) require.Nil(err, "%+v", err) assertPassword(assert, cstore, n1, p1, p2) diff --git a/cryptostore/storage_test.go b/cryptostore/storage_test.go index 6c6ea5e2c..78d107c11 100644 --- a/cryptostore/storage_test.go +++ b/cryptostore/storage_test.go @@ -15,7 +15,7 @@ func TestSortKeys(t *testing.T) { // alphabetical order is n3, n1, n2 n1, n2, n3 := "john", "mike", "alice" - infos := keys.KeyInfos{ + infos := keys.Infos{ info(n1, gen()), info(n2, gen()), info(n3, gen()), diff --git a/keys.toml b/keys.toml index 41f4d5286..f9eb95e1c 100644 --- a/keys.toml +++ b/keys.toml @@ -1 +1,2 @@ -format = "text" +output = "text" +keydir = ".mykeys" diff --git a/storage.go b/storage.go index 519ce1aa8..0c25eb8a5 100644 --- a/storage.go +++ b/storage.go @@ -3,8 +3,8 @@ package keys // Storage has many implementation, based on security and sharing requirements // like disk-backed, mem-backed, vault, db, etc. type Storage interface { - Put(name string, key []byte, info KeyInfo) error - Get(name string) ([]byte, KeyInfo, error) - List() ([]KeyInfo, error) + Put(name string, key []byte, info Info) error + Get(name string) ([]byte, Info, error) + List() (Infos, error) Delete(name string) error } diff --git a/storage/filestorage/main.go b/storage/filestorage/main.go index 554a36540..0396c9532 100644 --- a/storage/filestorage/main.go +++ b/storage/filestorage/main.go @@ -49,7 +49,7 @@ func (s FileStore) assertStorage() keys.Storage { // Put creates two files, one with the public info as json, the other // with the (encoded) private key as gpg ascii-armor style -func (s FileStore) Put(name string, key []byte, info keys.KeyInfo) error { +func (s FileStore) Put(name string, key []byte, info keys.Info) error { pub, priv := s.nameToPaths(name) // write public info @@ -62,10 +62,10 @@ func (s FileStore) Put(name string, key []byte, info keys.KeyInfo) error { return write(priv, name, key) } -// Get loads the keyinfo and (encoded) private key from the directory +// Get loads the info and (encoded) private key from the directory // It uses `name` to generate the filename, and returns an error if the // files don't exist or are in the incorrect format -func (s FileStore) Get(name string) ([]byte, keys.KeyInfo, error) { +func (s FileStore) Get(name string) ([]byte, keys.Info, error) { pub, priv := s.nameToPaths(name) info, err := readInfo(pub) @@ -78,8 +78,8 @@ func (s FileStore) Get(name string) ([]byte, keys.KeyInfo, error) { } // List parses the key directory for public info and returns a list of -// KeyInfo for all keys located in this directory. -func (s FileStore) List() ([]keys.KeyInfo, error) { +// Info for all keys located in this directory. +func (s FileStore) List() (keys.Infos, error) { dir, err := os.Open(s.keyDir) if err != nil { return nil, errors.Wrap(err, "List Keys") @@ -91,7 +91,7 @@ func (s FileStore) List() ([]keys.KeyInfo, error) { // filter names for .pub ending and load them one by one // half the files is a good guess for pre-allocating the slice - infos := make([]keys.KeyInfo, 0, len(names)/2) + infos := make([]keys.Info, 0, len(names)/2) for _, name := range names { if strings.HasSuffix(name, PubExt) { p := path.Join(s.keyDir, name) @@ -124,11 +124,11 @@ func (s FileStore) nameToPaths(name string) (pub, priv string) { return path.Join(s.keyDir, pubName), path.Join(s.keyDir, privName) } -func writeInfo(path string, info keys.KeyInfo) error { +func writeInfo(path string, info keys.Info) error { return write(path, info.Name, info.PubKey.Bytes()) } -func readInfo(path string) (info keys.KeyInfo, err error) { +func readInfo(path string) (info keys.Info, err error) { var data []byte data, info.Name, err = read(path) if err != nil { diff --git a/storage/filestorage/main_test.go b/storage/filestorage/main_test.go index f81ba7198..b27fecfb7 100644 --- a/storage/filestorage/main_test.go +++ b/storage/filestorage/main_test.go @@ -23,7 +23,7 @@ func TestBasicCRUD(t *testing.T) { name := "bar" key := []byte("secret-key-here") pubkey := crypto.GenPrivKeyEd25519().PubKey() - info := keys.KeyInfo{ + info := keys.Info{ Name: name, PubKey: crypto.PubKeyS{pubkey}, } diff --git a/storage/memstorage/main.go b/storage/memstorage/main.go index e6573eb9f..9f671e484 100644 --- a/storage/memstorage/main.go +++ b/storage/memstorage/main.go @@ -11,7 +11,7 @@ import ( ) type data struct { - info keys.KeyInfo + info keys.Info key []byte } @@ -29,7 +29,7 @@ func (s MemStore) assertStorage() keys.Storage { // Put adds the given key, returns an error if it another key // is already stored under this name -func (s MemStore) Put(name string, key []byte, info keys.KeyInfo) error { +func (s MemStore) Put(name string, key []byte, info keys.Info) error { if _, ok := s[name]; ok { return errors.Errorf("Key named '%s' already exists", name) } @@ -38,7 +38,7 @@ func (s MemStore) Put(name string, key []byte, info keys.KeyInfo) error { } // Get returns the key stored under the name, or returns an error if not present -func (s MemStore) Get(name string) ([]byte, keys.KeyInfo, error) { +func (s MemStore) Get(name string) ([]byte, keys.Info, error) { var err error d, ok := s[name] if !ok { @@ -48,8 +48,8 @@ func (s MemStore) Get(name string) ([]byte, keys.KeyInfo, error) { } // List returns the public info of all keys in the MemStore in unsorted order -func (s MemStore) List() ([]keys.KeyInfo, error) { - res := make([]keys.KeyInfo, len(s)) +func (s MemStore) List() (keys.Infos, error) { + res := make([]keys.Info, len(s)) i := 0 for _, d := range s { res[i] = d.info diff --git a/storage/memstorage/main_test.go b/storage/memstorage/main_test.go index 01c015a15..2863bffad 100644 --- a/storage/memstorage/main_test.go +++ b/storage/memstorage/main_test.go @@ -15,7 +15,7 @@ func TestBasicCRUD(t *testing.T) { name := "foo" key := []byte("secret-key-here") pubkey := crypto.GenPrivKeyEd25519().PubKey() - info := keys.KeyInfo{ + info := keys.Info{ Name: name, PubKey: crypto.PubKeyS{pubkey}, } diff --git a/transactions.go b/transactions.go index f22719f7e..13f38b41c 100644 --- a/transactions.go +++ b/transactions.go @@ -6,19 +6,19 @@ import ( crypto "github.com/tendermint/go-crypto" ) -// KeyInfo is the public information about a key -type KeyInfo struct { +// Info is the public information about a key +type Info struct { Name string PubKey crypto.PubKeyS } -// KeyInfos is a wrapper to allows alphabetical sorting of the keys -type KeyInfos []KeyInfo +// Infos is a wrapper to allows alphabetical sorting of the keys +type Infos []Info -func (k KeyInfos) Len() int { return len(k) } -func (k KeyInfos) Less(i, j int) bool { return k[i].Name < k[j].Name } -func (k KeyInfos) Swap(i, j int) { k[i], k[j] = k[j], k[i] } -func (k KeyInfos) Sort() { +func (k Infos) Len() int { return len(k) } +func (k Infos) Less(i, j int) bool { return k[i].Name < k[j].Name } +func (k Infos) Swap(i, j int) { k[i], k[j] = k[j], k[i] } +func (k Infos) Sort() { if k != nil { sort.Sort(k) } @@ -51,11 +51,11 @@ type Signer interface { Sign(name, passphrase string, tx Signable) error } -// KeyManager allows simple CRUD on a keystore, as an aid to signing -type KeyManager interface { - Create(name, passphrase string) error - List() (KeyInfos, error) - Get(name string) (KeyInfo, error) +// Manager allows simple CRUD on a keystore, as an aid to signing +type Manager interface { + Create(name, passphrase string) (Info, error) + List() (Infos, error) + Get(name string) (Info, error) Update(name, oldpass, newpass string) error Delete(name, passphrase string) error } From 9c427e95e224e8e375c586e5cbeafe17fa4a1ce6 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 19:02:24 +0100 Subject: [PATCH 033/273] Add update cli command, cleanup --- cmd/new.go | 14 ++------------ cmd/update.go | 34 +++++++++++++++++++++++++++------- cmd/utils.go | 16 ++++++++++++++++ 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/cmd/new.go b/cmd/new.go index 38d9762f9..03e8fd2ce 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -36,26 +36,16 @@ func init() { func newPassword(cmd *cobra.Command, args []string) { if len(args) != 1 || len(args[0]) == 0 { - fmt.Print("You must provide a name for the key") + fmt.Println("You must provide a name for the key") return } name := args[0] - // TODO: own function??? - pass, err := getPassword("Enter a passphrase:") + pass, err := getCheckPassword("Enter a passphrase:", "Repeat the passphrase:") if err != nil { fmt.Println(err.Error()) return } - pass2, err := getPassword("Repeat the passphrase:") - if err != nil { - fmt.Println(err.Error()) - return - } - if pass != pass2 { - fmt.Println("Passphrases don't match") - return - } info, err := manager.Create(name, pass) if err != nil { diff --git a/cmd/update.go b/cmd/update.go index c36bcf25a..9b5387cb9 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -18,7 +18,6 @@ import ( "fmt" "github.com/spf13/cobra" - "github.com/spf13/viper" ) // updateCmd represents the update command @@ -26,14 +25,35 @@ var updateCmd = &cobra.Command{ Use: "update", Short: "Change the password for a private key", Long: `Change the password for a private key.`, - Run: func(cmd *cobra.Command, args []string) { - // TODO: Work your own magic here - fmt.Println(viper.Get("name")) - fmt.Println("update called") - }, + Run: updatePassword, } func init() { RootCmd.AddCommand(updateCmd) - updateCmd.Flags().StringP("name", "n", "", "Name of key to update") +} + +func updatePassword(cmd *cobra.Command, args []string) { + if len(args) != 1 || len(args[0]) == 0 { + fmt.Println("You must provide a name for the key") + return + } + name := args[0] + + oldpass, err := getPassword("Enter the current passphrase:") + if err != nil { + fmt.Println(err.Error()) + return + } + newpass, err := getCheckPassword("Enter the new passphrase:", "Repeat the new passphrase:") + if err != nil { + fmt.Println(err.Error()) + return + } + + err = manager.Update(name, oldpass, newpass) + if err != nil { + fmt.Println(err.Error()) + } else { + fmt.Println("Password successfully updated!") + } } diff --git a/cmd/utils.go b/cmd/utils.go index bd067f9ca..9a62fe7e8 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -22,6 +22,22 @@ func getPassword(prompt string) (string, error) { return pass, nil } +func getCheckPassword(prompt, prompt2 string) (string, error) { + // TODO: own function??? + pass, err := getPassword(prompt) + if err != nil { + return "", err + } + pass2, err := getPassword(prompt2) + if err != nil { + return "", err + } + if pass != pass2 { + return "", errors.New("Passphrases don't match") + } + return pass, nil +} + func printInfo(info keys.Info) { switch output { case "text": From d5931c9ee39c1482492279cbdc242456bbbc5453 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 19:43:18 +0100 Subject: [PATCH 034/273] Set key algorithm on key creation --- .gitignore | 1 + cmd/README.md | 76 ++++++++++++++++++++++++++++++++++++++ cmd/new.go | 5 ++- cmd/root.go | 5 +-- cryptostore/generator.go | 16 +++++++- cryptostore/holder.go | 19 ++++++---- cryptostore/holder_test.go | 11 +++--- transactions.go | 2 +- 8 files changed, 117 insertions(+), 18 deletions(-) create mode 100644 .gitignore create mode 100644 cmd/README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..cfaef8179 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.mykeys diff --git a/cmd/README.md b/cmd/README.md new file mode 100644 index 000000000..97ea787c9 --- /dev/null +++ b/cmd/README.md @@ -0,0 +1,76 @@ +# Keys CLI + +This is as much an example how to expose cobra/viper, as for a cli itself +(I think this code is overkill for what go-keys needs). But please look at +the commands, and give feedback and changes. + +`RootCmd` calls some initialization functions (`cobra.OnInitialize` and `RootCmd.PersistentPreRunE`) which serve to connect environmental variables and cobra flags, as well as load the config file. It also validates the flags registered on root and creates the cryptomanager, which will be used by all subcommands. + +## Help info + +``` +# keys help +Keys allows you to manage your local keystore for tendermint. + +These keys may be in any format supported by go-crypto and can be +used by light-clients, full nodes, or any other application that +needs to sign with a private key. + +Usage: + keys [command] + +Available Commands: + list List all keys + new Create a new public/private key pair + serve Run the key manager as an http server + update Change the password for a private key + +Flags: + --keydir string Directory to store private keys (subdir of root) (default "keys") + -o, --output string Output format (text|json) (default "text") + -r, --root string root directory for config and data (default "/Users/ethan/.tlc") + +Use "keys [command] --help" for more information about a command.``` + +## Getting the config file + +The first step is to load in root, by checking the following in order: + +* -r, --root command line flag +* TM_ROOT environmental variable +* default ($HOME/.tlc evaluated at runtime) + +Once the `rootDir` is established, the script looks for a config file named `keys.{json,toml,yaml,hcl}` in that directory and parses it. These values will provide defaults for flags of the same name. + +## Getting/Setting variables + +When we want to get the value of a user-defined variable (eg. `output`), we can call `viper.GetString("output")`, which will do the following checks, until it finds a match: + +* Is `--output` command line flag present? +* Is `TM_OUTPUT` environmental variable set? +* Was a config file found and does it have an `output` variable? +* Is there a default set on the command line flag? + +If no variable is set and there was no default, we get back "". + +This setup allows us to have powerful command line flags, but use env variables or config files (local or 12-factor style) to avoid passing these arguments every time. + +## Nesting structures + +Sometimes we don't just need key-value pairs, but actually a multi-level config file, like + +``` +[mail] +from = "no-reply@example.com" +server = "mail.example.com" +port = 567 +password = "XXXXXX" +``` + +This CLI is too simple to warant such a structure, but I think eg. tendermint could benefit from such an approach. Here are some pointers: + +* [Accessing nested keys from config files](https://github.com/spf13/viper#accessing-nested-keys) +* [Overriding nested values with envvars](https://www.netlify.com/blog/2016/09/06/creating-a-microservice-boilerplate-in-go/#nested-config-values) - the mentioned outstanding PR is already merged into master! +* Overriding nested values with cli flags? (use `--log_config.level=info` ??) + +I'd love to see an example of this fully worked out in a more complex CLI. diff --git a/cmd/new.go b/cmd/new.go index 03e8fd2ce..5ac0d3b90 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -18,6 +18,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/spf13/viper" ) // newCmd represents the new command @@ -32,6 +33,7 @@ passed as a command line argument for security.`, func init() { RootCmd.AddCommand(newCmd) + newCmd.Flags().StringP("type", "t", "ed25519", "Type of key (ed25519|secp256k1") } func newPassword(cmd *cobra.Command, args []string) { @@ -40,6 +42,7 @@ func newPassword(cmd *cobra.Command, args []string) { return } name := args[0] + algo := viper.GetString("type") pass, err := getCheckPassword("Enter a passphrase:", "Repeat the passphrase:") if err != nil { @@ -47,7 +50,7 @@ func newPassword(cmd *cobra.Command, args []string) { return } - info, err := manager.Create(name, pass) + info, err := manager.Create(name, pass, algo) if err != nil { fmt.Println(err.Error()) return diff --git a/cmd/root.go b/cmd/root.go index 9d7ae9a9e..7f5122af2 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -58,9 +58,9 @@ func Execute() { func init() { cobra.OnInitialize(initEnv) - RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data (default is TM_ROOT or $HOME/.tlc)") + RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data") RootCmd.PersistentFlags().StringP("output", "o", "text", "Output format (text|json)") - RootCmd.PersistentFlags().StringP("keydir", "", "keys", "Directory to store private keys (subdir of root)") + RootCmd.PersistentFlags().String("keydir", "keys", "Directory to store private keys (subdir of root)") } // initEnv sets to use ENV variables if set. @@ -107,7 +107,6 @@ func validateFlags(cmd *cobra.Command) error { } // and construct the key manager manager = cryptostore.New( - cryptostore.GenEd25519, // TODO - cli switch??? cryptostore.SecretBox, filestorage.New(keyDir), ) diff --git a/cryptostore/generator.go b/cryptostore/generator.go index c6661fb34..cf877f20b 100644 --- a/cryptostore/generator.go +++ b/cryptostore/generator.go @@ -1,6 +1,9 @@ package cryptostore -import crypto "github.com/tendermint/go-crypto" +import ( + "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" +) var ( // GenEd25519 produces Ed25519 private keys @@ -28,3 +31,14 @@ func genEd25519() crypto.PrivKey { func genSecp256() crypto.PrivKey { return crypto.GenPrivKeySecp256k1() } + +func getGenerator(algo string) (Generator, error) { + switch algo { + case crypto.NameEd25519: + return GenEd25519, nil + case crypto.NameSecp256k1: + return GenSecp256k1, nil + default: + return nil, errors.Errorf("Cannot generate keys for algorithm: %s", algo) + } +} diff --git a/cryptostore/holder.go b/cryptostore/holder.go index 29682a87d..549326614 100644 --- a/cryptostore/holder.go +++ b/cryptostore/holder.go @@ -5,13 +5,11 @@ import keys "github.com/tendermint/go-keys" // Manager combines encyption and storage implementation to provide // a full-featured key manager type Manager struct { - gen Generator - es encryptedStorage + es encryptedStorage } -func New(gen Generator, coder Encoder, store keys.Storage) Manager { +func New(coder Encoder, store keys.Storage) Manager { return Manager{ - gen: gen, es: encryptedStorage{ coder: coder, store: store, @@ -31,9 +29,16 @@ func (s Manager) assertKeyManager() keys.Manager { // Create adds a new key to the storage engine, returning error if // another key already stored under this name -func (s Manager) Create(name, passphrase string) (keys.Info, error) { - key := s.gen.Generate() - err := s.es.Put(name, passphrase, key) +// +// algo must be a supported go-crypto algorithm: +// +func (s Manager) Create(name, passphrase, algo string) (keys.Info, error) { + gen, err := getGenerator(algo) + if err != nil { + return keys.Info{}, err + } + key := gen.Generate() + err = s.es.Put(name, passphrase, key) return info(name, key), err } diff --git a/cryptostore/holder_test.go b/cryptostore/holder_test.go index 116b92c4e..860869c86 100644 --- a/cryptostore/holder_test.go +++ b/cryptostore/holder_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-keys/cryptostore" "github.com/tendermint/go-keys/storage/memstorage" ) @@ -15,11 +16,11 @@ func TestKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := cryptostore.New( - cryptostore.GenSecp256k1, cryptostore.SecretBox, memstorage.New(), ) + algo := crypto.NameEd25519 n1, n2, n3 := "personal", "business", "other" p1, p2 := "1234", "really-secure!@#$" @@ -31,10 +32,10 @@ func TestKeyManagement(t *testing.T) { // create some keys _, err = cstore.Get(n1) assert.NotNil(err) - i, err := cstore.Create(n1, p1) + i, err := cstore.Create(n1, p1, algo) require.Equal(n1, i.Name) require.Nil(err) - _, err = cstore.Create(n2, p2) + _, err = cstore.Create(n2, p2, algo) require.Nil(err) // we can get these keys @@ -151,16 +152,16 @@ func TestAdvancedKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := cryptostore.New( - cryptostore.GenSecp256k1, cryptostore.SecretBox, memstorage.New(), ) + algo := crypto.NameSecp256k1 n1, n2 := "old-name", "new name" p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$" // make sure key works with initial password - _, err := cstore.Create(n1, p1) + _, err := cstore.Create(n1, p1, algo) require.Nil(err, "%+v", err) assertPassword(assert, cstore, n1, p1, p2) diff --git a/transactions.go b/transactions.go index 13f38b41c..3acb476cf 100644 --- a/transactions.go +++ b/transactions.go @@ -53,7 +53,7 @@ type Signer interface { // Manager allows simple CRUD on a keystore, as an aid to signing type Manager interface { - Create(name, passphrase string) (Info, error) + Create(name, passphrase, algo string) (Info, error) List() (Infos, error) Get(name string) (Info, error) Update(name, oldpass, newpass string) error From c59e2d7d13084fb4860fbe4b67db4bef4760e622 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 20:07:44 +0100 Subject: [PATCH 035/273] Expose address in keyinfo, add get command --- cmd/README.md | 7 ++++- cmd/get.go | 47 ++++++++++++++++++++++++++++++++ cmd/root.go | 3 +- cmd/update.go | 2 +- cmd/utils.go | 8 ++++-- cryptostore/enc_storage.go | 6 ++-- storage/filestorage/main.go | 4 +-- storage/filestorage/main_test.go | 6 ++-- storage/memstorage/main.go | 4 +-- storage/memstorage/main_test.go | 6 ++-- transactions.go | 13 +++++++-- 11 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 cmd/get.go diff --git a/cmd/README.md b/cmd/README.md index 97ea787c9..72f202bf1 100644 --- a/cmd/README.md +++ b/cmd/README.md @@ -10,6 +10,7 @@ the commands, and give feedback and changes. ``` # keys help + Keys allows you to manage your local keystore for tendermint. These keys may be in any format supported by go-crypto and can be @@ -20,6 +21,7 @@ Usage: keys [command] Available Commands: + get Get details of one key list List all keys new Create a new public/private key pair serve Run the key manager as an http server @@ -30,7 +32,8 @@ Flags: -o, --output string Output format (text|json) (default "text") -r, --root string root directory for config and data (default "/Users/ethan/.tlc") -Use "keys [command] --help" for more information about a command.``` +Use "keys [command] --help" for more information about a command. +``` ## Getting the config file @@ -42,6 +45,8 @@ The first step is to load in root, by checking the following in order: Once the `rootDir` is established, the script looks for a config file named `keys.{json,toml,yaml,hcl}` in that directory and parses it. These values will provide defaults for flags of the same name. +There is an example config file for testing out locally, which writes keys to `./.mykeys`. You can + ## Getting/Setting variables When we want to get the value of a user-defined variable (eg. `output`), we can call `viper.GetString("output")`, which will do the following checks, until it finds a match: diff --git a/cmd/get.go b/cmd/get.go new file mode 100644 index 000000000..d945809f9 --- /dev/null +++ b/cmd/get.go @@ -0,0 +1,47 @@ +// Copyright © 2017 Ethan Frey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// getCmd represents the get command +var getCmd = &cobra.Command{ + Use: "get ", + Short: "Get details of one key", + Long: `Return public details of one local key.`, + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 1 || len(args[0]) == 0 { + fmt.Println("You must provide a name for the key") + return + } + name := args[0] + + info, err := manager.Get(name) + if err != nil { + fmt.Println(err.Error()) + return + } + + printInfo(info) + }, +} + +func init() { + RootCmd.AddCommand(getCmd) +} diff --git a/cmd/root.go b/cmd/root.go index 7f5122af2..029c37f9d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -84,7 +84,8 @@ func bindFlags(cmd *cobra.Command, args []string) error { // If a config file is found, read it in. if err := viper.ReadInConfig(); err == nil { - fmt.Println("Using config file:", viper.ConfigFileUsed()) + // stderr, so if we redirect output to json file, this doesn't appear + fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) } return validateFlags(cmd) diff --git a/cmd/update.go b/cmd/update.go index 9b5387cb9..0340944be 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -22,7 +22,7 @@ import ( // updateCmd represents the update command var updateCmd = &cobra.Command{ - Use: "update", + Use: "update ", Short: "Change the password for a private key", Long: `Change the password for a private key.`, Run: updatePassword, diff --git a/cmd/utils.go b/cmd/utils.go index 9a62fe7e8..01f9801ae 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -41,11 +41,15 @@ func getCheckPassword(prompt, prompt2 string) (string, error) { func printInfo(info keys.Info) { switch output { case "text": - key, err := data.ToText(info.PubKey) + addr, err := data.ToText(info.Address) if err != nil { panic(err) // really shouldn't happen... } - fmt.Printf("%s\t%s\n", info.Name, key) + sep := "\t\t" + if len(info.Name) > 7 { + sep = "\t" + } + fmt.Printf("%s%s%s\n", info.Name, sep, addr) case "json": json, err := data.ToJSON(info) if err != nil { diff --git a/cryptostore/enc_storage.go b/cryptostore/enc_storage.go index 759ca90e9..9589f4cc1 100644 --- a/cryptostore/enc_storage.go +++ b/cryptostore/enc_storage.go @@ -40,8 +40,10 @@ func (es encryptedStorage) Delete(name string) error { // info hardcodes the encoding of keys func info(name string, key crypto.PrivKey) keys.Info { + pub := key.PubKey() return keys.Info{ - Name: name, - PubKey: crypto.PubKeyS{key.PubKey()}, + Name: name, + Address: pub.Address(), + PubKey: crypto.PubKeyS{pub}, } } diff --git a/storage/filestorage/main.go b/storage/filestorage/main.go index 0396c9532..4b7dbe525 100644 --- a/storage/filestorage/main.go +++ b/storage/filestorage/main.go @@ -74,7 +74,7 @@ func (s FileStore) Get(name string) ([]byte, keys.Info, error) { } key, _, err := read(priv) - return key, info, err + return key, info.Format(), err } // List parses the key directory for public info and returns a list of @@ -99,7 +99,7 @@ func (s FileStore) List() (keys.Infos, error) { if err != nil { return nil, err } - infos = append(infos, info) + infos = append(infos, info.Format()) } } diff --git a/storage/filestorage/main_test.go b/storage/filestorage/main_test.go index b27fecfb7..c9c55eb02 100644 --- a/storage/filestorage/main_test.go +++ b/storage/filestorage/main_test.go @@ -49,11 +49,13 @@ func TestBasicCRUD(t *testing.T) { k, i, err := store.Get(name) require.Nil(err, "%+v", err) assert.Equal(key, k) - assert.Equal(info, i) + assert.Equal(info.Name, i.Name) + assert.Equal(info.PubKey, i.PubKey) + assert.NotEmpty(i.Address) l, err = store.List() require.Nil(err, "%+v", err) assert.Equal(1, len(l)) - assert.Equal(info, l[0]) + assert.Equal(i, l[0]) // querying a non-existent key fails _, _, err = store.Get("badname") diff --git a/storage/memstorage/main.go b/storage/memstorage/main.go index 9f671e484..69c8d9b03 100644 --- a/storage/memstorage/main.go +++ b/storage/memstorage/main.go @@ -44,7 +44,7 @@ func (s MemStore) Get(name string) ([]byte, keys.Info, error) { if !ok { err = errors.Errorf("Key named '%s' doesn't exist", name) } - return d.key, d.info, err + return d.key, d.info.Format(), err } // List returns the public info of all keys in the MemStore in unsorted order @@ -52,7 +52,7 @@ func (s MemStore) List() (keys.Infos, error) { res := make([]keys.Info, len(s)) i := 0 for _, d := range s { - res[i] = d.info + res[i] = d.info.Format() i++ } return res, nil diff --git a/storage/memstorage/main_test.go b/storage/memstorage/main_test.go index 2863bffad..7605c8225 100644 --- a/storage/memstorage/main_test.go +++ b/storage/memstorage/main_test.go @@ -41,11 +41,13 @@ func TestBasicCRUD(t *testing.T) { k, i, err := store.Get(name) assert.Nil(err) assert.Equal(key, k) - assert.Equal(info, i) + assert.Equal(info.Name, i.Name) + assert.Equal(info.PubKey, i.PubKey) + assert.NotEmpty(i.Address) l, err = store.List() assert.Nil(err) assert.Equal(1, len(l)) - assert.Equal(info, l[0]) + assert.Equal(i, l[0]) // querying a non-existent key fails _, _, err = store.Get("badname") diff --git a/transactions.go b/transactions.go index 3acb476cf..91dc0e273 100644 --- a/transactions.go +++ b/transactions.go @@ -4,12 +4,21 @@ import ( "sort" crypto "github.com/tendermint/go-crypto" + data "github.com/tendermint/go-data" ) // Info is the public information about a key type Info struct { - Name string - PubKey crypto.PubKeyS + Name string `json:"name"` + Address data.Bytes `json:"address"` + PubKey crypto.PubKeyS `json:"pubkey"` +} + +func (i *Info) Format() Info { + if !i.PubKey.Empty() { + i.Address = i.PubKey.Address() + } + return *i } // Infos is a wrapper to allows alphabetical sorting of the keys From e1c717a04863a9ddf24251a9eaec14feaf7da37a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 20:26:45 +0100 Subject: [PATCH 036/273] Add support for hex / base64 / btc (b58) encoding of binary data --- cmd/README.md | 36 ++++++++++++++++++++++++++++++++++++ cmd/root.go | 18 +++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/cmd/README.md b/cmd/README.md index 72f202bf1..8bf9ca73b 100644 --- a/cmd/README.md +++ b/cmd/README.md @@ -79,3 +79,39 @@ This CLI is too simple to warant such a structure, but I think eg. tendermint co * Overriding nested values with cli flags? (use `--log_config.level=info` ??) I'd love to see an example of this fully worked out in a more complex CLI. + +## Have your cake and eat it too + +It's easy to render data different ways. Some better for viewing, some better for importing to other programs. You can just add some global (persistent) flags to control the output formatting, and everyone gets what they want. + +``` +# keys list -e hex +All keys: +betty d0789984492b1674e276b590d56b7ae077f81adc +john b77f4720b220d1411a649b6c7f1151eb6b1c226a + +# keys list -e btc +All keys: +betty 3uTF4r29CbtnzsNHZoPSYsE4BDwH +john 3ZGp2Md35iw4XVtRvZDUaAEkCUZP + +# keys list -e b64 -o json +[ + { + "name": "betty", + "address": "0HiZhEkrFnTidrWQ1Wt64Hf4Gtw=", + "pubkey": { + "type": "secp256k1", + "data": "F83WvhT0KwttSoqQqd_0_r2ztUUaQix5EXdO8AZyREoV31Og780NW59HsqTAb2O4hZ-w-j0Z-4b2IjfdqqfhVQ==" + } + }, + { + "name": "john", + "address": "t39HILIg0UEaZJtsfxFR62scImo=", + "pubkey": { + "type": "ed25519", + "data": "t1LFmbg_8UTwj-n1wkqmnTp6NfaOivokEhlYySlGYCY=" + } + } +] +``` diff --git a/cmd/root.go b/cmd/root.go index 029c37f9d..41803fc65 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -23,6 +23,8 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" + data "github.com/tendermint/go-data" + "github.com/tendermint/go-data/base58" keys "github.com/tendermint/go-keys" "github.com/tendermint/go-keys/cryptostore" "github.com/tendermint/go-keys/storage/filestorage" @@ -59,8 +61,9 @@ func Execute() { func init() { cobra.OnInitialize(initEnv) RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data") - RootCmd.PersistentFlags().StringP("output", "o", "text", "Output format (text|json)") RootCmd.PersistentFlags().String("keydir", "keys", "Directory to store private keys (subdir of root)") + RootCmd.PersistentFlags().StringP("output", "o", "text", "Output format (text|json)") + RootCmd.PersistentFlags().StringP("encoding", "e", "hex", "Binary encoding (hex|b64|btc)") } // initEnv sets to use ENV variables if set. @@ -101,6 +104,19 @@ func validateFlags(cmd *cobra.Command) error { return errors.Errorf("Unsupported output format: %s", output) } + // validate and set encoding + enc := viper.GetString("encoding") + switch enc { + case "hex": + data.Encoder = data.HexEncoder + case "b64": + data.Encoder = data.B64Encoder + case "btc": + data.Encoder = base58.BTCEncoder + default: + return errors.Errorf("Unsupported encoding: %s", enc) + } + // store the keys directory keyDir = viper.GetString("keydir") if !filepath.IsAbs(keyDir) { From 6ec2330eb8dbecb17495d2dc0565ace570adf457 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 21:09:35 +0100 Subject: [PATCH 037/273] Import keys server from light-client, with changes --- proxy/README.md | 65 +++++++++++++++ proxy/helpers.go | 58 ++++++++++++++ proxy/keys.go | 123 ++++++++++++++++++++++++++++ proxy/keys_test.go | 190 ++++++++++++++++++++++++++++++++++++++++++++ proxy/types/keys.go | 28 +++++++ proxy/valid.go | 12 +++ 6 files changed, 476 insertions(+) create mode 100644 proxy/README.md create mode 100644 proxy/helpers.go create mode 100644 proxy/keys.go create mode 100644 proxy/keys_test.go create mode 100644 proxy/types/keys.go create mode 100644 proxy/valid.go diff --git a/proxy/README.md b/proxy/README.md new file mode 100644 index 000000000..614110b7f --- /dev/null +++ b/proxy/README.md @@ -0,0 +1,65 @@ +# Proxy Server + +This package provides all the functionality for a local proxy http server, and ties together functionality from all the other packages to acheive this aim. Simply configure this server with your application-specific settings via a main script and you are good to go. + +This server should run on the client's machine, and can accept a trusted connection from localhost (via tcp or unix socket). It provides a simple json rest API and handles all the binary wrangling and cryptographic proofs under the hood. Thus, you can host a local webapp (via electron?) and connect to this proxy, perform simple queries and posts and behind the scenes take advantage of the *awesome power* of the tendermint blockchain. + +If you are writing native code, you can use this as well, or you can look for bindings to embed this functionality directly as a library in your codebase. +**(coming soon)** + +## API + +The API has various sections based on functionality. The major portions are key management, signing and posting transactions, and querying and proving data. + +### Key Management + +We expose a number of methods for safely managing your keychain. They are typically bound under `/keys`, but could be placed in another location by the app. + +* `POST /keys/` - provide a name and passphrase and create a brand new key +* `GET /keys/` - get a list of all available key names, along with their public key and address +* `GET /keys/{name}` - get public key and address for this named key + +Later expose: + +* `PUT /keys/{name}` - update the passphrase for the given key. requires you to correctly provide the current passphrase, as well as a new one. +* `DELETE /keys/{name}` - permanently delete this private key. requires you to correctly provide the current passphrase +* export and import functionality + +### Transactions + +You want to post your transaction. Great. Your application must provide logic to transform json into a `Signable` go struct. Then we handle the rest, signing it with a keypair of your choosing, posting it to tendermint core, and returning you confirmation when it was committed. + +* `POST /txs/` - provide name, passphrase and application-specific data to post to tendermint + + +### Proving Data + +We sent some money to our friend, now we want to check his balance. No, not just look at it, but really check it, verify all those cryptographic proofs that some node is not lying and it really, truly is in his account. + +Thankfully, we have the technology and can do all the checks in the proxy, it might just take a second or two for us to get all those block headers. + +However, this still just leaves us with a bunch of binary blobs from the server, so to make this whole process less painless, you should provide some application-specific logic to parse this binary data from the blockchain, so we can present it as json over the interface. + +* `GET /query/{path}/{data}` - will quickly query the data under the given (hex-encoded) key. `path` is `key` to query by merkle key, but your application could provide other prefixes, to differentiate by types (eg. `account`, `votes`, `escrow`). The returned data is parsed into json and displayed. +* `GET /proof/{key}` - will query for a merkle proof of the given key, download block headers, and verify all the signatures of that block. After it is done, it will present you some json and a stamp that it your data is really safe and sound. + +## Configuring + +When you instantiate a server, make sure to pass in application-specific info in order to properly. Like the following info: + +Possibly as command-line flags: + +* Where to store the private keys? (or find existing ones) +* Which type of key to generate? +* What is the URL of the tendermint RPC server? + * TODO: support multiple node URLs and round-robin +* What is the chain_id we wish to connect to? + +Extra code (plugin) you must write: + +* Logic to parse json -> `Signable` transaction +* Logic to parse binary values from merkle tree -> `struct`ured data to render + +TODO: + +* How to get the trusted validator set? diff --git a/proxy/helpers.go b/proxy/helpers.go new file mode 100644 index 000000000..ac314684b --- /dev/null +++ b/proxy/helpers.go @@ -0,0 +1,58 @@ +/* +package proxy provides http handlers to construct a proxy server +for key management, transaction signing, and query validation. + +Please read the README and godoc to see how to +configure the server for your application. +*/ +package proxy + +import ( + "encoding/json" + "io/ioutil" + "net/http" + + data "github.com/tendermint/go-data" + "github.com/tendermint/go-keys/proxy/types" + + "github.com/pkg/errors" +) + +func readRequest(r *http.Request, o interface{}) error { + defer r.Body.Close() + data, err := ioutil.ReadAll(r.Body) + if err != nil { + return errors.Wrap(err, "Read Request") + } + err = json.Unmarshal(data, o) + if err != nil { + return errors.Wrap(err, "Parse") + } + return validate(o) +} + +// most errors are bad input, so 406... do better.... +func writeError(w http.ResponseWriter, err error) { + // fmt.Printf("Error: %+v\n", err) + res := types.ErrorResponse{ + Code: 406, + Error: err.Error(), + } + writeCode(w, &res, 406) +} + +func writeCode(w http.ResponseWriter, o interface{}, code int) { + // two space indent to make it easier to read + data, err := data.ToJSON(o) + if err != nil { + writeError(w, err) + } else { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(code) + w.Write(data) + } +} + +func writeSuccess(w http.ResponseWriter, o interface{}) { + writeCode(w, o, 200) +} diff --git a/proxy/keys.go b/proxy/keys.go new file mode 100644 index 000000000..64b6819cd --- /dev/null +++ b/proxy/keys.go @@ -0,0 +1,123 @@ +package proxy + +import ( + "errors" + "net/http" + + "github.com/gorilla/mux" + keys "github.com/tendermint/go-keys" + "github.com/tendermint/go-keys/proxy/types" +) + +type KeyServer struct { + manager keys.Manager +} + +func NewKeyServer(manager keys.Manager) KeyServer { + return KeyServer{ + manager: manager, + } +} + +func (k KeyServer) GenerateKey(w http.ResponseWriter, r *http.Request) { + req := types.CreateKeyRequest{} + err := readRequest(r, &req) + if err != nil { + writeError(w, err) + return + } + + key, err := k.manager.Create(req.Name, req.Passphrase, req.Algo) + if err != nil { + writeError(w, err) + return + } + + writeSuccess(w, &key) +} + +func (k KeyServer) GetKey(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + name := vars["name"] + key, err := k.manager.Get(name) + if err != nil { + writeError(w, err) + return + } + writeSuccess(w, &key) +} + +func (k KeyServer) ListKeys(w http.ResponseWriter, r *http.Request) { + + keys, err := k.manager.List() + if err != nil { + writeError(w, err) + return + } + writeSuccess(w, keys) +} + +func (k KeyServer) UpdateKey(w http.ResponseWriter, r *http.Request) { + req := types.UpdateKeyRequest{} + err := readRequest(r, &req) + if err != nil { + writeError(w, err) + return + } + + vars := mux.Vars(r) + name := vars["name"] + if name != req.Name { + writeError(w, errors.New("path and json key names don't match")) + return + } + + err = k.manager.Update(req.Name, req.OldPass, req.NewPass) + if err != nil { + writeError(w, err) + return + } + + key, err := k.manager.Get(req.Name) + if err != nil { + writeError(w, err) + return + } + writeSuccess(w, &key) +} + +func (k KeyServer) DeleteKey(w http.ResponseWriter, r *http.Request) { + req := types.DeleteKeyRequest{} + err := readRequest(r, &req) + if err != nil { + writeError(w, err) + return + } + + vars := mux.Vars(r) + name := vars["name"] + if name != req.Name { + writeError(w, errors.New("path and json key names don't match")) + return + } + + err = k.manager.Delete(req.Name, req.Passphrase) + if err != nil { + writeError(w, err) + return + } + + // not really an error, but something generic + resp := types.ErrorResponse{ + Success: true, + } + writeSuccess(w, &resp) +} + +func (k KeyServer) Register(r *mux.Router) { + r.HandleFunc("/", k.GenerateKey).Methods("POST") + r.HandleFunc("/", k.ListKeys).Methods("GET") + r.HandleFunc("/{name}", k.GetKey).Methods("GET") + r.HandleFunc("/{name}", k.UpdateKey).Methods("POST", "PUT") + r.HandleFunc("/{name}", k.DeleteKey).Methods("DELETE") +} diff --git a/proxy/keys_test.go b/proxy/keys_test.go new file mode 100644 index 000000000..6eee94e39 --- /dev/null +++ b/proxy/keys_test.go @@ -0,0 +1,190 @@ +package proxy_test + +import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gorilla/mux" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + keys "github.com/tendermint/go-keys" + "github.com/tendermint/go-keys/cryptostore" + "github.com/tendermint/go-keys/proxy" + "github.com/tendermint/go-keys/proxy/types" + "github.com/tendermint/go-keys/storage/memstorage" +) + +func TestKeyServer(t *testing.T) { + assert, require := assert.New(t), require.New(t) + r := setupServer() + + // let's abstract this out a bit.... + keys, code, err := listKeys(r) + require.Nil(err) + require.Equal(http.StatusOK, code) + assert.Equal(0, len(keys)) + + algo := "ed25519" + n1, n2 := "personal", "business" + p0, p1, p2 := "1234", "over10chars...", "really-secure!@#$" + + // this fails for validation + _, code, err = createKey(r, n1, p0, algo) + require.Nil(err, "%+v", err) + require.NotEqual(http.StatusOK, code) + + // new password better + key, code, err := createKey(r, n1, p1, algo) + require.Nil(err, "%+v", err) + require.Equal(http.StatusOK, code) + require.Equal(key.Name, n1) + + // the other one works + key2, code, err := createKey(r, n2, p2, algo) + require.Nil(err, "%+v", err) + require.Equal(http.StatusOK, code) + require.Equal(key2.Name, n2) + + // let's abstract this out a bit.... + keys, code, err = listKeys(r) + require.Nil(err) + require.Equal(http.StatusOK, code) + if assert.Equal(2, len(keys)) { + // in alphabetical order + assert.Equal(keys[0].Name, n2) + assert.Equal(keys[1].Name, n1) + } + + // get works + k, code, err := getKey(r, n1) + require.Nil(err, "%+v", err) + require.Equal(http.StatusOK, code) + assert.Equal(k.Name, n1) + assert.NotNil(k.Address) + assert.Equal(k.Address, key.Address) + + // delete with proper key + _, code, err = deleteKey(r, n1, p1) + require.Nil(err, "%+v", err) + require.Equal(http.StatusOK, code) + + // after delete, get and list different + _, code, err = getKey(r, n1) + require.Nil(err, "%+v", err) + require.NotEqual(http.StatusOK, code) + keys, code, err = listKeys(r) + require.Nil(err, "%+v", err) + require.Equal(http.StatusOK, code) + if assert.Equal(1, len(keys)) { + assert.Equal(keys[0].Name, n2) + } + +} + +func setupServer() http.Handler { + // make the storage with reasonable defaults + cstore := cryptostore.New( + cryptostore.SecretBox, + memstorage.New(), + ) + + // build your http server + ks := proxy.NewKeyServer(cstore) + r := mux.NewRouter() + sk := r.PathPrefix("/keys").Subrouter() + ks.Register(sk) + return r +} + +// return data, status code, and error +func listKeys(h http.Handler) (keys.Infos, int, error) { + rr := httptest.NewRecorder() + req, err := http.NewRequest("GET", "/keys/", nil) + if err != nil { + return nil, 0, err + } + + h.ServeHTTP(rr, req) + if http.StatusOK != rr.Code { + return nil, rr.Code, nil + } + + data := keys.Infos{} + err = json.Unmarshal(rr.Body.Bytes(), &data) + return data, rr.Code, err +} + +func getKey(h http.Handler, name string) (*keys.Info, int, error) { + rr := httptest.NewRecorder() + req, err := http.NewRequest("GET", "/keys/"+name, nil) + if err != nil { + return nil, 0, err + } + + h.ServeHTTP(rr, req) + if http.StatusOK != rr.Code { + return nil, rr.Code, nil + } + + data := keys.Info{} + err = json.Unmarshal(rr.Body.Bytes(), &data) + return &data, rr.Code, err +} + +func createKey(h http.Handler, name, passphrase, algo string) (*keys.Info, int, error) { + rr := httptest.NewRecorder() + post := types.CreateKeyRequest{ + Name: name, + Passphrase: passphrase, + Algo: algo, + } + var b bytes.Buffer + err := json.NewEncoder(&b).Encode(&post) + if err != nil { + return nil, 0, err + } + + req, err := http.NewRequest("POST", "/keys/", &b) + if err != nil { + return nil, 0, err + } + + h.ServeHTTP(rr, req) + if http.StatusOK != rr.Code { + return nil, rr.Code, nil + } + + data := keys.Info{} + err = json.Unmarshal(rr.Body.Bytes(), &data) + return &data, rr.Code, err +} + +func deleteKey(h http.Handler, name, passphrase string) (*types.ErrorResponse, int, error) { + rr := httptest.NewRecorder() + post := types.DeleteKeyRequest{ + Name: name, + Passphrase: passphrase, + } + var b bytes.Buffer + err := json.NewEncoder(&b).Encode(&post) + if err != nil { + return nil, 0, err + } + + req, err := http.NewRequest("DELETE", "/keys/"+name, &b) + if err != nil { + return nil, 0, err + } + + h.ServeHTTP(rr, req) + if http.StatusOK != rr.Code { + return nil, rr.Code, nil + } + + data := types.ErrorResponse{} + err = json.Unmarshal(rr.Body.Bytes(), &data) + return &data, rr.Code, err +} diff --git a/proxy/types/keys.go b/proxy/types/keys.go new file mode 100644 index 000000000..ffdc542f1 --- /dev/null +++ b/proxy/types/keys.go @@ -0,0 +1,28 @@ +package types + +// CreateKeyRequest is sent to create a new key +type CreateKeyRequest struct { + Name string `json:"name" validate:"required,min=4,printascii"` + Passphrase string `json:"passphrase" validate:"required,min=10"` + Algo string `json:"algo"` +} + +// DeleteKeyRequest to destroy a key permanently (careful!) +type DeleteKeyRequest struct { + Name string `json:"name" validate:"required,min=4,printascii"` + Passphrase string `json:"passphrase" validate:"required,min=10"` +} + +// UpdateKeyRequest is sent to update the passphrase for an existing key +type UpdateKeyRequest struct { + Name string `json:"name" validate:"required,min=4,printascii"` + OldPass string `json:"passphrase" validate:"required,min=10"` + NewPass string `json:"new_passphrase" validate:"required,min=10"` +} + +// ErrorResponse is returned for 4xx and 5xx errors +type ErrorResponse struct { + Success bool `json:"success"` + Error string `json:"error"` // error message if Success is false + Code int `json:"code"` // error code if Success is false +} diff --git a/proxy/valid.go b/proxy/valid.go new file mode 100644 index 000000000..31782cfca --- /dev/null +++ b/proxy/valid.go @@ -0,0 +1,12 @@ +package proxy + +import ( + "github.com/pkg/errors" + "gopkg.in/go-playground/validator.v9" +) + +var v = validator.New() + +func validate(req interface{}) error { + return errors.Wrap(v.Struct(req), "Validate") +} From 6389d208ccd68d5f921b005d60b00e3126882bec Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 21:33:27 +0100 Subject: [PATCH 038/273] Key server API integrated in CLI --- cmd/new.go | 2 +- cmd/serve.go | 78 +++++++++++++++++++++++++++++++++++++++------- proxy/keys.go | 8 +++-- proxy/keys_test.go | 2 +- 4 files changed, 75 insertions(+), 15 deletions(-) diff --git a/cmd/new.go b/cmd/new.go index 5ac0d3b90..27c7dce75 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -33,7 +33,7 @@ passed as a command line argument for security.`, func init() { RootCmd.AddCommand(newCmd) - newCmd.Flags().StringP("type", "t", "ed25519", "Type of key (ed25519|secp256k1") + newCmd.Flags().StringP("type", "t", "ed25519", "Type of key (ed25519|secp256k1)") } func newPassword(cmd *cobra.Command, args []string) { diff --git a/cmd/serve.go b/cmd/serve.go index 06e923c7b..1555c6480 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -16,8 +16,16 @@ package cmd import ( "fmt" + "net" + "net/http" + "os" + "github.com/gorilla/handlers" + "github.com/gorilla/mux" + "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/tendermint/go-keys/proxy" ) // serveCmd represents the serve command @@ -28,23 +36,71 @@ var serveCmd = &cobra.Command{ private keys much more in depth than the cli can perform. In particular, this will allow you to sign transactions with the private keys in the store.`, - Run: func(cmd *cobra.Command, args []string) { - // TODO: Work your own magic here - fmt.Println("serve called") - }, + RunE: server, } func init() { RootCmd.AddCommand(serveCmd) + serveCmd.Flags().IntP("port", "p", 8118, "TCP Port for listen for http server") + serveCmd.Flags().StringP("socket", "s", "", "UNIX socket for more secure http server") + serveCmd.Flags().StringP("type", "t", "ed25519", "Default key type (ed25519|secp256k1)") +} + +func server(cmd *cobra.Command, args []string) error { + var l net.Listener + var err error + socket := viper.GetString("socket") + if socket != "" { + l, err = createSocket(socket) + if err != nil { + return errors.Wrap(err, "Cannot create socket") + } + } else { + port := viper.GetInt("port") + l, err = net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + return errors.Errorf("Cannot listen on port %d", port) + } + } + + router := mux.NewRouter() + ks := proxy.NewKeyServer(manager, viper.GetString("type")) + ks.Register(router) + + // only set cors for tcp listener + var h http.Handler + if socket == "" { + allowedHeaders := handlers.AllowedHeaders([]string{"Content-Type"}) + h = handlers.CORS(allowedHeaders)(router) + } else { + h = router + } + + err = http.Serve(l, h) + fmt.Printf("Server Killed: %+v\n", err) + return nil +} - // Here you will define your flags and configuration settings. +// createSocket deletes existing socket if there, creates a new one, +// starts a server on the socket, and sets permissions to 0600 +func createSocket(socket string) (net.Listener, error) { + err := os.Remove(socket) + if err != nil && !os.IsNotExist(err) { + // only fail if it does exist and cannot be deleted + return nil, err + } - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // serveCmd.PersistentFlags().String("foo", "", "A help for foo") + l, err := net.Listen("unix", socket) + if err != nil { + return nil, err + } - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // serveCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + mode := os.FileMode(0700) | os.ModeSocket + err = os.Chmod(socket, mode) + if err != nil { + l.Close() + return nil, err + } + return l, nil } diff --git a/proxy/keys.go b/proxy/keys.go index 64b6819cd..0dde57074 100644 --- a/proxy/keys.go +++ b/proxy/keys.go @@ -11,16 +11,20 @@ import ( type KeyServer struct { manager keys.Manager + algo string } -func NewKeyServer(manager keys.Manager) KeyServer { +func NewKeyServer(manager keys.Manager, algo string) KeyServer { return KeyServer{ manager: manager, + algo: algo, } } func (k KeyServer) GenerateKey(w http.ResponseWriter, r *http.Request) { - req := types.CreateKeyRequest{} + req := types.CreateKeyRequest{ + Algo: k.algo, // default key type from cli + } err := readRequest(r, &req) if err != nil { writeError(w, err) diff --git a/proxy/keys_test.go b/proxy/keys_test.go index 6eee94e39..3a9c73717 100644 --- a/proxy/keys_test.go +++ b/proxy/keys_test.go @@ -92,7 +92,7 @@ func setupServer() http.Handler { ) // build your http server - ks := proxy.NewKeyServer(cstore) + ks := proxy.NewKeyServer(cstore, "ed25519") r := mux.NewRouter() sk := r.PathPrefix("/keys").Subrouter() ks.Register(sk) From 0c92c8516f530f7f58150073a03e7fc7639b1cfb Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Feb 2017 21:53:05 +0100 Subject: [PATCH 039/273] Rename proxy to server for clarity --- cmd/serve.go | 8 ++-- proxy/README.md | 65 --------------------------------- server/README.md | 13 +++++++ {proxy => server}/helpers.go | 6 +-- {proxy => server}/keys.go | 22 +++++------ {proxy => server}/keys_test.go | 8 ++-- {proxy => server}/types/keys.go | 0 {proxy => server}/valid.go | 2 +- 8 files changed, 36 insertions(+), 88 deletions(-) delete mode 100644 proxy/README.md create mode 100644 server/README.md rename {proxy => server}/helpers.go (90%) rename {proxy => server}/keys.go (77%) rename {proxy => server}/keys_test.go (96%) rename {proxy => server}/types/keys.go (100%) rename {proxy => server}/valid.go (92%) diff --git a/cmd/serve.go b/cmd/serve.go index 1555c6480..2717913fd 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -25,7 +25,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/go-keys/proxy" + "github.com/tendermint/go-keys/server" ) // serveCmd represents the serve command @@ -36,7 +36,7 @@ var serveCmd = &cobra.Command{ private keys much more in depth than the cli can perform. In particular, this will allow you to sign transactions with the private keys in the store.`, - RunE: server, + RunE: serveHTTP, } func init() { @@ -46,7 +46,7 @@ func init() { serveCmd.Flags().StringP("type", "t", "ed25519", "Default key type (ed25519|secp256k1)") } -func server(cmd *cobra.Command, args []string) error { +func serveHTTP(cmd *cobra.Command, args []string) error { var l net.Listener var err error socket := viper.GetString("socket") @@ -64,7 +64,7 @@ func server(cmd *cobra.Command, args []string) error { } router := mux.NewRouter() - ks := proxy.NewKeyServer(manager, viper.GetString("type")) + ks := server.New(manager, viper.GetString("type")) ks.Register(router) // only set cors for tcp listener diff --git a/proxy/README.md b/proxy/README.md deleted file mode 100644 index 614110b7f..000000000 --- a/proxy/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Proxy Server - -This package provides all the functionality for a local proxy http server, and ties together functionality from all the other packages to acheive this aim. Simply configure this server with your application-specific settings via a main script and you are good to go. - -This server should run on the client's machine, and can accept a trusted connection from localhost (via tcp or unix socket). It provides a simple json rest API and handles all the binary wrangling and cryptographic proofs under the hood. Thus, you can host a local webapp (via electron?) and connect to this proxy, perform simple queries and posts and behind the scenes take advantage of the *awesome power* of the tendermint blockchain. - -If you are writing native code, you can use this as well, or you can look for bindings to embed this functionality directly as a library in your codebase. -**(coming soon)** - -## API - -The API has various sections based on functionality. The major portions are key management, signing and posting transactions, and querying and proving data. - -### Key Management - -We expose a number of methods for safely managing your keychain. They are typically bound under `/keys`, but could be placed in another location by the app. - -* `POST /keys/` - provide a name and passphrase and create a brand new key -* `GET /keys/` - get a list of all available key names, along with their public key and address -* `GET /keys/{name}` - get public key and address for this named key - -Later expose: - -* `PUT /keys/{name}` - update the passphrase for the given key. requires you to correctly provide the current passphrase, as well as a new one. -* `DELETE /keys/{name}` - permanently delete this private key. requires you to correctly provide the current passphrase -* export and import functionality - -### Transactions - -You want to post your transaction. Great. Your application must provide logic to transform json into a `Signable` go struct. Then we handle the rest, signing it with a keypair of your choosing, posting it to tendermint core, and returning you confirmation when it was committed. - -* `POST /txs/` - provide name, passphrase and application-specific data to post to tendermint - - -### Proving Data - -We sent some money to our friend, now we want to check his balance. No, not just look at it, but really check it, verify all those cryptographic proofs that some node is not lying and it really, truly is in his account. - -Thankfully, we have the technology and can do all the checks in the proxy, it might just take a second or two for us to get all those block headers. - -However, this still just leaves us with a bunch of binary blobs from the server, so to make this whole process less painless, you should provide some application-specific logic to parse this binary data from the blockchain, so we can present it as json over the interface. - -* `GET /query/{path}/{data}` - will quickly query the data under the given (hex-encoded) key. `path` is `key` to query by merkle key, but your application could provide other prefixes, to differentiate by types (eg. `account`, `votes`, `escrow`). The returned data is parsed into json and displayed. -* `GET /proof/{key}` - will query for a merkle proof of the given key, download block headers, and verify all the signatures of that block. After it is done, it will present you some json and a stamp that it your data is really safe and sound. - -## Configuring - -When you instantiate a server, make sure to pass in application-specific info in order to properly. Like the following info: - -Possibly as command-line flags: - -* Where to store the private keys? (or find existing ones) -* Which type of key to generate? -* What is the URL of the tendermint RPC server? - * TODO: support multiple node URLs and round-robin -* What is the chain_id we wish to connect to? - -Extra code (plugin) you must write: - -* Logic to parse json -> `Signable` transaction -* Logic to parse binary values from merkle tree -> `struct`ured data to render - -TODO: - -* How to get the trusted validator set? diff --git a/server/README.md b/server/README.md new file mode 100644 index 000000000..032cf574e --- /dev/null +++ b/server/README.md @@ -0,0 +1,13 @@ +# Proxy Server + +This package provides all the functionality for a local http server, providing access to key management functionality (creating, listing, updating, and deleting keys). This is a nice building block for larger apps, and the HTTP handlers here can be embedded in a larger server that does nice things like signing transactions and posting them to a tendermint chain (which requires domain-knowledge of the transactions types and out of scope of this generic app). + +## Key Management + +We expose a number of methods for safely managing your keychain. If you are embedding this in a larger server, you will typically want to mount all these paths under `/keys`. + +* `POST /` - provide a name and passphrase and create a brand new key +* `GET /` - get a list of all available key names, along with their public key and address +* `GET /{name}` - get public key and address for this named key +* `PUT /{name}` - update the passphrase for the given key. requires you to correctly provide the current passphrase, as well as a new one. +* `DELETE /{name}` - permanently delete this private key. requires you to correctly provide the current passphrase diff --git a/proxy/helpers.go b/server/helpers.go similarity index 90% rename from proxy/helpers.go rename to server/helpers.go index ac314684b..111f158e7 100644 --- a/proxy/helpers.go +++ b/server/helpers.go @@ -1,11 +1,11 @@ /* -package proxy provides http handlers to construct a proxy server +package server provides http handlers to construct a server server for key management, transaction signing, and query validation. Please read the README and godoc to see how to configure the server for your application. */ -package proxy +package server import ( "encoding/json" @@ -13,7 +13,7 @@ import ( "net/http" data "github.com/tendermint/go-data" - "github.com/tendermint/go-keys/proxy/types" + "github.com/tendermint/go-keys/server/types" "github.com/pkg/errors" ) diff --git a/proxy/keys.go b/server/keys.go similarity index 77% rename from proxy/keys.go rename to server/keys.go index 0dde57074..78a382e5e 100644 --- a/proxy/keys.go +++ b/server/keys.go @@ -1,4 +1,4 @@ -package proxy +package server import ( "errors" @@ -6,22 +6,22 @@ import ( "github.com/gorilla/mux" keys "github.com/tendermint/go-keys" - "github.com/tendermint/go-keys/proxy/types" + "github.com/tendermint/go-keys/server/types" ) -type KeyServer struct { +type Keys struct { manager keys.Manager algo string } -func NewKeyServer(manager keys.Manager, algo string) KeyServer { - return KeyServer{ +func New(manager keys.Manager, algo string) Keys { + return Keys{ manager: manager, algo: algo, } } -func (k KeyServer) GenerateKey(w http.ResponseWriter, r *http.Request) { +func (k Keys) GenerateKey(w http.ResponseWriter, r *http.Request) { req := types.CreateKeyRequest{ Algo: k.algo, // default key type from cli } @@ -40,7 +40,7 @@ func (k KeyServer) GenerateKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &key) } -func (k KeyServer) GetKey(w http.ResponseWriter, r *http.Request) { +func (k Keys) GetKey(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) name := vars["name"] key, err := k.manager.Get(name) @@ -51,7 +51,7 @@ func (k KeyServer) GetKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &key) } -func (k KeyServer) ListKeys(w http.ResponseWriter, r *http.Request) { +func (k Keys) ListKeys(w http.ResponseWriter, r *http.Request) { keys, err := k.manager.List() if err != nil { @@ -61,7 +61,7 @@ func (k KeyServer) ListKeys(w http.ResponseWriter, r *http.Request) { writeSuccess(w, keys) } -func (k KeyServer) UpdateKey(w http.ResponseWriter, r *http.Request) { +func (k Keys) UpdateKey(w http.ResponseWriter, r *http.Request) { req := types.UpdateKeyRequest{} err := readRequest(r, &req) if err != nil { @@ -90,7 +90,7 @@ func (k KeyServer) UpdateKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &key) } -func (k KeyServer) DeleteKey(w http.ResponseWriter, r *http.Request) { +func (k Keys) DeleteKey(w http.ResponseWriter, r *http.Request) { req := types.DeleteKeyRequest{} err := readRequest(r, &req) if err != nil { @@ -118,7 +118,7 @@ func (k KeyServer) DeleteKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &resp) } -func (k KeyServer) Register(r *mux.Router) { +func (k Keys) Register(r *mux.Router) { r.HandleFunc("/", k.GenerateKey).Methods("POST") r.HandleFunc("/", k.ListKeys).Methods("GET") r.HandleFunc("/{name}", k.GetKey).Methods("GET") diff --git a/proxy/keys_test.go b/server/keys_test.go similarity index 96% rename from proxy/keys_test.go rename to server/keys_test.go index 3a9c73717..8333e8e53 100644 --- a/proxy/keys_test.go +++ b/server/keys_test.go @@ -1,4 +1,4 @@ -package proxy_test +package server_test import ( "bytes" @@ -12,8 +12,8 @@ import ( "github.com/stretchr/testify/require" keys "github.com/tendermint/go-keys" "github.com/tendermint/go-keys/cryptostore" - "github.com/tendermint/go-keys/proxy" - "github.com/tendermint/go-keys/proxy/types" + "github.com/tendermint/go-keys/server" + "github.com/tendermint/go-keys/server/types" "github.com/tendermint/go-keys/storage/memstorage" ) @@ -92,7 +92,7 @@ func setupServer() http.Handler { ) // build your http server - ks := proxy.NewKeyServer(cstore, "ed25519") + ks := server.New(cstore, "ed25519") r := mux.NewRouter() sk := r.PathPrefix("/keys").Subrouter() ks.Register(sk) diff --git a/proxy/types/keys.go b/server/types/keys.go similarity index 100% rename from proxy/types/keys.go rename to server/types/keys.go diff --git a/proxy/valid.go b/server/valid.go similarity index 92% rename from proxy/valid.go rename to server/valid.go index 31782cfca..50b51e21b 100644 --- a/proxy/valid.go +++ b/server/valid.go @@ -1,4 +1,4 @@ -package proxy +package server import ( "github.com/pkg/errors" From af7e3120888a199c22e94f6e9a1b1a3a0545c5ac Mon Sep 17 00:00:00 2001 From: "Paul W. Homer" Date: Thu, 2 Mar 2017 17:16:15 -0500 Subject: [PATCH 040/273] Added glide dependency handling --- .gitignore | 1 + Makefile | 19 ++++++++- glide.lock | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ glide.yaml | 19 +++++++++ 4 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 glide.lock create mode 100644 glide.yaml diff --git a/.gitignore b/.gitignore index cfaef8179..2f1e043a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .mykeys +vendor diff --git a/Makefile b/Makefile index b15317b25..63eb70787 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,22 @@ +GOTOOLS = \ + github.com/mitchellh/gox \ + github.com/Masterminds/glide + +.PHONEY: all test install get_vendor_deps ensure_tools + +all: install test + test: - go test ./... + go test `glide novendor` install: go install ./cmd/keys + +get_vendor_deps: ensure_tools + @rm -rf vendor/ + @echo "--> Running glide install" + @glide install + +ensure_tools: + go get $(GOTOOLS) + diff --git a/glide.lock b/glide.lock new file mode 100644 index 000000000..c74262a4e --- /dev/null +++ b/glide.lock @@ -0,0 +1,123 @@ +hash: 4a517b0f71ea6e3aadcf98286cde97c2f567e9e7999a4c7ec9ce6e5b6c21564a +updated: 2017-03-02T16:57:20.740518259-05:00 +imports: +- name: github.com/bgentry/speakeasy + version: 675b82c74c0ed12283ee81ba8a534c8982c07b85 +- name: github.com/btcsuite/btcd + version: d06c0bb181529331be8f8d9350288c420d9e60e4 + subpackages: + - btcec +- name: github.com/fsnotify/fsnotify + version: 7d7316ed6e1ed2de075aab8dfc76de5d158d66e1 +- name: github.com/go-playground/locales + version: 084b0226cf88d891a2bdeccac01d592af13a8f7b + subpackages: + - currency +- name: github.com/go-playground/universal-translator + version: b32fa301c9fe55953584134cb6853a13c87ec0a1 +- name: github.com/go-stack/stack + version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 +- name: github.com/gorilla/context + version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 +- name: github.com/gorilla/handlers + version: 13d73096a474cac93275c679c7b8a2dc17ddba82 +- name: github.com/gorilla/mux + version: 599cba5e7b6137d46ddf58fb1765f5d928e69604 +- name: github.com/hashicorp/hcl + version: 630949a3c5fa3c613328e1b8256052cbc2327c9b + subpackages: + - hcl/ast + - hcl/parser + - hcl/scanner + - hcl/strconv + - hcl/token + - json/parser + - json/scanner + - json/token +- name: github.com/inconshreveable/mousetrap + version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 +- name: github.com/magiconair/properties + version: b3b15ef068fd0b17ddf408a23669f20811d194d2 +- name: github.com/mattn/go-colorable + version: 5411d3eea5978e6cdc258b30de592b60df6aba96 +- name: github.com/mattn/go-isatty + version: 281032e84ae07510239465db46bf442aa44b953a +- name: github.com/mitchellh/mapstructure + version: db1efb556f84b25a0a13a04aad883943538ad2e0 +- name: github.com/pelletier/go-buffruneio + version: c37440a7cf42ac63b919c752ca73a85067e05992 +- name: github.com/pelletier/go-toml + version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a +- name: github.com/pkg/errors + version: 248dadf4e9068a0b3e79f02ed0a610d935de5302 +- name: github.com/spf13/afero + version: 9be650865eab0c12963d8753212f4f9c66cdcf12 + subpackages: + - mem +- name: github.com/spf13/cast + version: f820543c3592e283e311a60d2a600a664e39f6f7 +- name: github.com/spf13/cobra + version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c +- name: github.com/spf13/jwalterweatherman + version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66 +- name: github.com/spf13/pflag + version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 +- name: github.com/spf13/viper + version: 7538d73b4eb9511d85a9f1dfef202eeb8ac260f4 +- name: github.com/tendermint/ed25519 + version: 1f52c6f8b8a5c7908aff4497c186af344b428925 + subpackages: + - edwards25519 + - extra25519 +- name: github.com/tendermint/go-common + version: 339e135776142939d82bc8e699db0bf391fd938d +- name: github.com/tendermint/go-crypto + version: 562b4cc9ef0d20217f6e95679f9e83cb7bc98b17 +- name: github.com/tendermint/go-data + version: 32271140e8fd5abdbb22e268d7a02421fa382f0b + subpackages: + - base58 +- name: github.com/tendermint/go-logger + version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 +- name: github.com/tendermint/go-wire + version: 3216ec9d47bbdf8d4fc27d22169ea86a6688bc15 +- name: github.com/tendermint/log15 + version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 + subpackages: + - term +- name: golang.org/x/crypto + version: 453249f01cfeb54c3d549ddb75ff152ca243f9d8 + subpackages: + - nacl/secretbox + - openpgp/armor + - openpgp/errors + - poly1305 + - ripemd160 + - salsa20/salsa +- name: golang.org/x/sys + version: e24f485414aeafb646f6fca458b0bf869c0880a1 + subpackages: + - unix +- name: golang.org/x/text + version: d680ca3ed853995402af43b866311167281bdc20 + subpackages: + - transform + - unicode/norm +- name: gopkg.in/go-playground/validator.v9 + version: 4bd19358521c53f09639f21e2a9d6883d6890f24 +- name: gopkg.in/yaml.v2 + version: a3f3340b5840cee44f372bddb5880fcbc419b46a +testImports: +- name: github.com/davecgh/go-spew + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + subpackages: + - spew +- name: github.com/pmezard/go-difflib + version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + subpackages: + - difflib +- name: github.com/stretchr/testify + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + subpackages: + - assert + - require diff --git a/glide.yaml b/glide.yaml new file mode 100644 index 000000000..39402fa8b --- /dev/null +++ b/glide.yaml @@ -0,0 +1,19 @@ +package: github.com/tendermint/go-keys +import: +- package: github.com/bgentry/speakeasy +- package: github.com/gorilla/handlers +- package: github.com/gorilla/mux +- package: github.com/pkg/errors +- package: github.com/spf13/cobra +- package: github.com/spf13/viper +- package: github.com/tendermint/go-crypto + version: develop +- package: github.com/tendermint/go-data + subpackages: + - base58 +- package: gopkg.in/go-playground/validator.v9 +testImport: +- package: github.com/stretchr/testify + subpackages: + - assert + - require From 76ace969256d2e3c2c89ddc8566489c9b8cb78bd Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 20 Mar 2017 09:55:07 +0100 Subject: [PATCH 041/273] Create nested directories as needed to store keys --- storage/filestorage/main.go | 4 ++-- storage/filestorage/main_test.go | 25 +++++++++++++++++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/storage/filestorage/main.go b/storage/filestorage/main.go index 4b7dbe525..737f0772c 100644 --- a/storage/filestorage/main.go +++ b/storage/filestorage/main.go @@ -35,8 +35,8 @@ type FileStore struct { // dir should be an absolute path of a directory owner by this user. It will // be created if it doesn't exist already. func New(dir string) FileStore { - err := os.Mkdir(dir, dirPerm) - if err != nil && !os.IsExist(err) { + err := os.MkdirAll(dir, dirPerm) + if err != nil { panic(err) } return FileStore{dir} diff --git a/storage/filestorage/main_test.go b/storage/filestorage/main_test.go index c9c55eb02..890898dcb 100644 --- a/storage/filestorage/main_test.go +++ b/storage/filestorage/main_test.go @@ -83,15 +83,24 @@ func TestDirectoryHandling(t *testing.T) { newDir := path.Join(os.TempDir(), "file-test-dir") _, err := os.Open(newDir) assert.True(os.IsNotExist(err)) + defer os.RemoveAll(newDir) + + // now, check with two levels deep.... + parentDir := path.Join(os.TempDir(), "missing-dir") + nestedDir := path.Join(parentDir, "lots", "of", "levels", "here") + _, err = os.Open(parentDir) + assert.True(os.IsNotExist(err)) + defer os.RemoveAll(parentDir) // create a new storage, and verify it creates the directory with good permissions - New(newDir) - defer os.RemoveAll(newDir) - d, err := os.Open(newDir) - require.Nil(err) - defer d.Close() + for _, dir := range []string{newDir, nestedDir, newDir} { + New(dir) + d, err := os.Open(dir) + require.Nil(err) + defer d.Close() - stat, err := d.Stat() - require.Nil(err) - assert.Equal(dirPerm, stat.Mode()&os.ModePerm) + stat, err := d.Stat() + require.Nil(err) + assert.Equal(dirPerm, stat.Mode()&os.ModePerm) + } } From 3a1313ab7d0868f9c410ab423909bdbc45ad4a7f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 22 Mar 2017 01:18:56 -0400 Subject: [PATCH 042/273] secp256k1: use compressed pubkey, bitcoin-style address --- priv_key.go | 6 +++--- pub_key.go | 27 ++++++++++++++------------- pub_key_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 pub_key_test.go diff --git a/priv_key.go b/priv_key.go index 54fa36a3a..f2d108ee5 100644 --- a/priv_key.go +++ b/priv_key.go @@ -160,9 +160,9 @@ func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature { func (privKey PrivKeySecp256k1) PubKey() PubKey { _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) - pub := [64]byte{} - copy(pub[:], pub__.SerializeUncompressed()[1:]) - return PubKeySecp256k1(pub) + var pub PubKeySecp256k1 + copy(pub[:], pub__.SerializeCompressed()) + return pub } func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { diff --git a/pub_key.go b/pub_key.go index 9067a0363..45a4db92c 100644 --- a/pub_key.go +++ b/pub_key.go @@ -2,6 +2,7 @@ package crypto import ( "bytes" + "crypto/sha256" secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" @@ -135,20 +136,20 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool { //------------------------------------- -// Implements PubKey -type PubKeySecp256k1 [64]byte +// Implements PubKey. +// Compressed pubkey (just the x-cord), +// prefixed with 0x02 or 0x03, depending on the y-cord. +type PubKeySecp256k1 [33]byte +// Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) func (pubKey PubKeySecp256k1) Address() []byte { - w, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(pubKey[:], w, n, err) - if *err != nil { - PanicCrisis(*err) - } - // append type byte - encodedPubkey := append([]byte{TypeSecp256k1}, w.Bytes()...) - hasher := ripemd160.New() - hasher.Write(encodedPubkey) // does not error - return hasher.Sum(nil) + hasherSHA256 := sha256.New() + hasherSHA256.Write(pubKey[:]) // does not error + sha := hasherSHA256.Sum(nil) + + hasherRIPEMD160 := ripemd160.New() + hasherRIPEMD160.Write(sha) // does not error + return hasherRIPEMD160.Sum(nil) } func (pubKey PubKeySecp256k1) Bytes() []byte { @@ -166,7 +167,7 @@ func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { return false } - pub__, err := secp256k1.ParsePubKey(append([]byte{0x04}, pubKey[:]...), secp256k1.S256()) + pub__, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256()) if err != nil { return false } diff --git a/pub_key_test.go b/pub_key_test.go new file mode 100644 index 000000000..0616f5546 --- /dev/null +++ b/pub_key_test.go @@ -0,0 +1,41 @@ +package crypto + +import ( + "encoding/hex" + "testing" + + "github.com/btcsuite/btcutil/base58" + "github.com/stretchr/testify/assert" +) + +type keyData struct { + priv string + pub string + addr string +} + +var secpDataTable = []keyData{ + { + priv: "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330", + pub: "02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c", + addr: "1CKZ9Nx4zgds8tU7nJHotKSDr4a9bYJCa3", + }, +} + +func TestPubKeySecp256k1Address(t *testing.T) { + for _, d := range secpDataTable { + privB, _ := hex.DecodeString(d.priv) + pubB, _ := hex.DecodeString(d.pub) + addrB, _, _ := base58.CheckDecode(d.addr) + + var priv PrivKeySecp256k1 + copy(priv[:], privB) + + pubT := priv.PubKey().(PubKeySecp256k1) + pub := pubT[:] + addr := priv.PubKey().Address() + + assert.Equal(t, pub, pubB, "Expected pub keys to match") + assert.Equal(t, addr, addrB, "Expected addresses to match") + } +} From ce9c57fca8261934db9f3612bc31ca5d0bd4505d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 22 Mar 2017 15:59:48 -0400 Subject: [PATCH 043/273] hd test --- hd/hd_test.go | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 hd/hd_test.go diff --git a/hd/hd_test.go b/hd/hd_test.go new file mode 100644 index 000000000..6bd49a8ac --- /dev/null +++ b/hd/hd_test.go @@ -0,0 +1,132 @@ +package crypto + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/tyler-smith/go-bip39" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcutil/hdkeychain" + "github.com/tyler-smith/go-bip32" + + "github.com/tendermint/go-crypto" +) + +type addrData struct { + Mnemonic string + Seed string + Priv string + Pub string + Addr string +} + +// NOTE: atom fundraiser address +var hdPath string = "m/44'/118'/0'/0/0" +var hdToAddrTable []addrData + +/*{ + { + Mnemonic: "spawn essence sudden gown library fire chalk edge start museum glimpse sea", + Priv: "ab20a81c1b9002538e2269e1f1302d519901633d40408313211598899bc00fc6", + Pub: "03eb89fb1c4582eed592e09c31c4665d3956154ea66fd269933d3f036e879abfe6", + Addr: "f7d613738f0a665ec320306d14f5d62a850ff714", + }, +}*/ + +func init() { + + b, err := ioutil.ReadFile("test.json") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + err = json.Unmarshal(b, &hdToAddrTable) + if err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func TestHDToAddr(t *testing.T) { + + for i, d := range hdToAddrTable { + privB, _ := hex.DecodeString(d.Priv) + pubB, _ := hex.DecodeString(d.Pub) + addrB, _ := hex.DecodeString(d.Addr) + seedB, _ := hex.DecodeString(d.Seed) + + seed := bip39.NewSeed(d.Mnemonic, "") + + fmt.Println(i, d.Mnemonic) + + priv, pub := tylerSmith(seed) + //priv, pub := btcsuite(seed) + + fmt.Printf("\t%X %X\n", seedB, seed) + fmt.Printf("\t%X %X\n", privB, priv) + fmt.Printf("\t%X %X\n", pubB, pub) + assert.Equal(t, priv, privB, "Expected priv keys to match") + assert.Equal(t, pub, pubB, "Expected pub keys to match") + + var pubT crypto.PubKeySecp256k1 + copy(pubT[:], pub) + addr := pubT.Address() + assert.Equal(t, addr, addrB, "Expected addresses to match") + + /* if i%10 == 0 { + fmt.Printf("ADDR %d: %s %X %X\n", i, d.Mnemonic, addr, addrB) + }*/ + } +} + +func ifExit(err error, n int) { + if err != nil { + fmt.Println(n, err) + os.Exit(1) + } +} + +func btcsuite(seed []byte) ([]byte, []byte) { + masterKey, _ := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) + fh := hdkeychain.HardenedKeyStart + k, err := masterKey.Child(uint32(fh + 44)) + ifExit(err, 44) + k, err = k.Child(uint32(fh + 118)) + ifExit(err, 118) + k, err = k.Child(uint32(fh + 0)) + ifExit(err, 1) + k, err = k.Child(uint32(0)) + ifExit(err, 2) + k, err = k.Child(uint32(0)) + ifExit(err, 3) + ecpriv, err := k.ECPrivKey() + ifExit(err, 10) + ecpub, err := k.ECPubKey() + ifExit(err, 11) + + priv := ecpriv.Serialize() + pub := ecpub.SerializeCompressed() + return priv, pub +} + +// return priv and pub +func tylerSmith(seed []byte) ([]byte, []byte) { + masterKey, _ := bip32.NewMasterKey(seed) + fh := bip32.FirstHardenedChild + k, _ := masterKey.NewChildKey(fh + 44) + k, _ = k.NewChildKey(fh + 118) + k, _ = k.NewChildKey(fh + 0) + k, _ = k.NewChildKey(0) + k, _ = k.NewChildKey(0) + + priv := k.Key + pub := k.PublicKey().Key + return priv, pub +} From c6be97c71c1a67d962b38ba7a9c0d4ac7a3de969 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 22 Mar 2017 16:45:30 -0400 Subject: [PATCH 044/273] error testing the hd --- hd/hd_test.go | 62 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/hd/hd_test.go b/hd/hd_test.go index 6bd49a8ac..ac07c7ed6 100644 --- a/hd/hd_test.go +++ b/hd/hd_test.go @@ -1,6 +1,10 @@ package crypto import ( + "bytes" + "crypto/hmac" + "crypto/sha512" + "encoding/binary" "encoding/hex" "encoding/json" "fmt" @@ -13,6 +17,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil/hdkeychain" + "github.com/mndrix/btcutil" "github.com/tyler-smith/go-bip32" "github.com/tendermint/go-crypto" @@ -67,12 +72,13 @@ func TestHDToAddr(t *testing.T) { fmt.Println(i, d.Mnemonic) priv, pub := tylerSmith(seed) - //priv, pub := btcsuite(seed) + // priv, pub := btcsuite(seed) fmt.Printf("\t%X %X\n", seedB, seed) fmt.Printf("\t%X %X\n", privB, priv) fmt.Printf("\t%X %X\n", pubB, pub) - assert.Equal(t, priv, privB, "Expected priv keys to match") + _, _ = priv, privB + // assert.Equal(t, priv, privB, "Expected priv keys to match") assert.Equal(t, pub, pubB, "Expected pub keys to match") var pubT crypto.PubKeySecp256k1 @@ -94,7 +100,23 @@ func ifExit(err error, n int) { } func btcsuite(seed []byte) ([]byte, []byte) { - masterKey, _ := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) + fmt.Println("HD") + masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) + if err != nil { + hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) + hmac.Write([]byte(seed)) + intermediary := hmac.Sum(nil) + + curve := btcutil.Secp256k1() + curveParams := curve.Params() + + // Split it into our key and chain code + keyBytes := intermediary[:32] + fmt.Printf("\t%X\n", keyBytes) + fmt.Printf("\t%X\n", curveParams.N.Bytes()) + keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes)) + fmt.Printf("\t%d\n", keyInt) + } fh := hdkeychain.HardenedKeyStart k, err := masterKey.Child(uint32(fh + 44)) ifExit(err, 44) @@ -118,13 +140,35 @@ func btcsuite(seed []byte) ([]byte, []byte) { // return priv and pub func tylerSmith(seed []byte) ([]byte, []byte) { - masterKey, _ := bip32.NewMasterKey(seed) + masterKey, err := bip32.NewMasterKey(seed) + if err != nil { + hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) + hmac.Write([]byte(seed)) + intermediary := hmac.Sum(nil) + + curve := btcutil.Secp256k1() + curveParams := curve.Params() + + // Split it into our key and chain code + keyBytes := intermediary[:32] + fmt.Printf("\t%X\n", keyBytes) + fmt.Printf("\t%X\n", curveParams.N.Bytes()) + keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes)) + fmt.Printf("\t%d\n", keyInt) + + } + ifExit(err, 0) fh := bip32.FirstHardenedChild - k, _ := masterKey.NewChildKey(fh + 44) - k, _ = k.NewChildKey(fh + 118) - k, _ = k.NewChildKey(fh + 0) - k, _ = k.NewChildKey(0) - k, _ = k.NewChildKey(0) + k, err := masterKey.NewChildKey(fh + 44) + ifExit(err, 44) + k, err = k.NewChildKey(fh + 118) + ifExit(err, 118) + k, err = k.NewChildKey(fh + 0) + ifExit(err, 1) + k, err = k.NewChildKey(0) + ifExit(err, 2) + k, err = k.NewChildKey(0) + ifExit(err, 3) priv := k.Key pub := k.PublicKey().Key From 6fddcdf2452aa43e1e35f5fa47c5525468c4af2d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 22 Mar 2017 20:13:16 -0400 Subject: [PATCH 045/273] hd test: check masters too --- hd/hd_test.go | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/hd/hd_test.go b/hd/hd_test.go index ac07c7ed6..42d034717 100644 --- a/hd/hd_test.go +++ b/hd/hd_test.go @@ -25,6 +25,7 @@ import ( type addrData struct { Mnemonic string + Master string Seed string Priv string Pub string @@ -66,25 +67,30 @@ func TestHDToAddr(t *testing.T) { pubB, _ := hex.DecodeString(d.Pub) addrB, _ := hex.DecodeString(d.Addr) seedB, _ := hex.DecodeString(d.Seed) + masterB, _ := hex.DecodeString(d.Master) seed := bip39.NewSeed(d.Mnemonic, "") fmt.Println(i, d.Mnemonic) - priv, pub := tylerSmith(seed) - // priv, pub := btcsuite(seed) + //master, priv, pub := tylerSmith(seed) + master, priv, pub := btcsuite(seed) fmt.Printf("\t%X %X\n", seedB, seed) + fmt.Printf("\t%X %X\n", masterB, master) fmt.Printf("\t%X %X\n", privB, priv) fmt.Printf("\t%X %X\n", pubB, pub) _, _ = priv, privB + + assert.Equal(t, master, masterB, fmt.Sprintf("Expected masters to match for %d", i)) + // assert.Equal(t, priv, privB, "Expected priv keys to match") - assert.Equal(t, pub, pubB, "Expected pub keys to match") + assert.Equal(t, pub, pubB, fmt.Sprintf("Expected pub keys to match for %d", i)) var pubT crypto.PubKeySecp256k1 copy(pubT[:], pub) addr := pubT.Address() - assert.Equal(t, addr, addrB, "Expected addresses to match") + assert.Equal(t, addr, addrB, fmt.Sprintf("Expected addresses to match %d", i)) /* if i%10 == 0 { fmt.Printf("ADDR %d: %s %X %X\n", i, d.Mnemonic, addr, addrB) @@ -99,7 +105,7 @@ func ifExit(err error, n int) { } } -func btcsuite(seed []byte) ([]byte, []byte) { +func btcsuite(seed []byte) ([]byte, []byte, []byte) { fmt.Println("HD") masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) if err != nil { @@ -135,11 +141,12 @@ func btcsuite(seed []byte) ([]byte, []byte) { priv := ecpriv.Serialize() pub := ecpub.SerializeCompressed() - return priv, pub + mkey, _ := masterKey.ECPrivKey() + return mkey.Serialize(), priv, pub } // return priv and pub -func tylerSmith(seed []byte) ([]byte, []byte) { +func tylerSmith(seed []byte) ([]byte, []byte, []byte) { masterKey, err := bip32.NewMasterKey(seed) if err != nil { hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) @@ -172,5 +179,5 @@ func tylerSmith(seed []byte) ([]byte, []byte) { priv := k.Key pub := k.PublicKey().Key - return priv, pub + return masterKey.Key, priv, pub } From 398ac046da7e1b23551e6a0d4405d3a7653eafad Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 23 Mar 2017 20:31:47 +0100 Subject: [PATCH 046/273] Reorganize cobra cmd to enable better reuse --- cmd/common.go | 119 +++++++++++++++++++++++++++++++++++++++++++++++ cmd/get.go | 2 +- cmd/keys/main.go | 11 ++++- cmd/list.go | 2 +- cmd/new.go | 2 +- cmd/root.go | 95 ++++--------------------------------- cmd/serve.go | 2 +- cmd/update.go | 2 +- cmd/utils.go | 5 +- 9 files changed, 146 insertions(+), 94 deletions(-) create mode 100644 cmd/common.go diff --git a/cmd/common.go b/cmd/common.go new file mode 100644 index 000000000..56c9afbab --- /dev/null +++ b/cmd/common.go @@ -0,0 +1,119 @@ +package cmd + +import ( + "fmt" + "os" + "strings" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/spf13/viper" + data "github.com/tendermint/go-data" + "github.com/tendermint/go-data/base58" +) + +/******* + +TODO + +This file should move into go-common or the like as a basis for all cli tools. +It is here for experimentation of re-use between go-keys and light-client. + +*********/ + +const ( + RootFlag = "root" + OutputFlag = "output" +) + +func PrepareMainCmd(cmd *cobra.Command, envPrefix, defautRoot string) func() { + cobra.OnInitialize(func() { initEnv(envPrefix) }) + cmd.PersistentFlags().StringP(RootFlag, "r", defautRoot, "root directory for config and data") + cmd.PersistentFlags().StringP("encoding", "e", "hex", "Binary encoding (hex|b64|btc)") + cmd.PersistentFlags().StringP(OutputFlag, "o", "text", "Output format (text|json)") + cmd.PersistentPreRunE = multiE(bindFlags, setEncoding, validateOutput, cmd.PersistentPreRunE) + return func() { execute(cmd) } +} + +// initEnv sets to use ENV variables if set. +func initEnv(prefix string) { + // env variables with TM prefix (eg. TM_ROOT) + viper.SetEnvPrefix(prefix) + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + viper.AutomaticEnv() +} + +// execute adds all child commands to the root command sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func execute(cmd *cobra.Command) { + if err := cmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(-1) + } +} + +type wrapE func(cmd *cobra.Command, args []string) error + +func multiE(fs ...wrapE) wrapE { + return func(cmd *cobra.Command, args []string) error { + for _, f := range fs { + if f != nil { + if err := f(cmd, args); err != nil { + return err + } + } + } + return nil + } +} + +func bindFlags(cmd *cobra.Command, args []string) error { + // cmd.Flags() includes flags from this command and all persistent flags from the parent + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + + // rootDir is command line flag, env variable, or default $HOME/.tlc + rootDir := viper.GetString("root") + viper.SetConfigName("config") // name of config file (without extension) + viper.AddConfigPath(rootDir) // search root directory + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + // stderr, so if we redirect output to json file, this doesn't appear + // fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) + } else if _, ok := err.(viper.ConfigFileNotFoundError); !ok { + // we ignore not found error, only parse error + // stderr, so if we redirect output to json file, this doesn't appear + fmt.Fprintf(os.Stderr, "%#v", err) + } + return nil +} + +// setEncoding reads the encoding flag +func setEncoding(cmd *cobra.Command, args []string) error { + // validate and set encoding + enc := viper.GetString("encoding") + switch enc { + case "hex": + data.Encoder = data.HexEncoder + case "b64": + data.Encoder = data.B64Encoder + case "btc": + data.Encoder = base58.BTCEncoder + default: + return errors.Errorf("Unsupported encoding: %s", enc) + } + return nil +} + +func validateOutput(cmd *cobra.Command, args []string) error { + // validate output format + output := viper.GetString(OutputFlag) + switch output { + case "text", "json": + default: + return errors.Errorf("Unsupported output format: %s", output) + } + return nil +} diff --git a/cmd/get.go b/cmd/get.go index d945809f9..10d528807 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -32,7 +32,7 @@ var getCmd = &cobra.Command{ } name := args[0] - info, err := manager.Get(name) + info, err := Manager.Get(name) if err != nil { fmt.Println(err.Error()) return diff --git a/cmd/keys/main.go b/cmd/keys/main.go index 8c880ea03..40bf31808 100644 --- a/cmd/keys/main.go +++ b/cmd/keys/main.go @@ -14,8 +14,15 @@ package main -import "github.com/tendermint/go-keys/cmd" +import ( + "os" + + "github.com/tendermint/go-keys/cmd" +) func main() { - cmd.Execute() + cmd.RootCmd.PersistentPreRunE = cmd.SetupKeys + cmd.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) + cmd.RootCmd.Execute() + // exec() } diff --git a/cmd/list.go b/cmd/list.go index 44fefb8d6..bf4d14b68 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -27,7 +27,7 @@ var listCmd = &cobra.Command{ Long: `Return a list of all public keys stored by this key manager along with their associated name and address.`, Run: func(cmd *cobra.Command, args []string) { - infos, err := manager.List() + infos, err := Manager.List() if err != nil { fmt.Println(err.Error()) return diff --git a/cmd/new.go b/cmd/new.go index 27c7dce75..3564ddf90 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -50,7 +50,7 @@ func newPassword(cmd *cobra.Command, args []string) { return } - info, err := manager.Create(name, pass, algo) + info, err := Manager.Create(name, pass, algo) if err != nil { fmt.Println(err.Error()) return diff --git a/cmd/root.go b/cmd/root.go index 41803fc65..ffe5cc36b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -15,26 +15,19 @@ package cmd import ( - "fmt" - "os" "path/filepath" - "strings" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - data "github.com/tendermint/go-data" - "github.com/tendermint/go-data/base58" keys "github.com/tendermint/go-keys" "github.com/tendermint/go-keys/cryptostore" "github.com/tendermint/go-keys/storage/filestorage" ) +const KeySubdir = "keys" + var ( - rootDir string - output string - keyDir string - manager keys.Manager + Manager keys.Manager ) // RootCmd represents the base command when called without any subcommands @@ -46,87 +39,19 @@ var RootCmd = &cobra.Command{ These keys may be in any format supported by go-crypto and can be used by light-clients, full nodes, or any other application that needs to sign with a private key.`, - PersistentPreRunE: bindFlags, -} - -// Execute adds all child commands to the root command sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } -} - -func init() { - cobra.OnInitialize(initEnv) - RootCmd.PersistentFlags().StringP("root", "r", os.ExpandEnv("$HOME/.tlc"), "root directory for config and data") - RootCmd.PersistentFlags().String("keydir", "keys", "Directory to store private keys (subdir of root)") - RootCmd.PersistentFlags().StringP("output", "o", "text", "Output format (text|json)") - RootCmd.PersistentFlags().StringP("encoding", "e", "hex", "Binary encoding (hex|b64|btc)") -} - -// initEnv sets to use ENV variables if set. -func initEnv() { - // env variables with TM prefix (eg. TM_ROOT) - viper.SetEnvPrefix("TM") - viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) - viper.AutomaticEnv() } -func bindFlags(cmd *cobra.Command, args []string) error { - // cmd.Flags() includes flags from this command and all persistent flags from the parent - if err := viper.BindPFlags(cmd.Flags()); err != nil { - return err - } - - // rootDir is command line flag, env variable, or default $HOME/.tlc - rootDir = viper.GetString("root") - viper.SetConfigName("keys") // name of config file (without extension) - viper.AddConfigPath(rootDir) // search root directory - - // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - // stderr, so if we redirect output to json file, this doesn't appear - fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) - } - - return validateFlags(cmd) -} - -// validateFlags asserts all RootCmd flags are valid -func validateFlags(cmd *cobra.Command) error { - // validate output format - output = viper.GetString("output") - switch output { - case "text", "json": - default: - return errors.Errorf("Unsupported output format: %s", output) - } - - // validate and set encoding - enc := viper.GetString("encoding") - switch enc { - case "hex": - data.Encoder = data.HexEncoder - case "b64": - data.Encoder = data.B64Encoder - case "btc": - data.Encoder = base58.BTCEncoder - default: - return errors.Errorf("Unsupported encoding: %s", enc) - } - +// SetupKeys must be registered in main() on the top level command +// here this is RootCmd, but if we embed keys in eg. light-client, +// that must be responsible for the update +func SetupKeys(cmd *cobra.Command, args []string) error { // store the keys directory - keyDir = viper.GetString("keydir") - if !filepath.IsAbs(keyDir) { - keyDir = filepath.Join(rootDir, keyDir) - } + rootDir := viper.GetString("root") + keyDir := filepath.Join(rootDir, KeySubdir) // and construct the key manager - manager = cryptostore.New( + Manager = cryptostore.New( cryptostore.SecretBox, filestorage.New(keyDir), ) - return nil } diff --git a/cmd/serve.go b/cmd/serve.go index 2717913fd..5268f0b92 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -64,7 +64,7 @@ func serveHTTP(cmd *cobra.Command, args []string) error { } router := mux.NewRouter() - ks := server.New(manager, viper.GetString("type")) + ks := server.New(Manager, viper.GetString("type")) ks.Register(router) // only set cors for tcp listener diff --git a/cmd/update.go b/cmd/update.go index 0340944be..63b6f84df 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -50,7 +50,7 @@ func updatePassword(cmd *cobra.Command, args []string) { return } - err = manager.Update(name, oldpass, newpass) + err = Manager.Update(name, oldpass, newpass) if err != nil { fmt.Println(err.Error()) } else { diff --git a/cmd/utils.go b/cmd/utils.go index 01f9801ae..31a3a8df3 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -5,6 +5,7 @@ import ( "github.com/bgentry/speakeasy" "github.com/pkg/errors" + "github.com/spf13/viper" data "github.com/tendermint/go-data" keys "github.com/tendermint/go-keys" ) @@ -39,7 +40,7 @@ func getCheckPassword(prompt, prompt2 string) (string, error) { } func printInfo(info keys.Info) { - switch output { + switch viper.Get(OutputFlag) { case "text": addr, err := data.ToText(info.Address) if err != nil { @@ -60,7 +61,7 @@ func printInfo(info keys.Info) { } func printInfos(infos keys.Infos) { - switch output { + switch viper.Get(OutputFlag) { case "text": fmt.Println("All keys:") for _, i := range infos { From 58e537a42de4de0c7719171123695c5d0ed7b97c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 28 Mar 2017 19:05:33 +0200 Subject: [PATCH 047/273] Refactor setting up the key manager from config --- cmd/common.go | 7 ++++--- cmd/get.go | 2 +- cmd/keys/main.go | 1 - cmd/list.go | 2 +- cmd/new.go | 2 +- cmd/root.go | 28 ++++++++++++++-------------- cmd/serve.go | 2 +- cmd/update.go | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/cmd/common.go b/cmd/common.go index 56c9afbab..eb7a158ae 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -22,14 +22,15 @@ It is here for experimentation of re-use between go-keys and light-client. *********/ const ( - RootFlag = "root" - OutputFlag = "output" + RootFlag = "root" + OutputFlag = "output" + EncodingFlag = "encoding" ) func PrepareMainCmd(cmd *cobra.Command, envPrefix, defautRoot string) func() { cobra.OnInitialize(func() { initEnv(envPrefix) }) cmd.PersistentFlags().StringP(RootFlag, "r", defautRoot, "root directory for config and data") - cmd.PersistentFlags().StringP("encoding", "e", "hex", "Binary encoding (hex|b64|btc)") + cmd.PersistentFlags().StringP(EncodingFlag, "e", "hex", "Binary encoding (hex|b64|btc)") cmd.PersistentFlags().StringP(OutputFlag, "o", "text", "Output format (text|json)") cmd.PersistentPreRunE = multiE(bindFlags, setEncoding, validateOutput, cmd.PersistentPreRunE) return func() { execute(cmd) } diff --git a/cmd/get.go b/cmd/get.go index 10d528807..9b8718996 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -32,7 +32,7 @@ var getCmd = &cobra.Command{ } name := args[0] - info, err := Manager.Get(name) + info, err := GetKeyManager().Get(name) if err != nil { fmt.Println(err.Error()) return diff --git a/cmd/keys/main.go b/cmd/keys/main.go index 40bf31808..8b92b3f49 100644 --- a/cmd/keys/main.go +++ b/cmd/keys/main.go @@ -21,7 +21,6 @@ import ( ) func main() { - cmd.RootCmd.PersistentPreRunE = cmd.SetupKeys cmd.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) cmd.RootCmd.Execute() // exec() diff --git a/cmd/list.go b/cmd/list.go index bf4d14b68..875520159 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -27,7 +27,7 @@ var listCmd = &cobra.Command{ Long: `Return a list of all public keys stored by this key manager along with their associated name and address.`, Run: func(cmd *cobra.Command, args []string) { - infos, err := Manager.List() + infos, err := GetKeyManager().List() if err != nil { fmt.Println(err.Error()) return diff --git a/cmd/new.go b/cmd/new.go index 3564ddf90..b59874bb0 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -50,7 +50,7 @@ func newPassword(cmd *cobra.Command, args []string) { return } - info, err := Manager.Create(name, pass, algo) + info, err := GetKeyManager().Create(name, pass, algo) if err != nil { fmt.Println(err.Error()) return diff --git a/cmd/root.go b/cmd/root.go index ffe5cc36b..64adf2b0b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -27,7 +27,7 @@ import ( const KeySubdir = "keys" var ( - Manager keys.Manager + manager keys.Manager ) // RootCmd represents the base command when called without any subcommands @@ -41,17 +41,17 @@ used by light-clients, full nodes, or any other application that needs to sign with a private key.`, } -// SetupKeys must be registered in main() on the top level command -// here this is RootCmd, but if we embed keys in eg. light-client, -// that must be responsible for the update -func SetupKeys(cmd *cobra.Command, args []string) error { - // store the keys directory - rootDir := viper.GetString("root") - keyDir := filepath.Join(rootDir, KeySubdir) - // and construct the key manager - Manager = cryptostore.New( - cryptostore.SecretBox, - filestorage.New(keyDir), - ) - return nil +// GetKeyManager initializes a key manager based on the configuration +func GetKeyManager() keys.Manager { + if manager == nil { + // store the keys directory + rootDir := viper.GetString("root") + keyDir := filepath.Join(rootDir, KeySubdir) + // and construct the key manager + manager = cryptostore.New( + cryptostore.SecretBox, + filestorage.New(keyDir), + ) + } + return manager } diff --git a/cmd/serve.go b/cmd/serve.go index 5268f0b92..c3f7dbe39 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -64,7 +64,7 @@ func serveHTTP(cmd *cobra.Command, args []string) error { } router := mux.NewRouter() - ks := server.New(Manager, viper.GetString("type")) + ks := server.New(GetKeyManager(), viper.GetString("type")) ks.Register(router) // only set cors for tcp listener diff --git a/cmd/update.go b/cmd/update.go index 63b6f84df..3835242c5 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -50,7 +50,7 @@ func updatePassword(cmd *cobra.Command, args []string) { return } - err = Manager.Update(name, oldpass, newpass) + err = GetKeyManager().Update(name, oldpass, newpass) if err != nil { fmt.Println(err.Error()) } else { From ae55713864f0679dfa628b23654d462bb12a109a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 29 Mar 2017 20:41:11 +0200 Subject: [PATCH 048/273] Move tx from light-client and add tests --- tx/docs.go | 10 ++++++ tx/multi.go | 67 +++++++++++++++++++++++++++++++++++++++++ tx/multi_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++ tx/one.go | 58 +++++++++++++++++++++++++++++++++++ tx/one_test.go | 73 ++++++++++++++++++++++++++++++++++++++++++++ tx/reader.go | 76 ++++++++++++++++++++++++++++++++++++++++++++++ tx/reader_test.go | 70 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 431 insertions(+) create mode 100644 tx/docs.go create mode 100644 tx/multi.go create mode 100644 tx/multi_test.go create mode 100644 tx/one.go create mode 100644 tx/one_test.go create mode 100644 tx/reader.go create mode 100644 tx/reader_test.go diff --git a/tx/docs.go b/tx/docs.go new file mode 100644 index 000000000..6a5ea3ce3 --- /dev/null +++ b/tx/docs.go @@ -0,0 +1,10 @@ +/* +package tx contains generic Signable implementations that can be used +by your application or tests to handle authentication needs. + +It currently supports transaction data as opaque bytes and either single +or multiple private key signatures using straightforward algorithms. +It currently does not support N-of-M key share signing of other more +complex algorithms (although it would be great to add them) +*/ +package tx diff --git a/tx/multi.go b/tx/multi.go new file mode 100644 index 000000000..eac86b010 --- /dev/null +++ b/tx/multi.go @@ -0,0 +1,67 @@ +package tx + +import ( + "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" + data "github.com/tendermint/go-data" +) + +// MultiSig lets us wrap arbitrary data with a go-crypto signature +// +// TODO: rethink how we want to integrate this with KeyStore so it makes +// more sense (particularly the verify method) +type MultiSig struct { + Data data.Bytes + Sigs []Signed +} + +type Signed struct { + Sig crypto.SignatureS + Pubkey crypto.PubKeyS +} + +var _ SigInner = &MultiSig{} + +func NewMulti(data []byte) Sig { + return Sig{&MultiSig{Data: data}} +} + +// SignBytes returns the original data passed into `NewSig` +func (s *MultiSig) SignBytes() []byte { + return s.Data +} + +// Sign will add a signature and pubkey. +// +// Depending on the Signable, one may be able to call this multiple times for multisig +// Returns error if called with invalid data or too many times +func (s *MultiSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error { + if pubkey == nil || sig == nil { + return errors.New("Signature or Key missing") + } + + // set the value once we are happy + x := Signed{crypto.SignatureS{sig}, crypto.PubKeyS{pubkey}} + s.Sigs = append(s.Sigs, x) + return nil +} + +// Signers will return the public key(s) that signed if the signature +// is valid, or an error if there is any issue with the signature, +// including if there are no signatures +func (s *MultiSig) Signers() ([]crypto.PubKey, error) { + if len(s.Sigs) == 0 { + return nil, errors.New("Never signed") + } + + keys := make([]crypto.PubKey, len(s.Sigs)) + for i := range s.Sigs { + ms := s.Sigs[i] + if !ms.Pubkey.VerifyBytes(s.Data, ms.Sig) { + return nil, errors.Errorf("Signature %d doesn't match (key: %X)", i, ms.Pubkey.Bytes()) + } + keys[i] = ms.Pubkey + } + + return keys, nil +} diff --git a/tx/multi_test.go b/tx/multi_test.go new file mode 100644 index 000000000..815b9e15a --- /dev/null +++ b/tx/multi_test.go @@ -0,0 +1,77 @@ +package tx + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" + keys "github.com/tendermint/go-keys" + "github.com/tendermint/go-keys/cryptostore" + "github.com/tendermint/go-keys/storage/memstorage" +) + +func TestMultiSig(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + algo := crypto.NameEd25519 + cstore := cryptostore.New( + cryptostore.SecretBox, + memstorage.New(), + ) + n, p := "foo", "bar" + n2, p2 := "other", "thing" + + acct, err := cstore.Create(n, p, algo) + require.Nil(err, "%+v", err) + acct2, err := cstore.Create(n2, p2, algo) + require.Nil(err, "%+v", err) + + type signer struct { + key keys.Info + name, pass string + } + cases := []struct { + data string + signers []signer + }{ + {"one", []signer{{acct, n, p}}}, + {"two", []signer{{acct2, n2, p2}}}, + {"both", []signer{{acct, n, p}, {acct2, n2, p2}}}, + } + + for _, tc := range cases { + tx := NewMulti([]byte(tc.data)) + // unsigned version + _, err = tx.Signers() + assert.NotNil(err) + orig, err := tx.TxBytes() + require.Nil(err, "%+v", err) + data := tx.SignBytes() + assert.Equal(tc.data, string(data)) + + // sign it + for _, s := range tc.signers { + err = cstore.Sign(s.name, s.pass, tx) + require.Nil(err, "%+v", err) + } + + // make sure it is proper now + sigs, err := tx.Signers() + require.Nil(err, "%+v", err) + if assert.Equal(len(tc.signers), len(sigs)) { + for i := range sigs { + // This must be refactored... + assert.Equal(tc.signers[i].key.PubKey, sigs[i]) + } + } + // the tx bytes should change after this + after, err := tx.TxBytes() + require.Nil(err, "%+v", err) + assert.NotEqual(orig, after, "%X != %X", orig, after) + + // sign bytes are the same + data = tx.SignBytes() + assert.Equal(tc.data, string(data)) + } +} diff --git a/tx/one.go b/tx/one.go new file mode 100644 index 000000000..0ad61dd50 --- /dev/null +++ b/tx/one.go @@ -0,0 +1,58 @@ +package tx + +import ( + "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" + data "github.com/tendermint/go-data" +) + +// OneSig lets us wrap arbitrary data with a go-crypto signature +// +// TODO: rethink how we want to integrate this with KeyStore so it makes +// more sense (particularly the verify method) +type OneSig struct { + Data data.Bytes + Signed +} + +var _ SigInner = &OneSig{} + +func New(data []byte) Sig { + return WrapSig(&OneSig{Data: data}) +} + +// SignBytes returns the original data passed into `NewSig` +func (s *OneSig) SignBytes() []byte { + return s.Data +} + +// Sign will add a signature and pubkey. +// +// Depending on the Signable, one may be able to call this multiple times for multisig +// Returns error if called with invalid data or too many times +func (s *OneSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error { + if pubkey == nil || sig == nil { + return errors.New("Signature or Key missing") + } + if !s.Sig.Empty() { + return errors.New("Transaction can only be signed once") + } + + // set the value once we are happy + s.Pubkey = crypto.PubKeyS{pubkey} + s.Sig = crypto.SignatureS{sig} + return nil +} + +// Signers will return the public key(s) that signed if the signature +// is valid, or an error if there is any issue with the signature, +// including if there are no signatures +func (s *OneSig) Signers() ([]crypto.PubKey, error) { + if s.Pubkey.Empty() || s.Sig.Empty() { + return nil, errors.New("Never signed") + } + if !s.Pubkey.VerifyBytes(s.Data, s.Sig) { + return nil, errors.New("Signature doesn't match") + } + return []crypto.PubKey{s.Pubkey}, nil +} diff --git a/tx/one_test.go b/tx/one_test.go new file mode 100644 index 000000000..71b8011ef --- /dev/null +++ b/tx/one_test.go @@ -0,0 +1,73 @@ +package tx + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" + keys "github.com/tendermint/go-keys" + "github.com/tendermint/go-keys/cryptostore" + "github.com/tendermint/go-keys/storage/memstorage" +) + +func TestOneSig(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + algo := crypto.NameEd25519 + cstore := cryptostore.New( + cryptostore.SecretBox, + memstorage.New(), + ) + n, p := "foo", "bar" + n2, p2 := "other", "thing" + + acct, err := cstore.Create(n, p, algo) + require.Nil(err, "%+v", err) + acct2, err := cstore.Create(n2, p2, algo) + require.Nil(err, "%+v", err) + + cases := []struct { + data string + key keys.Info + name, pass string + }{ + {"first", acct, n, p}, + {"kehfkhefy8y", acct, n, p}, + {"second", acct2, n2, p2}, + } + + for _, tc := range cases { + tx := New([]byte(tc.data)) + // unsigned version + _, err = tx.Signers() + assert.NotNil(err) + orig, err := tx.TxBytes() + require.Nil(err, "%+v", err) + data := tx.SignBytes() + assert.Equal(tc.data, string(data)) + + // sign it + err = cstore.Sign(tc.name, tc.pass, tx) + require.Nil(err, "%+v", err) + // but not twice + err = cstore.Sign(tc.name, tc.pass, tx) + require.NotNil(err) + + // make sure it is proper now + sigs, err := tx.Signers() + require.Nil(err, "%+v", err) + if assert.Equal(1, len(sigs)) { + // This must be refactored... + assert.Equal(tc.key.PubKey, sigs[0]) + } + // the tx bytes should change after this + after, err := tx.TxBytes() + require.Nil(err, "%+v", err) + assert.NotEqual(orig, after, "%X != %X", orig, after) + + // sign bytes are the same + data = tx.SignBytes() + assert.Equal(tc.data, string(data)) + } +} diff --git a/tx/reader.go b/tx/reader.go new file mode 100644 index 000000000..7689693cb --- /dev/null +++ b/tx/reader.go @@ -0,0 +1,76 @@ +package tx + +import ( + crypto "github.com/tendermint/go-crypto" + data "github.com/tendermint/go-data" + keys "github.com/tendermint/go-keys" +) + +const ( + typeOneSig = byte(0x01) + typeMultiSig = byte(0x02) + nameOneSig = "sig" + nameMultiSig = "multi" +) + +var _ keys.Signable = Sig{} +var TxMapper data.Mapper + +func init() { + TxMapper = data.NewMapper(Sig{}). + RegisterInterface(&OneSig{}, nameOneSig, typeOneSig). + RegisterInterface(&MultiSig{}, nameMultiSig, typeMultiSig) +} + +/* +DO NOT USE this interface. + +It is public by necessity but should never be used directly +outside of this package. + +Only use Sig, never SigInner +*/ +type SigInner interface { + SignBytes() []byte + Sign(pubkey crypto.PubKey, sig crypto.Signature) error + Signers() ([]crypto.PubKey, error) +} + +// Sig is what is exported, and handles serialization +type Sig struct { + SigInner +} + +// TxBytes +func (s Sig) TxBytes() ([]byte, error) { + return data.ToWire(s) +} + +// WrapSig goes from concrete implementation to "interface" struct +func WrapSig(pk SigInner) Sig { + if wrap, ok := pk.(Sig); ok { + pk = wrap.Unwrap() + } + return Sig{pk} +} + +// Unwrap recovers the concrete interface safely (regardless of levels of embeds) +func (p Sig) Unwrap() SigInner { + pk := p.SigInner + for wrap, ok := pk.(Sig); ok; wrap, ok = pk.(Sig) { + pk = wrap.SigInner + } + return pk +} + +func (p Sig) MarshalJSON() ([]byte, error) { + return TxMapper.ToJSON(p.Unwrap()) +} + +func (p *Sig) UnmarshalJSON(data []byte) (err error) { + parsed, err := TxMapper.FromJSON(data) + if err == nil && parsed != nil { + p.SigInner = parsed.(SigInner) + } + return +} diff --git a/tx/reader_test.go b/tx/reader_test.go new file mode 100644 index 000000000..54b76af96 --- /dev/null +++ b/tx/reader_test.go @@ -0,0 +1,70 @@ +package tx + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" + data "github.com/tendermint/go-data" + "github.com/tendermint/go-keys/cryptostore" + "github.com/tendermint/go-keys/storage/memstorage" +) + +func TestReader(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + algo := crypto.NameEd25519 + cstore := cryptostore.New( + cryptostore.SecretBox, + memstorage.New(), + ) + type sigs struct{ name, pass string } + u := sigs{"alice", "1234"} + u2 := sigs{"bob", "foobar"} + + _, err := cstore.Create(u.name, u.pass, algo) + require.Nil(err, "%+v", err) + _, err = cstore.Create(u2.name, u2.pass, algo) + require.Nil(err, "%+v", err) + + cases := []struct { + tx Sig + sigs []sigs + }{ + {New([]byte("first")), nil}, + {New([]byte("second")), []sigs{u}}, + {New([]byte("other")), []sigs{u2}}, + {NewMulti([]byte("m-first")), nil}, + {NewMulti([]byte("m-second")), []sigs{u}}, + {NewMulti([]byte("m-other")), []sigs{u, u2}}, + } + + for _, tc := range cases { + tx := tc.tx + + // make sure json serialization and loading works w/o sigs + var pre Sig + pjs, err := data.ToJSON(tx) + require.Nil(err, "%+v", err) + err = data.FromJSON(pjs, &pre) + require.Nil(err, "%+v", err) + assert.Equal(tx, pre) + + for _, s := range tc.sigs { + err = cstore.Sign(s.name, s.pass, tx) + require.Nil(err, "%+v", err) + } + + var post Sig + sjs, err := data.ToJSON(tx) + require.Nil(err, "%+v", err) + err = data.FromJSON(sjs, &post) + require.Nil(err, "%+v\n%s", err, string(sjs)) + assert.Equal(tx, post) + + if len(tc.sigs) > 0 { + assert.NotEqual(pjs, sjs, "%s\n ------ %s", string(pjs), string(sjs)) + } + } +} From e49fdf7be75cb8a1c25b65bf3304e9038af9aea5 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sat, 8 Apr 2017 17:07:02 -0700 Subject: [PATCH 049/273] Add HD functions --- .gitignore | 2 + README.md | 837 +++++++++++++++++++++++++++++++++++++++++++++ hd/address.go | 289 ++++++++++++++++ hd/address_test.go | 37 ++ hd/hd_test.go | 50 +-- hd/test.json | 1 + 6 files changed, 1194 insertions(+), 22 deletions(-) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 hd/address.go create mode 100644 hd/address_test.go create mode 100644 hd/test.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..381931381 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.swp +*.swo diff --git a/README.md b/README.md new file mode 100644 index 000000000..ada192080 --- /dev/null +++ b/README.md @@ -0,0 +1,837 @@ + + +# crypto +`import "github.com/tendermint/go-crypto"` + +* [Overview](#pkg-overview) +* [Index](#pkg-index) +* [Subdirectories](#pkg-subdirectories) + +## Overview + + + +## Index +* [Constants](#pkg-constants) +* [func CRandBytes(numBytes int) []byte](#CRandBytes) +* [func CRandHex(numDigits int) string](#CRandHex) +* [func CReader() io.Reader](#CReader) +* [func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error)](#DecodeArmor) +* [func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error)](#DecryptSymmetric) +* [func EncodeArmor(blockType string, headers map[string]string, data []byte) string](#EncodeArmor) +* [func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte)](#EncryptSymmetric) +* [func MixEntropy(seedBytes []byte)](#MixEntropy) +* [func Ripemd160(bytes []byte) []byte](#Ripemd160) +* [func Sha256(bytes []byte) []byte](#Sha256) +* [type PrivKey](#PrivKey) + * [func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error)](#PrivKeyFromBytes) +* [type PrivKeyEd25519](#PrivKeyEd25519) + * [func GenPrivKeyEd25519() PrivKeyEd25519](#GenPrivKeyEd25519) + * [func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519](#GenPrivKeyEd25519FromSecret) + * [func (privKey PrivKeyEd25519) Bytes() []byte](#PrivKeyEd25519.Bytes) + * [func (privKey PrivKeyEd25519) Equals(other PrivKey) bool](#PrivKeyEd25519.Equals) + * [func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519](#PrivKeyEd25519.Generate) + * [func (p PrivKeyEd25519) MarshalJSON() ([]byte, error)](#PrivKeyEd25519.MarshalJSON) + * [func (privKey PrivKeyEd25519) PubKey() PubKey](#PrivKeyEd25519.PubKey) + * [func (privKey PrivKeyEd25519) Sign(msg []byte) Signature](#PrivKeyEd25519.Sign) + * [func (privKey PrivKeyEd25519) String() string](#PrivKeyEd25519.String) + * [func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte](#PrivKeyEd25519.ToCurve25519) + * [func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error](#PrivKeyEd25519.UnmarshalJSON) +* [type PrivKeyS](#PrivKeyS) + * [func (p PrivKeyS) Empty() bool](#PrivKeyS.Empty) + * [func (p PrivKeyS) MarshalJSON() ([]byte, error)](#PrivKeyS.MarshalJSON) + * [func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error)](#PrivKeyS.UnmarshalJSON) +* [type PrivKeySecp256k1](#PrivKeySecp256k1) + * [func GenPrivKeySecp256k1() PrivKeySecp256k1](#GenPrivKeySecp256k1) + * [func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1](#GenPrivKeySecp256k1FromSecret) + * [func (privKey PrivKeySecp256k1) Bytes() []byte](#PrivKeySecp256k1.Bytes) + * [func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool](#PrivKeySecp256k1.Equals) + * [func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error)](#PrivKeySecp256k1.MarshalJSON) + * [func (privKey PrivKeySecp256k1) PubKey() PubKey](#PrivKeySecp256k1.PubKey) + * [func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature](#PrivKeySecp256k1.Sign) + * [func (privKey PrivKeySecp256k1) String() string](#PrivKeySecp256k1.String) + * [func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error](#PrivKeySecp256k1.UnmarshalJSON) +* [type PubKey](#PubKey) + * [func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error)](#PubKeyFromBytes) +* [type PubKeyEd25519](#PubKeyEd25519) + * [func (pubKey PubKeyEd25519) Address() []byte](#PubKeyEd25519.Address) + * [func (pubKey PubKeyEd25519) Bytes() []byte](#PubKeyEd25519.Bytes) + * [func (pubKey PubKeyEd25519) Equals(other PubKey) bool](#PubKeyEd25519.Equals) + * [func (pubKey PubKeyEd25519) KeyString() string](#PubKeyEd25519.KeyString) + * [func (p PubKeyEd25519) MarshalJSON() ([]byte, error)](#PubKeyEd25519.MarshalJSON) + * [func (pubKey PubKeyEd25519) String() string](#PubKeyEd25519.String) + * [func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte](#PubKeyEd25519.ToCurve25519) + * [func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error](#PubKeyEd25519.UnmarshalJSON) + * [func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool](#PubKeyEd25519.VerifyBytes) +* [type PubKeyS](#PubKeyS) + * [func (p PubKeyS) Empty() bool](#PubKeyS.Empty) + * [func (p PubKeyS) MarshalJSON() ([]byte, error)](#PubKeyS.MarshalJSON) + * [func (p *PubKeyS) UnmarshalJSON(data []byte) (err error)](#PubKeyS.UnmarshalJSON) +* [type PubKeySecp256k1](#PubKeySecp256k1) + * [func (pubKey PubKeySecp256k1) Address() []byte](#PubKeySecp256k1.Address) + * [func (pubKey PubKeySecp256k1) Bytes() []byte](#PubKeySecp256k1.Bytes) + * [func (pubKey PubKeySecp256k1) Equals(other PubKey) bool](#PubKeySecp256k1.Equals) + * [func (pubKey PubKeySecp256k1) KeyString() string](#PubKeySecp256k1.KeyString) + * [func (p PubKeySecp256k1) MarshalJSON() ([]byte, error)](#PubKeySecp256k1.MarshalJSON) + * [func (pubKey PubKeySecp256k1) String() string](#PubKeySecp256k1.String) + * [func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error](#PubKeySecp256k1.UnmarshalJSON) + * [func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool](#PubKeySecp256k1.VerifyBytes) +* [type Signature](#Signature) + * [func SignatureFromBytes(sigBytes []byte) (sig Signature, err error)](#SignatureFromBytes) +* [type SignatureEd25519](#SignatureEd25519) + * [func (sig SignatureEd25519) Bytes() []byte](#SignatureEd25519.Bytes) + * [func (sig SignatureEd25519) Equals(other Signature) bool](#SignatureEd25519.Equals) + * [func (sig SignatureEd25519) IsZero() bool](#SignatureEd25519.IsZero) + * [func (p SignatureEd25519) MarshalJSON() ([]byte, error)](#SignatureEd25519.MarshalJSON) + * [func (sig SignatureEd25519) String() string](#SignatureEd25519.String) + * [func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error](#SignatureEd25519.UnmarshalJSON) +* [type SignatureS](#SignatureS) + * [func (p SignatureS) Empty() bool](#SignatureS.Empty) + * [func (p SignatureS) MarshalJSON() ([]byte, error)](#SignatureS.MarshalJSON) + * [func (p *SignatureS) UnmarshalJSON(data []byte) (err error)](#SignatureS.UnmarshalJSON) +* [type SignatureSecp256k1](#SignatureSecp256k1) + * [func (sig SignatureSecp256k1) Bytes() []byte](#SignatureSecp256k1.Bytes) + * [func (sig SignatureSecp256k1) Equals(other Signature) bool](#SignatureSecp256k1.Equals) + * [func (sig SignatureSecp256k1) IsZero() bool](#SignatureSecp256k1.IsZero) + * [func (p SignatureSecp256k1) MarshalJSON() ([]byte, error)](#SignatureSecp256k1.MarshalJSON) + * [func (sig SignatureSecp256k1) String() string](#SignatureSecp256k1.String) + * [func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error](#SignatureSecp256k1.UnmarshalJSON) + + +#### Package files +[armor.go](/src/github.com/tendermint/go-crypto/armor.go) [hash.go](/src/github.com/tendermint/go-crypto/hash.go) [priv_key.go](/src/github.com/tendermint/go-crypto/priv_key.go) [pub_key.go](/src/github.com/tendermint/go-crypto/pub_key.go) [random.go](/src/github.com/tendermint/go-crypto/random.go) [signature.go](/src/github.com/tendermint/go-crypto/signature.go) [symmetric.go](/src/github.com/tendermint/go-crypto/symmetric.go) + + +## Constants +``` go +const ( + TypeEd25519 = byte(0x01) + TypeSecp256k1 = byte(0x02) + NameEd25519 = "ed25519" + NameSecp256k1 = "secp256k1" +) +``` +Types of implementations + + + + +## func [CRandBytes](/src/target/random.go?s=698:734#L28) +``` go +func CRandBytes(numBytes int) []byte +``` +This uses the OS and the Seed(s). + + + +## func [CRandHex](/src/target/random.go?s=924:959#L38) +``` go +func CRandHex(numDigits int) string +``` +RandHex(24) gives 96 bits of randomness, strong enough for most purposes. + + + +## func [CReader](/src/target/random.go?s=1078:1102#L43) +``` go +func CReader() io.Reader +``` +Returns a crand.Reader mixed with user-supplied entropy + + + +## func [DecodeArmor](/src/target/armor.go?s=596:699#L18) +``` go +func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error) +``` + + +## func [DecryptSymmetric](/src/target/symmetric.go?s=1048:1133#L23) +``` go +func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error) +``` +secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) +The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. + + + +## func [EncodeArmor](/src/target/armor.go?s=125:206#L1) +``` go +func EncodeArmor(blockType string, headers map[string]string, data []byte) string +``` + + +## func [EncryptSymmetric](/src/target/symmetric.go?s=356:430#L6) +``` go +func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte) +``` +secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) +The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. +NOTE: call crypto.MixEntropy() first. + + + +## func [MixEntropy](/src/target/random.go?s=407:440#L13) +``` go +func MixEntropy(seedBytes []byte) +``` +Mix additional bytes of randomness, e.g. from hardware, user-input, etc. +It is OK to call it multiple times. It does not diminish security. + + + +## func [Ripemd160](/src/target/hash.go?s=185:220#L4) +``` go +func Ripemd160(bytes []byte) []byte +``` + + +## func [Sha256](/src/target/hash.go?s=78:110#L1) +``` go +func Sha256(bytes []byte) []byte +``` + + + +## type [PrivKey](/src/target/priv_key.go?s=326:435#L5) +``` go +type PrivKey interface { + Bytes() []byte + Sign(msg []byte) Signature + PubKey() PubKey + Equals(PrivKey) bool +} +``` +PrivKey is part of PrivAccount and state.PrivValidator. + + + + + + + +### func [PrivKeyFromBytes](/src/target/priv_key.go?s=1302:1373#L50) +``` go +func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) +``` + + + + +## type [PrivKeyEd25519](/src/target/priv_key.go?s=1502:1530#L58) +``` go +type PrivKeyEd25519 [64]byte +``` +Implements PrivKey + + + + + + + +### func [GenPrivKeyEd25519](/src/target/priv_key.go?s=3003:3042#L116) +``` go +func GenPrivKeyEd25519() PrivKeyEd25519 +``` + +### func [GenPrivKeyEd25519FromSecret](/src/target/priv_key.go?s=3290:3352#L125) +``` go +func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 +``` +NOTE: secret should be the output of a KDF like bcrypt, +if it's derived from user input. + + + + + +### func (PrivKeyEd25519) [Bytes](/src/target/priv_key.go?s=1532:1576#L60) +``` go +func (privKey PrivKeyEd25519) Bytes() []byte +``` + + + +### func (PrivKeyEd25519) [Equals](/src/target/priv_key.go?s=1973:2029#L75) +``` go +func (privKey PrivKeyEd25519) Equals(other PrivKey) bool +``` + + + +### func (PrivKeyEd25519) [Generate](/src/target/priv_key.go?s=2761:2825#L106) +``` go +func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 +``` +Deterministically generates new priv-key bytes from key. + + + + +### func (PrivKeyEd25519) [MarshalJSON](/src/target/priv_key.go?s=2156:2209#L83) +``` go +func (p PrivKeyEd25519) MarshalJSON() ([]byte, error) +``` + + + +### func (PrivKeyEd25519) [PubKey](/src/target/priv_key.go?s=1826:1871#L70) +``` go +func (privKey PrivKeyEd25519) PubKey() PubKey +``` + + + +### func (PrivKeyEd25519) [Sign](/src/target/priv_key.go?s=1635:1691#L64) +``` go +func (privKey PrivKeyEd25519) Sign(msg []byte) Signature +``` + + + +### func (PrivKeyEd25519) [String](/src/target/priv_key.go?s=2613:2658#L101) +``` go +func (privKey PrivKeyEd25519) String() string +``` + + + +### func (PrivKeyEd25519) [ToCurve25519](/src/target/priv_key.go?s=2399:2453#L94) +``` go +func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte +``` + + + +### func (\*PrivKeyEd25519) [UnmarshalJSON](/src/target/priv_key.go?s=2250:2306#L87) +``` go +func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error +``` + + + +## type [PrivKeyS](/src/target/priv_key.go?s=929:962#L30) +``` go +type PrivKeyS struct { + PrivKey +} +``` +PrivKeyS add json serialization to PrivKey + + + + + + + + + + +### func (PrivKeyS) [Empty](/src/target/priv_key.go?s=1241:1271#L46) +``` go +func (p PrivKeyS) Empty() bool +``` + + + +### func (PrivKeyS) [MarshalJSON](/src/target/priv_key.go?s=964:1011#L34) +``` go +func (p PrivKeyS) MarshalJSON() ([]byte, error) +``` + + + +### func (\*PrivKeyS) [UnmarshalJSON](/src/target/priv_key.go?s=1057:1114#L38) +``` go +func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error) +``` + + + +## type [PrivKeySecp256k1](/src/target/priv_key.go?s=3635:3665#L136) +``` go +type PrivKeySecp256k1 [32]byte +``` +Implements PrivKey + + + + + + + +### func [GenPrivKeySecp256k1](/src/target/priv_key.go?s=5071:5114#L194) +``` go +func GenPrivKeySecp256k1() PrivKeySecp256k1 +``` + +### func [GenPrivKeySecp256k1FromSecret](/src/target/priv_key.go?s=5436:5502#L204) +``` go +func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1 +``` +NOTE: secret should be the output of a KDF like bcrypt, +if it's derived from user input. + + + + + +### func (PrivKeySecp256k1) [Bytes](/src/target/priv_key.go?s=3667:3713#L138) +``` go +func (privKey PrivKeySecp256k1) Bytes() []byte +``` + + + +### func (PrivKeySecp256k1) [Equals](/src/target/priv_key.go?s=4235:4293#L158) +``` go +func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool +``` + + + +### func (PrivKeySecp256k1) [MarshalJSON](/src/target/priv_key.go?s=4426:4481#L166) +``` go +func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error) +``` + + + +### func (PrivKeySecp256k1) [PubKey](/src/target/priv_key.go?s=4032:4079#L151) +``` go +func (privKey PrivKeySecp256k1) PubKey() PubKey +``` + + + +### func (PrivKeySecp256k1) [Sign](/src/target/priv_key.go?s=3772:3830#L142) +``` go +func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature +``` + + + +### func (PrivKeySecp256k1) [String](/src/target/priv_key.go?s=4673:4720#L177) +``` go +func (privKey PrivKeySecp256k1) String() string +``` + + + +### func (\*PrivKeySecp256k1) [UnmarshalJSON](/src/target/priv_key.go?s=4522:4580#L170) +``` go +func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error +``` + + + +## type [PubKey](/src/target/pub_key.go?s=361:506#L7) +``` go +type PubKey interface { + Address() []byte + Bytes() []byte + KeyString() string + VerifyBytes(msg []byte, sig Signature) bool + Equals(PubKey) bool +} +``` +PubKey is part of Account and Validator. + + + + + + + +### func [PubKeyFromBytes](/src/target/pub_key.go?s=1203:1270#L45) +``` go +func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) +``` + + + + +## type [PubKeyEd25519](/src/target/pub_key.go?s=1396:1423#L53) +``` go +type PubKeyEd25519 [32]byte +``` +Implements PubKey + + + + + + + + + + +### func (PubKeyEd25519) [Address](/src/target/pub_key.go?s=1425:1469#L55) +``` go +func (pubKey PubKeyEd25519) Address() []byte +``` + + + +### func (PubKeyEd25519) [Bytes](/src/target/pub_key.go?s=1789:1831#L68) +``` go +func (pubKey PubKeyEd25519) Bytes() []byte +``` + + + +### func (PubKeyEd25519) [Equals](/src/target/pub_key.go?s=3064:3117#L119) +``` go +func (pubKey PubKeyEd25519) Equals(other PubKey) bool +``` + + + +### func (PubKeyEd25519) [KeyString](/src/target/pub_key.go?s=2983:3029#L115) +``` go +func (pubKey PubKeyEd25519) KeyString() string +``` +Must return the full bytes in hex. +Used for map keying, etc. + + + + +### func (PubKeyEd25519) [MarshalJSON](/src/target/pub_key.go?s=2279:2331#L87) +``` go +func (p PubKeyEd25519) MarshalJSON() ([]byte, error) +``` + + + +### func (PubKeyEd25519) [String](/src/target/pub_key.go?s=2823:2866#L109) +``` go +func (pubKey PubKeyEd25519) String() string +``` + + + +### func (PubKeyEd25519) [ToCurve25519](/src/target/pub_key.go?s=2585:2637#L100) +``` go +func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte +``` +For use with golang/crypto/nacl/box +If error, returns nil. + + + + +### func (\*PubKeyEd25519) [UnmarshalJSON](/src/target/pub_key.go?s=2372:2427#L91) +``` go +func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error +``` + + + +### func (PubKeyEd25519) [VerifyBytes](/src/target/pub_key.go?s=1888:1960#L72) +``` go +func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool +``` + + + +## type [PubKeyS](/src/target/pub_key.go?s=841:872#L25) +``` go +type PubKeyS struct { + PubKey +} +``` +PubKeyS add json serialization to PubKey + + + + + + + + + + +### func (PubKeyS) [Empty](/src/target/pub_key.go?s=1144:1173#L41) +``` go +func (p PubKeyS) Empty() bool +``` + + + +### func (PubKeyS) [MarshalJSON](/src/target/pub_key.go?s=874:920#L29) +``` go +func (p PubKeyS) MarshalJSON() ([]byte, error) +``` + + + +### func (\*PubKeyS) [UnmarshalJSON](/src/target/pub_key.go?s=964:1020#L33) +``` go +func (p *PubKeyS) UnmarshalJSON(data []byte) (err error) +``` + + + +## type [PubKeySecp256k1](/src/target/pub_key.go?s=3401:3430#L132) +``` go +type PubKeySecp256k1 [33]byte +``` +Implements PubKey. +Compressed pubkey (just the x-cord), +prefixed with 0x02 or 0x03, depending on the y-cord. + + + + + + + + + + +### func (PubKeySecp256k1) [Address](/src/target/pub_key.go?s=3497:3543#L135) +``` go +func (pubKey PubKeySecp256k1) Address() []byte +``` +Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) + + + + +### func (PubKeySecp256k1) [Bytes](/src/target/pub_key.go?s=3774:3818#L145) +``` go +func (pubKey PubKeySecp256k1) Bytes() []byte +``` + + + +### func (PubKeySecp256k1) [Equals](/src/target/pub_key.go?s=4897:4952#L192) +``` go +func (pubKey PubKeySecp256k1) Equals(other PubKey) bool +``` + + + +### func (PubKeySecp256k1) [KeyString](/src/target/pub_key.go?s=4814:4862#L188) +``` go +func (pubKey PubKeySecp256k1) KeyString() string +``` +Must return the full bytes in hex. +Used for map keying, etc. + + + + +### func (PubKeySecp256k1) [MarshalJSON](/src/target/pub_key.go?s=4405:4459#L171) +``` go +func (p PubKeySecp256k1) MarshalJSON() ([]byte, error) +``` + + + +### func (PubKeySecp256k1) [String](/src/target/pub_key.go?s=4650:4695#L182) +``` go +func (pubKey PubKeySecp256k1) String() string +``` + + + +### func (\*PubKeySecp256k1) [UnmarshalJSON](/src/target/pub_key.go?s=4500:4557#L175) +``` go +func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error +``` + + + +### func (PubKeySecp256k1) [VerifyBytes](/src/target/pub_key.go?s=3875:3949#L149) +``` go +func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool +``` + + + +## type [Signature](/src/target/signature.go?s=204:304#L3) +``` go +type Signature interface { + Bytes() []byte + IsZero() bool + String() string + Equals(Signature) bool +} +``` +Signature is a part of Txs and consensus Votes. + + + + + + + +### func [SignatureFromBytes](/src/target/signature.go?s=1031:1098#L40) +``` go +func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) +``` + + + + +## type [SignatureEd25519](/src/target/signature.go?s=1221:1251#L48) +``` go +type SignatureEd25519 [64]byte +``` +Implements Signature + + + + + + + + + + +### func (SignatureEd25519) [Bytes](/src/target/signature.go?s=1253:1295#L50) +``` go +func (sig SignatureEd25519) Bytes() []byte +``` + + + +### func (SignatureEd25519) [Equals](/src/target/signature.go?s=1520:1576#L58) +``` go +func (sig SignatureEd25519) Equals(other Signature) bool +``` + + + +### func (SignatureEd25519) [IsZero](/src/target/signature.go?s=1352:1393#L54) +``` go +func (sig SignatureEd25519) IsZero() bool +``` + + + +### func (SignatureEd25519) [MarshalJSON](/src/target/signature.go?s=1701:1756#L66) +``` go +func (p SignatureEd25519) MarshalJSON() ([]byte, error) +``` + + + +### func (SignatureEd25519) [String](/src/target/signature.go?s=1420:1463#L56) +``` go +func (sig SignatureEd25519) String() string +``` + + + +### func (\*SignatureEd25519) [UnmarshalJSON](/src/target/signature.go?s=1797:1855#L70) +``` go +func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error +``` + + + +## type [SignatureS](/src/target/signature.go?s=648:685#L20) +``` go +type SignatureS struct { + Signature +} +``` +SignatureS add json serialization to Signature + + + + + + + + + + +### func (SignatureS) [Empty](/src/target/signature.go?s=966:998#L36) +``` go +func (p SignatureS) Empty() bool +``` + + + +### func (SignatureS) [MarshalJSON](/src/target/signature.go?s=687:736#L24) +``` go +func (p SignatureS) MarshalJSON() ([]byte, error) +``` + + + +### func (\*SignatureS) [UnmarshalJSON](/src/target/signature.go?s=780:839#L28) +``` go +func (p *SignatureS) UnmarshalJSON(data []byte) (err error) +``` + + + +## type [SignatureSecp256k1](/src/target/signature.go?s=2013:2043#L80) +``` go +type SignatureSecp256k1 []byte +``` +Implements Signature + + + + + + + + + + +### func (SignatureSecp256k1) [Bytes](/src/target/signature.go?s=2045:2089#L82) +``` go +func (sig SignatureSecp256k1) Bytes() []byte +``` + + + +### func (SignatureSecp256k1) [Equals](/src/target/signature.go?s=2318:2376#L90) +``` go +func (sig SignatureSecp256k1) Equals(other Signature) bool +``` + + + +### func (SignatureSecp256k1) [IsZero](/src/target/signature.go?s=2146:2189#L86) +``` go +func (sig SignatureSecp256k1) IsZero() bool +``` + + + +### func (SignatureSecp256k1) [MarshalJSON](/src/target/signature.go?s=2502:2559#L97) +``` go +func (p SignatureSecp256k1) MarshalJSON() ([]byte, error) +``` + + + +### func (SignatureSecp256k1) [String](/src/target/signature.go?s=2216:2261#L88) +``` go +func (sig SignatureSecp256k1) String() string +``` + + + +### func (\*SignatureSecp256k1) [UnmarshalJSON](/src/target/signature.go?s=2597:2657#L101) +``` go +func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error +``` + + + + + + + +- - - +Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md) diff --git a/hd/address.go b/hd/address.go new file mode 100644 index 000000000..afdeefbc4 --- /dev/null +++ b/hd/address.go @@ -0,0 +1,289 @@ +package hd + +import ( + "crypto/ecdsa" + "crypto/hmac" + "crypto/sha256" + "crypto/sha512" + "encoding/base64" + "encoding/binary" + "encoding/hex" + "errors" + "fmt" + "hash" + "log" + "math/big" + "strconv" + "strings" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcutil/base58" + "github.com/tendermint/go-crypto" + "golang.org/x/crypto/ripemd160" +) + +const ( + // BIP32 chainpath prefix + CHAINPATH_PREFIX_DEPOSIT = 0 + CHAINPATH_PREFIX_CHANGE = 1 + CHAINPATH_PREFIX_SWEEP = 2 + CHAINPATH_PREFIX_SWEEP_DRY = 102 +) + +func ComputeAddress(coin string, pubKeyHex string, chainHex string, path string, index int32) string { + pubKeyBytes := DerivePublicKeyForPath( + HexDecode(pubKeyHex), + HexDecode(chainHex), + fmt.Sprintf("%v/%v", path, index), + ) + return AddrFromPubKeyBytes(coin, pubKeyBytes) +} + +func ComputePrivateKey(mprivHex string, chainHex string, path string, index int32) string { + privKeyBytes := DerivePrivateKeyForPath( + HexDecode(mprivHex), + HexDecode(chainHex), + fmt.Sprintf("%v/%v", path, index), + ) + return HexEncode(privKeyBytes) +} + +func ComputeAddressForPrivKey(coin string, privKey string) string { + pubKeyBytes := PubKeyBytesFromPrivKeyBytes(HexDecode(privKey), true) + return AddrFromPubKeyBytes(coin, pubKeyBytes) +} + +func SignMessage(privKey string, message string, compress bool) string { + prefixBytes := []byte("Bitcoin Signed Message:\n") + messageBytes := []byte(message) + bytes := []byte{} + bytes = append(bytes, byte(len(prefixBytes))) + bytes = append(bytes, prefixBytes...) + bytes = append(bytes, byte(len(messageBytes))) + bytes = append(bytes, messageBytes...) + privKeyBytes := HexDecode(privKey) + x, y := btcec.S256().ScalarBaseMult(privKeyBytes) + ecdsaPubKey := ecdsa.PublicKey{ + Curve: btcec.S256(), + X: x, + Y: y, + } + ecdsaPrivKey := &btcec.PrivateKey{ + PublicKey: ecdsaPubKey, + D: new(big.Int).SetBytes(privKeyBytes), + } + sigbytes, err := btcec.SignCompact(btcec.S256(), ecdsaPrivKey, crypto.Sha256(crypto.Sha256(bytes)), compress) + if err != nil { + panic(err) + } + return base64.StdEncoding.EncodeToString(sigbytes) +} + +// returns MPK, Chain, and master secret in hex. +func ComputeMastersFromSeed(seed string) (string, string, string, string) { + secret, chain := I64([]byte("Bitcoin seed"), []byte(seed)) + pubKeyBytes := PubKeyBytesFromPrivKeyBytes(secret, true) + return HexEncode(pubKeyBytes), HexEncode(secret), HexEncode(chain), HexEncode(secret) +} + +func ComputeWIF(coin string, privKey string, compress bool) string { + return WIFFromPrivKeyBytes(coin, HexDecode(privKey), compress) +} + +func ComputeTxId(rawTxHex string) string { + return HexEncode(ReverseBytes(CalcHash256(HexDecode(rawTxHex)))) +} + +// Private methods... + +func printKeyInfo(privKeyBytes []byte, pubKeyBytes []byte, chain []byte) { + if pubKeyBytes == nil { + pubKeyBytes = PubKeyBytesFromPrivKeyBytes(privKeyBytes, true) + } + addr := AddrFromPubKeyBytes("BTC", pubKeyBytes) + log.Println("\nprikey:\t%v\npubKeyBytes:\t%v\naddr:\t%v\nchain:\t%v", + HexEncode(privKeyBytes), + HexEncode(pubKeyBytes), + addr, + HexEncode(chain)) +} + +func DerivePrivateKeyForPath(privKeyBytes []byte, chain []byte, path string) []byte { + data := privKeyBytes + parts := strings.Split(path, "/") + for _, part := range parts { + prime := part[len(part)-1:] == "'" + // prime == private derivation. Otherwise public. + if prime { + part = part[:len(part)-1] + } + i, err := strconv.Atoi(part) + if err != nil { + panic(err) + } + if i < 0 { + panic(errors.New("index too large.")) + } + data, chain = DerivePrivateKey(data, chain, uint32(i), prime) + //printKeyInfo(data, nil, chain) + } + return data +} + +func DerivePublicKeyForPath(pubKeyBytes []byte, chain []byte, path string) []byte { + data := pubKeyBytes + parts := strings.Split(path, "/") + for _, part := range parts { + prime := part[len(part)-1:] == "'" + if prime { + panic(errors.New("cannot do a prime derivation from public key")) + } + i, err := strconv.Atoi(part) + if err != nil { + panic(err) + } + if i < 0 { + panic(errors.New("index too large.")) + } + data, chain = DerivePublicKey(data, chain, uint32(i)) + //printKeyInfo(nil, data, chain) + } + return data +} + +func DerivePrivateKey(privKeyBytes []byte, chain []byte, i uint32, prime bool) ([]byte, []byte) { + data := []byte{} + if prime { + i = i | 0x80000000 + data = append([]byte{byte(0)}, privKeyBytes...) + } else { + public := PubKeyBytesFromPrivKeyBytes(privKeyBytes, true) + data = public + } + data = append(data, uint32ToBytes(i)...) + data2, chain2 := I64(chain, data) + x := addScalars(privKeyBytes, data2) + return x, chain2 +} + +func DerivePublicKey(pubKeyBytes []byte, chain []byte, i uint32) ([]byte, []byte) { + data := []byte{} + data = append(data, pubKeyBytes...) + data = append(data, uint32ToBytes(i)...) + data2, chain2 := I64(chain, data) + data2p := PubKeyBytesFromPrivKeyBytes(data2, true) + return addPoints(pubKeyBytes, data2p), chain2 +} + +func addPoints(a []byte, b []byte) []byte { + ap, err := btcec.ParsePubKey(a, btcec.S256()) + if err != nil { + panic(err) + } + bp, err := btcec.ParsePubKey(b, btcec.S256()) + if err != nil { + panic(err) + } + sumX, sumY := btcec.S256().Add(ap.X, ap.Y, bp.X, bp.Y) + sum := (*btcec.PublicKey)(&btcec.PublicKey{ + Curve: btcec.S256(), + X: sumX, + Y: sumY, + }) + return sum.SerializeCompressed() +} + +func addScalars(a []byte, b []byte) []byte { + aInt := new(big.Int).SetBytes(a) + bInt := new(big.Int).SetBytes(b) + sInt := new(big.Int).Add(aInt, bInt) + x := sInt.Mod(sInt, btcec.S256().N).Bytes() + x2 := [32]byte{} + copy(x2[32-len(x):], x) + return x2[:] +} + +func uint32ToBytes(i uint32) []byte { + b := [4]byte{} + binary.BigEndian.PutUint32(b[:], i) + return b[:] +} + +func HexEncode(b []byte) string { + return hex.EncodeToString(b) +} + +func HexDecode(str string) []byte { + b, _ := hex.DecodeString(str) + return b +} + +func I64(key []byte, data []byte) ([]byte, []byte) { + mac := hmac.New(sha512.New, key) + mac.Write(data) + I := mac.Sum(nil) + return I[:32], I[32:] +} + +func AddrFromPubKeyBytes(coin string, pubKeyBytes []byte) string { + prefix := byte(0x00) // TODO Make const or configurable + h160 := CalcHash160(pubKeyBytes) + h160 = append([]byte{prefix}, h160...) + checksum := CalcHash256(h160) + b := append(h160, checksum[:4]...) + return base58.Encode(b) +} + +func WIFFromPrivKeyBytes(coin string, privKeyBytes []byte, compress bool) string { + prefix := byte(0x80) // TODO Make const or configurable + bytes := append([]byte{prefix}, privKeyBytes...) + if compress { + bytes = append(bytes, byte(1)) + } + checksum := CalcHash256(bytes) + bytes = append(bytes, checksum[:4]...) + return base58.Encode(bytes) +} + +func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyBytes []byte) { + x, y := btcec.S256().ScalarBaseMult(privKeyBytes) + pub := (*btcec.PublicKey)(&btcec.PublicKey{ + Curve: btcec.S256(), + X: x, + Y: y, + }) + + if compress { + return pub.SerializeCompressed() + } + return pub.SerializeUncompressed() +} + +// Calculate the hash of hasher over buf. +func CalcHash(buf []byte, hasher hash.Hash) []byte { + hasher.Write(buf) + return hasher.Sum(nil) +} + +// calculate hash160 which is ripemd160(sha256(data)) +func CalcHash160(buf []byte) []byte { + return CalcHash(CalcHash(buf, sha256.New()), ripemd160.New()) +} + +// calculate hash256 which is sha256(sha256(data)) +func CalcHash256(buf []byte) []byte { + return CalcHash(CalcHash(buf, sha256.New()), sha256.New()) +} + +// calculate sha512(data) +func CalcSha512(buf []byte) []byte { + return CalcHash(buf, sha512.New()) +} + +func ReverseBytes(buf []byte) []byte { + res := []byte{} + for i := len(buf) - 1; i >= 0; i-- { + res = append(res, buf[i]) + } + return res +} diff --git a/hd/address_test.go b/hd/address_test.go new file mode 100644 index 000000000..0554733f1 --- /dev/null +++ b/hd/address_test.go @@ -0,0 +1,37 @@ +package hd + +/* + +import ( + "encoding/hex" + "fmt" + "testing" +) + +func TestManual(t *testing.T) { + bytes, _ := hex.DecodeString("dfac699f1618c9be4df2befe94dc5f313946ebafa386756bd4926a1ecfd7cf2438426ede521d1ee6512391bc200b7910bcbea593e68d52b874c29bdc5a308ed1") + fmt.Println(bytes) + puk, prk, ch, se := ComputeMastersFromSeed(string(bytes)) + fmt.Println(puk, ch, se) + + pubBytes2 := DerivePublicKeyForPath( + HexDecode(puk), + HexDecode(ch), + //"44'/118'/0'/0/0", + "0/0", + ) + fmt.Printf("PUB2 %X\n", pubBytes2) + + privBytes := DerivePrivateKeyForPath( + HexDecode(prk), + HexDecode(ch), + //"44'/118'/0'/0/0", + //"0/0", + "44'/118'/0'/0/0", + ) + fmt.Printf("PRIV %X\n", privBytes) + pubBytes := PubKeyBytesFromPrivKeyBytes(privBytes, true) + fmt.Printf("PUB %X\n", pubBytes) +} + +*/ diff --git a/hd/hd_test.go b/hd/hd_test.go index 42d034717..e771f14b6 100644 --- a/hd/hd_test.go +++ b/hd/hd_test.go @@ -1,4 +1,4 @@ -package crypto +package hd import ( "bytes" @@ -36,15 +36,6 @@ type addrData struct { var hdPath string = "m/44'/118'/0'/0/0" var hdToAddrTable []addrData -/*{ - { - Mnemonic: "spawn essence sudden gown library fire chalk edge start museum glimpse sea", - Priv: "ab20a81c1b9002538e2269e1f1302d519901633d40408313211598899bc00fc6", - Pub: "03eb89fb1c4582eed592e09c31c4665d3956154ea66fd269933d3f036e879abfe6", - Addr: "f7d613738f0a665ec320306d14f5d62a850ff714", - }, -}*/ - func init() { b, err := ioutil.ReadFile("test.json") @@ -71,30 +62,30 @@ func TestHDToAddr(t *testing.T) { seed := bip39.NewSeed(d.Mnemonic, "") - fmt.Println(i, d.Mnemonic) + fmt.Println("================================") + fmt.Println("ROUND:", i, "MNEMONIC:", d.Mnemonic) - //master, priv, pub := tylerSmith(seed) - master, priv, pub := btcsuite(seed) + // master, priv, pub := tylerSmith(seed) + // master, priv, pub := btcsuite(seed) + master, priv, pub := gocrypto(seed) - fmt.Printf("\t%X %X\n", seedB, seed) - fmt.Printf("\t%X %X\n", masterB, master) - fmt.Printf("\t%X %X\n", privB, priv) - fmt.Printf("\t%X %X\n", pubB, pub) + fmt.Printf("\tNODEJS GOLANG\n") + fmt.Printf("SEED \t%X %X\n", seedB, seed) + fmt.Printf("MSTR \t%X %X\n", masterB, master) + fmt.Printf("PRIV \t%X %X\n", privB, priv) + fmt.Printf("PUB \t%X %X\n", pubB, pub) _, _ = priv, privB assert.Equal(t, master, masterB, fmt.Sprintf("Expected masters to match for %d", i)) - - // assert.Equal(t, priv, privB, "Expected priv keys to match") + assert.Equal(t, priv, privB, "Expected priv keys to match") assert.Equal(t, pub, pubB, fmt.Sprintf("Expected pub keys to match for %d", i)) var pubT crypto.PubKeySecp256k1 copy(pubT[:], pub) addr := pubT.Address() + fmt.Printf("ADDR \t%X %X\n", addrB, addr) assert.Equal(t, addr, addrB, fmt.Sprintf("Expected addresses to match %d", i)) - /* if i%10 == 0 { - fmt.Printf("ADDR %d: %s %X %X\n", i, d.Mnemonic, addr, addrB) - }*/ } } @@ -105,6 +96,21 @@ func ifExit(err error, n int) { } } +func gocrypto(seed []byte) ([]byte, []byte, []byte) { + + _, priv, ch, _ := ComputeMastersFromSeed(string(seed)) + + privBytes := DerivePrivateKeyForPath( + HexDecode(priv), + HexDecode(ch), + "44'/118'/0'/0/0", + ) + + pubBytes := PubKeyBytesFromPrivKeyBytes(privBytes, true) + + return HexDecode(priv), privBytes, pubBytes +} + func btcsuite(seed []byte) ([]byte, []byte, []byte) { fmt.Println("HD") masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) diff --git a/hd/test.json b/hd/test.json new file mode 100644 index 000000000..fa9610999 --- /dev/null +++ b/hd/test.json @@ -0,0 +1 @@ +[{"mnemonic":"measure slogan connect luggage stereo federal stuff stomach stumble security end differ","master":"c177fa4bd21420b6ba2246e4f7a43fbe76545d1204174cae942ffbd79a434d11","seed":"c237f7aa198c5bd560ac8daf5b8421d03855171465b2999b07159671e9186461e7d75dba6c7264b963108431f8674ac8d095b7a22878fa0ab8b582e5d6ea1986","priv":"91bba8805845210665d7a9c5aff63ef69f7604fbeddb485706d31f04458f572c","pub":"0210ddc89abc90bbcbec8c63f5a4ebb016b58063b9d1a77854502042bdfcac5e51","addr":"72e7d6e9cfa899043a0783752a4876423f8effb8"},{"mnemonic":"car taste absurd genius miracle toy earth true glare mobile pig forest","master":"d7e07c472b05a2d668328c148ca07264afb4b53e078a2e1c106470b51c6ef81c","seed":"fda7006f5e9b8d1c02404df6d4e4497ff5c2edf29c801180a046dc54fca2e019554da6e3dd2c26073a7871c5ac529ad465ccf77ec3608727cc47ef88f998ae2b","priv":"1122ac929a0a3b2947ef99c33c20b657cf7342ea09be92869c363cfc52118200","pub":"03d0b431b56ae65aeb5a572654445b3fc968fa9d73995d3b21243cb07ed1ef0067","addr":"63eba204c249c795cd9dbdad58561db56b1d0c9b"},{"mnemonic":"trophy crop coffee oppose pelican help sense note bar faint hen aunt","master":"d1baaea05c34a4bbdc6791ada5aad77fdb0e626642cb884e48d25cd4ef6c9bed","seed":"1cdcfda64cb0e4f5806a48ff374e9f5f7d2939815e7adcce3abd898a7a9204eec4a5822997ca556ad797b4610c4ae6accddc29d80fd651a33d5ed911892479f1","priv":"c4bbb8f1ec60271c1e4f9e019ea45f82ca0ee3c42d8ac268f898fdbdfc28cf48","pub":"03abff20397222f9cae536d6b6776ba48c9b51898f7527dea918058f986fbfad15","addr":"fb6abc72817a9d2c6c1a2fe652434999661e1178"},{"mnemonic":"embrace office author among dream island social gift ask drill polar festival","master":"8d58a57b66a08bc0bd8dde7a718432a01f7aff03cbf999aeb3830d7a1c3d0d54","seed":"65b81faccab573d4a4272ab7c46e5fcc7db66eceeab6796d6dd70d8c54d6c95c3b73a637210a96a95df5ef736f51eec1dd3af4ccca53e98fb7f16d4e22dc3f52","priv":"dec3ffc51d5c9eadfb11e11dcc640f8cb294a21cfbb4a230f164693d57851b3b","pub":"03ef202a875683203e9d9643a2943cb40ff5a69b6efb3b0dedfc8ab1c6928261d1","addr":"db1a5fd30abfe666a049f5c6689a0e3db3ebec1e"},{"mnemonic":"aware gospel lemon tomorrow east wheel member forest walnut virus shallow stick","master":"24075bca853e0066909a6ff06ff02f196d4d641c00677704a6472810b0e3263e","seed":"1a4419cb19e2e7686fe68187aa55a2d4fab8d655c505c5666963d61bc9e92cfb990402d8527f9463b2deb3e86894055e3c6b31cf9995ca5bdf9959db755c9e90","priv":"853665c8f66682e50db33fe699ee72dae036422bee03e37093ed95c871ae8309","pub":"02a4e19e61decd6006bec54fa9c7ada7ee63ca6df12640e9fcf4214faafce791e6","addr":"155dac0e19dc24880b5aed827ebabb05bb563b23"},{"mnemonic":"perfect chief lend clock bracket guard extend medal slice vague cheese child","master":"b594e8d22e4864bdf75ddf29de16b7b207b2bbbdf29132b859f9c71c919ff669","seed":"631fc64164825a9769c4cd376cd736d4dd4191b7728e70b1e84b46322cb8bfb01b5b33cc6707d59bed09f6e7c82335541cd7dfc51ebedfcc2786713a9d141663","priv":"eab18ec583e155fd4ece4a14248bda80c75a6f209a1e4a9b1801e1a707b4356e","pub":"0247995311612868a8d1f6927f18ae5163a9d64a41d8f4015f9dcbbdace9277ed3","addr":"1f42f6538f64d844cef39b941986465076da3d54"},{"mnemonic":"edge early ten vicious piece begin observe ripple neutral farm volume accident","master":"1d6462662cd27419936c1f5b579eb7ebbafe84a6b1a58906c37fc0c2aa612d22","seed":"fb9588a1e3a2d9c26dcdb3cb010b8f868b29c493c95f7fe16761b2a666a8b96ca62997646e8d2cea1ff8ec3b85bd2311741ee327076515ad075623853279b57e","priv":"081847ec4f11a7d54ddd78c6f0fb3cdc32508e4956da14e0d728ddd3862124ce","pub":"03533c9f60afc94de73a0abb7d3e98906fa72cd2aebb202fdac32e2014452779d1","addr":"bcab563beb9ead1a87ab5adabc708502dc4081de"},{"mnemonic":"escape crystal wrist method cave retire wedding unable fringe inhale vibrant inform","master":"8b8597cd8ca42fe10236cc933bf0adda507132be6c41451d6ddda615b4032798","seed":"84582da23a6c4cf3d8f75be55db0d2710e10e31e9d6cee8288d827ed17d6585f19d81831aac12aff8d2724ace9c4220924e7d778eaebb3ff7ac4976b5ee25cc9","priv":"d011566a0c3996c99cf02ee41aa3f24c3328b5773ad0c9ea23f1bda1967a7e2c","pub":"03dcb9dd25915f827965c2d64e258eed1e4cf55f9fa3a9a8b5b411cbccffb11de0","addr":"54eea7e51aec6be8eca7a556c0ba5abfb702b34f"},{"mnemonic":"alter buddy rival question bachelor expose unique menu east sample also fence","master":"0eff009e6a00061a23a9b26f365cc00b0189825fe2eec0a3e78928fbd9f4dd7b","seed":"afa260446549711688b754edf33e313ceaece5502d0dbd8d82bc3c797151741620e403575ba6b54b0071e7122c8ae54893ccf29a43de209c67f7a8c296e47c84","priv":"39be182557862e0b7cf6440fb23568e54772edf734b4710ef571b37a6c27d16c","pub":"032c0d9bdbb97f2b7041734968eae96b3283573b9eefcd3ea1ce286c872bc8df4b","addr":"cbc2321a8e91ea81a56150689921b65a402b5c63"},{"mnemonic":"jar toward train panic unhappy control artefact horse deposit liar minimum pink","master":"009a99faadbdaa139f7ad2297367fdf92103c75194097133b51e0dd57629d06f","seed":"75b28bd52420c950aad1b4270fea0f8816c240e1bb16ad7f35a4bcc234e1c0bce4642422ea359dfae0332417c188a10e1b7efda4a9129809d98a179e8ef618dc","priv":"fbb6c27c23346fb30aa1aca0004f3adff649067efcbcdd58f9e8ed1be9167624","pub":"02463386f13659d68ca10edbecafab3294fddfb989b8012dd8a306c1e716ea73bc","addr":"9aef504159fcefcce23e49b64fe73d64b652751a"},{"mnemonic":"wise undo month ugly case garbage cannon torch sight burst flock enter","master":"e8533102aa8baa896888094c49fd096151adde972cbdd46429095b6081226d88","seed":"c64eab45997b8f27af96667bb8b3e3b1f13cd1cae3f33d357ef8996e958a24f78c6fff1dd21a7aad45a236d02e93722a74827e723415f4c3d2e28b5755ce74bf","priv":"7b28255abe4b5dfc46dd3e4a78aff23fd519ee20d0fccf77fa1f08dc87d4c2a8","pub":"03666213b09e6838c37edd56d858361cc7252aff15c86d9cbb7fd2ffaab2797eff","addr":"8de416131b81c2b4fb347c619e162e5b9d8e9171"},{"mnemonic":"fever hotel cup cover lake cream hello drastic scrap appear device skill","master":"c0c7ae8be6467f73da04bf31893fed60a7d2874a1b8b40cf6b947d3e0c072fd8","seed":"ba8ccb1d6df012c48cd0e97e126aca7192fc49ffe58fe554f2f96b85f7c8ee842e582a7967e053c4ea26f5ee0730dd7b78212b397f5ad89c0691c151c5b649b2","priv":"2d28bdd1c56e6f0c953b97ea571d7ee13f4b53557e9de79de436faee8b984944","pub":"02d4ef64e150ee986d14953bb42d7da5a26e184ae00d33c648e552ec31cc81df62","addr":"1919c6f2d0c93447d4fb8f10b8af4c57a06ad235"},{"mnemonic":"camp pizza test idea attend urban pond gym solution denial coach oppose","master":"e85ce81ff0663a945753449ea5a53a72e429a7badc3c681d7c13bb1b75a4d2ed","seed":"2bc62e90ae9d83635b316ef55f4ada1652dea512da332474598f53f93268ee1e18802ba19e75df651cfe931049ccc7aba7b96d43b62182e0e5b0e21a1cc2f489","priv":"bbd3109cd6edfc583ad1fca84b3c32def7d41e36f1994ac40eb5fd9f72211a47","pub":"032a3e6b6d55ede0c25b78a2bb860adea7ec8b3dbaf7340197ad2d0c07e1673a1f","addr":"4f9ba3935c15ff8ce14f0b09ef498e50693c4c90"},{"mnemonic":"solution buffalo armor capital enter cat banana manage caution loan people gauge","master":"1d894a5d9932bc19f91fa92f0d03f25136a77b4eb961ddd742b74c54edad9332","seed":"b833db5ff34a1bddbbee895d96518261025bbc6a9be596d58435468f1547ff378f504062aab7add0c69763708238d0ab42a90f6af0b790caa1569d1cc089b605","priv":"4e26066e7ff8936e63fb011173f70b0206c1b6ecaa519fb252185e18dbc19705","pub":"03fd00f281ba6065cdc8f6a8cf17cdb22b2ccad62eeb535708381004b2a260837f","addr":"e6247dacab881ff882e412630350eaa6de14817a"},{"mnemonic":"power answer mixture choose course crop decline border carpet absorb long artwork","master":"1d74c0120756009f821899f220d3a9e77291e0549241481b657ddb84af1b66f8","seed":"cd9ac735fee9bbcf45bd79b31196138b3ca002513bd1fb973eae4bffd0c5732611cd67006af3f79dd127ce21532947a0c1355cc774faee82f58cdbef6f8bd7fa","priv":"45f7df4a90d4ed0f58c47ab4839220f50689cb2a5663acd9cbb359d6a23e465e","pub":"02697233abb54eeef1f03a371b0da9a97e85ffe404707b5b7ee3f0e3d2e2f0768f","addr":"0f5addad3faaad7ebaf37c3d3f2576a0a1a5e533"},{"mnemonic":"patrol room turtle cinnamon remain tank butter hazard expose winner rough pull","master":"91eb616d5be757e91052fe74042515b828e2bb14f5666370d7ec37c45018abbd","seed":"7e3b9d910c4b16b06e813b2b003d9c0e8c76ec520702be210d9ec2ef2406e7f473f09f41fda56b6a657c2f1000130e11a88362209c6b4b47362e786b7880916c","priv":"ffc2a31bf0371a095cadbad2e0b5adc5669ceb6faad08da818c3c64e4af53b44","pub":"03b50efecc97cc7d7f101fdcae02662d49d118a63f03180889d8321019f245f6aa","addr":"0c43cd72c09dee746c3af1691b495a8c02286612"},{"mnemonic":"bulb neglect chalk congress cattle found balcony easy tube sick journey quick","master":"a7c632878e900903d4e0e6bc57291f1e64981d703e27b82c2da00dec800d5570","seed":"aaa765dce33f6b289d37fff2e409a540a29f3830a7baa0526eba3317d559ef59e8936e8285b6ea8a62753ec72616163e24963e49d795f38df210836ffc7d8807","priv":"f8b281b658e9a584087e16eab0179747db5c38193cada4fc85364a8f743bfec9","pub":"0384df6f5de3f50793f62eee838d30334501d6339998a25889688ba305998d15cf","addr":"cfe9adc1e454387351d4ef2dfd086101a0012863"},{"mnemonic":"arm asthma voyage mansion hurdle alley ensure team coffee palm spice general","master":"48e37cc4961ff1234938ca5ad6ed22f668b29017067c283ebf2d9642cfc2e57b","seed":"6bec879e82e5d243a6bbd5a0a5dcd21a6403d450f0f498975d5205da7154f62350cf0afa034f921cfedd4dd4dde0b6e3e9cc118b16b6682686211040b3b80b6c","priv":"b0b487d336dbb594947dab6717a5f140056d998f9e8428307491d12b3f9e3883","pub":"039db2ffbad67e7e824bfd0cd9fd8798647390b8c9a583807995a9b49e252279c3","addr":"1353002776f22c179aa208bbdddeab3c369c51be"},{"mnemonic":"spread curtain furnace trim funny usual age floor crunch blue urge pistol","master":"3c44072b545e2e955892ee4e6e5949b748d17d47d3ebeda85fb50a341bda7668","seed":"05376e4a1725d48191bebb1e03bdf76880d82b033f597182becbdcf78f167b260bb5cd6b79681f7ecd7ec75c241f90cb40b2d57d108bcc1b7766a63002af1960","priv":"58285cb1f39d00c6aa84a32a69e0e108ca80e33e75b7b4890e182a7e19485a36","pub":"02e4194b7eab20702d498ee7eb7cc98c3ac8d8b2fc63aa66bc81aad93bb1aa3b71","addr":"9b8ded654ae3336405f0bdf768d4293c462ed51d"},{"mnemonic":"century outdoor world grunt member stuff holiday intact property race mutual vehicle","master":"9b9fcc1fedcf63ae9fd216f9a7253f85cdec90f9b1fdca0c36b03169a5860ff6","seed":"e39f8455cceaf542d4062d998b8de4d7e153e594224ef7d7069abc38acf479fd2485f0821fd9af2116c58180f0069af32d10f0b7222eaef6622de83741824999","priv":"e7b4c942473ebc56868904e588bea3342f761528ca90f2add423e17615ef80cd","pub":"02059867db3a2ab4307a5ff502e9f89c45837927eb2f2b75fe55f0dcf25df9e1ee","addr":"714b9aa6afc10a40d702076990a451dc3ee4fa4b"},{"mnemonic":"world trade divert sad unable plug stereo autumn father ankle biology clown","master":"dae1a9e15469905d0d20172bbaa768be4ea4900594080499a56a69d1ae6d0557","seed":"50169fc286de6432685d85b4352908b079ab4fd11f1d8c6a82093093a9161650c2e10d8407f65f8cd1cf4d9d557590f21f5c717a761e7918ef8ca9b73f410120","priv":"4cd8309f36881d1afbfba66b9fcfa09f948d544db0baa3d81d3bd4d2067950b7","pub":"02a86d26c5b309f49017d4778b13be315cdd1d7c3baceeb61fb91c78bfafda4447","addr":"36e8463e55df56e01fd08b8fafa3ec1704ca5480"},{"mnemonic":"observe minute art scheme pear lava search dove cube entry orbit worth","master":"b7ad8e5b587bf747fae6c42423fc4cafecde0db7c9443d48afe10115d95f9b93","seed":"f3ac2022097390a9a0ae0e47d7746e6bce017d15d97ab74b1f99f70ed1c1e9b3534bdafb69e2aba1a7fa2ad787e9ac6b408f2259259ed4f744054504b05c2001","priv":"63797b9d76fe914825f90664c4a109501be006ce9049d561b9f6798d5e518c33","pub":"028b851a2e41625548564242b16e4bfe07cbf685e2df45dfdaefb4aee9fcd607c9","addr":"16d7f83a219857fe095aff5c31e30333e06b329c"},{"mnemonic":"sphere diamond electric milk furnace uniform tomorrow fatigue mercy isolate judge arena","master":"f88c8bbcf7deb1636c5d96003a2bab945a518278d9d58782cc9e7c9fba4facbf","seed":"5660e5ac88a5c43cf14cdae6929c3894ea5aa3bccf3307f85f1162880562ca352153fc1955b21e8533ce844e79583ab95df0c4199b9bac4520ca1c2821ab4f18","priv":"700fd3176db1c0988d7c35d5ef2cd109c7f52b583ae665011f5d476e5a7b3ff5","pub":"022efb00f6c83d296a12f787239fb7905b7f0c27e4fbb62ae62fe43a91cffa9bf7","addr":"7e4a94be643599be266227f349d4797fb7befb89"},{"mnemonic":"syrup unfair confirm hunt flee armor limb travel hint ski mother credit","master":"01aa87dd513611771cfeee1a39986b13fff29760f0d4c7cfde678e70fd053909","seed":"0e54e0db6ff149c9c572a14c3902fdddd567c8ec361ba3bcccb3a407e3e5c6767ec71eaae2c75aa1fcebaaa95e14920e803d824ae4ce64b13413734dd4526836","priv":"72258e31f535c698fc029b953da4c0a89448e5633cccf27e3e6680bb895dfb99","pub":"02b9e8b06d6ef0ae29f911d48c7facd2528a45f432efb4f2c1f1eeb6056380de2b","addr":"90500208588f51b84399e4ba62ffb653d513cd43"},{"mnemonic":"embrace travel lake capital dream shaft focus kind card hood enjoy memory","master":"04e38c8074b77f3ae174593b3c69cf2f55bcbdc02bde68079691e2d8f4e26e6b","seed":"f9d883ef73a830ccfea41726a150e50c9c51b9acda9e4d022c0b8852a57f6df5d8f26542ef1bfaf83eddbe276b8f16cb7ef151fc512dbe005e473a64a5b84250","priv":"3c1b914b34fb0e5866ef082def1cc4fa589ac0d7be5813621d22fffe68b0d4eb","pub":"0381cc19aa68c4ce5bb656a1ac6d1f93375ae096826f99b46548b69c4a9d07e30e","addr":"2b82395c3c65dfe0c8a82928bb3a53e745e29d26"},{"mnemonic":"rabbit choose combine yellow permit raw puppy interest spring work wall humble","master":"04d834acb4020196f894564e1fe631420ce9e801b27bfdcf221c3068aecf3eef","seed":"1089688a78e4c6e35761aee10a12600d9f48eca57d239eb4573b4ccf28925cf72561c2921b31bdc5b00a222c537ef8c37773cedc7742f61633f1adcf94dee039","priv":"132eb740a216f2e92c7c5f96605ae61824ebcc4fbecddfd17689a1452fa174c0","pub":"03ad014b5a58c19ea616716e555dc7f30c67b5fe06bf77cd91e179f8218ddf89fa","addr":"8e05459a88d149b8473c0411a175c0b070423e05"},{"mnemonic":"bracket what unlock tooth melody wire chapter verb grow direct spin rescue","master":"f64c4e7a30ad534ca260cd280f1e8a6055e63f546d57e61071d5c7937273b4e6","seed":"56ad6c16f5bcdad95f566e8628fcceec9f00cedde68816077e0b6db1c106fc3203052ad334a0fa4b232157ba09983087d853240495fd010ee416a38cd3158108","priv":"37f99cd9868a0e44bf26a0a3180cb13f7e4fc0e379cb035b30bff23dac6518fa","pub":"0218c1d6b479b4a8ed804f62c84397d0ba8405a1a266c5318130f0c8473a60412b","addr":"224d710168a45dea667015231a3b8f910ba91191"},{"mnemonic":"position nation recipe recipe friend defense friend engine that leave match finish","master":"15aef2c47f684437bf88e44e9e518a5c517f16e163efa24f1ed8414d5e975933","seed":"15df2473af5b7147abb3b7d17da3d9668901d37ccc86ff652c9ebc75b596e8f3939e77ba39194276a659bd86947a50fef8ba147058db007232a4648e8c642ca9","priv":"59eaffd27a11231bdb4b39137e6667fe2c3ed81e6ead13818e4cd966729d558e","pub":"03865fbd6db962067b2547f69afd7effe57fb3dd3342bf5255ea6d5456dfea0842","addr":"0a0c1411a031ffc35f95c214e9a580ba4eae6c02"},{"mnemonic":"sight broken hockey empower hair never bean beyond glue small coil barely","master":"b6847c7371864fa8e19e57718425d640a027593b535d779b815e003098294910","seed":"3ad83d292efb99c2fcec6c12433c5fab6d250ae5895e0da6f1db3103bc12d82527be2853711532331280d3defa5f8bfe58fd325d11621c9a10b5c7712b02821b","priv":"9c3f71613d8ca92267a45b562e39e7e12305473be0a6498b3d2b9fa4c65b743d","pub":"02f9461c5bbb2e8ab8281f1384b5f0d412abb970b82e43ef0f1c44b9476319d87b","addr":"501b211909a1647afffe57f1ab7754d4c48940b4"},{"mnemonic":"pause usual cigar festival vanish direct amateur bone orchard cloud fall fat","master":"acdcc1f311b27f850eade92937a5d7a3a9ea1513e2ab5d08fbacba42ea267c30","seed":"cf00b72b84afc0e4b0e2480c6ae55ec1c5ef8eaa0bfa531432b3e9578fdd4ed5199cd24ab22e1cade76f0b763d901becebe686770f3409a8aafd2ee89f111b00","priv":"f0412e04a062aa3cb70cd68fcd327446121c76c33bc440ff93f63e05cd1aeea8","pub":"033708eb3564ba835b779fbce8ad6d64501333c05d0fd798c92f926256464149a4","addr":"92a06b244988b778f0986502d8ffe1804f78d10f"},{"mnemonic":"caution unusual response boost dose jaguar nice exhaust chunk tobacco cable toward","master":"7c584d3382f394a4d07684df15e04c482ba0dd3c8223a97c92c091bc95d2021f","seed":"17e49b743fda3aafe81ad205605dc7012a2096cef2475b7b12e79e54b625de459de8661ebdfacef620c851a11a0237c781ad2a84e7e30abe42f63d8da460267c","priv":"9666bc12bd5dbf4eb4bc1a8acfa021ba8f862e5551d16dd97e8e49381259196a","pub":"0314e1d0b675c88061db3d87de6bf4728ce8ec170bafc754f4fd846341ddad619e","addr":"9b695fc1b1429ec5f697df05a1f4c850489830c6"},{"mnemonic":"dream walk typical enroll knife gallery kingdom dynamic extend course shove power","master":"a0bef19259cafacafdb4854e37f36b332066b5c571538e970a7057ca0d97db1a","seed":"7d2bc8f37a8215149b75577f9efd29e0ada9f5db469e9125883804162dc7b100373f020667c06bebbcc593452dada790237ba11ef638573210d2fe67c7e7f205","priv":"370caa36a7e3a5aead2d4abb58d57b90299b4a65484613e5f39b0b7d1733e1ca","pub":"03bfddfb81e4058e08f3ee57b06065194c252e2a31b074acbb15cc7c5f6487368e","addr":"6299fc81f05eb71fa12dc69b2ca4ddfb6514af29"},{"mnemonic":"apology benefit donkey van target neutral success hen easy capable smart stuff","master":"dd96dfa3d46e0bf70df538f0da3b94cdbd7c20e170c8875032285ed7f6654ba2","seed":"c3e6214d2db9684e4c7022311861a013853761ae9900ea823fc4bc6d70bcb8de98f100664f0a04d32e18cceeba41539f9237e89400cf94e0017fc66622a902a8","priv":"3add5757d65ed58816a2b90411d2019d206b56692205724d6e412a26da88abe9","pub":"033607f86548d8e432cc23c8c995749dbb0bc0731121b90b952465fadec31df521","addr":"e2073969ad58513da3df1225e5266e03c0917e46"},{"mnemonic":"sing eagle hello october action alien equip tongue riot pave oyster fit","master":"03f58c7803af441682b522de573e37b218fdaeef55d9637c1ff8c58e01e57564","seed":"7b9cca7d24f97bf461619b101ecd343455f9b00146fec997ddf3e1c569c615e010cdac3b6643a6e9f4ec45be954bfde0b0320e86b0e869c121ca0adca7d11b5a","priv":"21f52146c31e0a6ab9016b717f0435b36847d5b72d83183b3719890171599068","pub":"02f391dc750aa937a7b89dffc9543f72e73d6939fda1c0d74dcf99f27140656307","addr":"7719d5badc862468acdaae65afef4e1e2ba5fd08"},{"mnemonic":"proof symptom trap diary biology tail cement interest fruit tobacco soccer prosper","master":"a0e4189e097622681654ff2b346e79bbffb8e4e7be139567fba8b2c6aa427096","seed":"557153d485c01cf29622ee3a2e1fdad38c815a7cfe72eb18c85605a96c30e38b16ab37d9a2be07cbee7a211e911bdaf460d47a07d83f385fdae9217eb70487e0","priv":"57a2ee34ff6e6cc2dcc3fe3b907cb44fcce0251013877d46b04e24c9aa20ab73","pub":"026172d3d801fb6e855e2eb0f1171de15e6823bb13002b4e9b01a41cd430da7f69","addr":"a1a953df8d8ff38614bbed7ea9f704ef98a37435"},{"mnemonic":"wire gorilla pupil since trust open amateur evil chicken razor minute science","master":"bb549a48f5610f28b23bff00b8b0de2c93bf4e093400989632c98feb3f45967e","seed":"b05c272f522ec2c53dc26679e207f2c16b6506de02e8fb231175265445218fd8617222a374beadfe1999ed617d5a1f89e0a93c85bc022eff6468c4646f3ea381","priv":"2e96c265f6cafb5912bb2748ff4e0d4b9e960d0b4fbc92967a73591c6d7f54c6","pub":"030d6aa64cba047b2ee2c5af2d3893e17004e66762696e6375b09e32e3675daa21","addr":"e065248114f65902b5cc3aefcc1bbbec4d7ed597"},{"mnemonic":"deer meat share below retire when crash original boy wide leaf blade","master":"47f23c913c2e53d34f7c5d869fccfc07a9a5a7a2e2e811abf9781c69aebb4ec4","seed":"7f1a2f19bab3b121415adf5ffc709749b009fdb90df35b6f3b7d17d8eeeae0d41e0f37565c5320b90edb50076d712aaa5e606a88a44460cea67cb686f1886984","priv":"dcb974cc926c246144d1e6c1c5b3babeb4de3be7dd24ad40d6fbbbc592f384ee","pub":"038d6fa489c22c5a8d95d6931144de5d61748be81076b8cc2f6a0c928065f098c7","addr":"4c8a5b45086b2514f8094d3579b2d420b36f7af4"},{"mnemonic":"accident symbol token cotton enough false cereal verify item army pulse sell","master":"70b049648afff7bafb6ac1d8f5a2e2d78bea9fa93c2924f0cba70d4aee27dde6","seed":"d58819c9862ce8078a2b4db0a25434f03631bac4143590f1a245eed73d41f68f0ab089753064eb879b2edf1a56ccb83d0fa88721cbe2ce05f2c46c040dbfe14c","priv":"ffccb427730c5e0b70f535e6ed079888f64b56b8ff51a7f5be1f1312ab63567a","pub":"03e4300d0181f901e200b71f607729f6db5b422c1dccc6facd28f7c694975d2bcd","addr":"66cff13f2cef89b9313377ef24b4a1fbe2851a64"},{"mnemonic":"modify monster ridge bullet lazy sweet output acid shove hire warrior broken","master":"014daa371dd0446424b0b8cbeacbf8209c5136f184cb97346e82ed155b535b58","seed":"a5c1919d9fab0049de70600a275930979ad0da3a3da6333feccbb1aa41ce461ff1bfc5fe0fa6db126fcd96887dfdc2f531a522fbb90741aea5cf2c7dbde8d585","priv":"b66d283958f01a72683b8c7637dbe3910575fa853c7cdfc395904dc73723fff3","pub":"0298afdd5257542bc7918449a8e22a85c5c6bee8311ebf6c712da73232252ac3bf","addr":"22a6f55327b02536e91a046e9a8347c38be6f111"},{"mnemonic":"economy relief sort silly pizza trick urge harbor coffee flash fantasy sorry","master":"f1ad3c0e0551b62d80ac54f85aa89c9f241f0601397b1b4e12206a67479443c5","seed":"d3abce93f99595d45d0e9eb84aa18cf836f0d7eef60345b8eb2a9d4c87a8eccb7a0304907adca904503d8211dd31ba96e076a4b2eaa91ae575d4d1f7c815e670","priv":"4aab4cc83a2acee81a99bf7fe4fea79cebf133b1a7f0fa3f583912efd60a8525","pub":"03b241333aa683b8319975cd9ab2b046cb7731459e79a0ee9facfafa85bf0a31ea","addr":"9ff29de09deaa15e5050b5156754f9168ddd6df8"},{"mnemonic":"wage thumb correct coffee salute rice trade middle monkey height hint plunge","master":"22c4ec2703eaaf2de49e585a5ac5b7e17340a07523aa46e35503176a3a53fe28","seed":"b93e4f76a12d3cf66af70b58b30a66d5d648918be7d5db33fc3d573d6ca546f39490d3101dd686185e61f4334f4880f1e52d94919b358806812057aeda57bef9","priv":"d5e46c667c3e8c08bec8c7f7dfb1dcff3a628cb39f1eb6b8e117ccfa96551354","pub":"03219d1b8b9d5562e550d0fdd5cb6227988622d664bdc48fcad2c07dc78b82f1a7","addr":"d8f9a7f71ad4a92a07ea0c53a54395895fac7134"},{"mnemonic":"miracle penalty base jeans inhale state roof size tent chair life afraid","master":"82e0e8ce42e1a391f362bd19a0959529139153e6102eb5c947a64ba6b8699c36","seed":"d43f307257db97baf0e458c06b0f509e5534aea2bf8e2972eeef0a5408b9fd52a13df5b73adeccad68ef61017d63243dedcd167185e10402e7a7c03c88087527","priv":"8a82fb302c3b5cf10e119ff3ab01a036e002e9e2d49f0db0a40d5b6828291bc4","pub":"0233cb5096a11a4c79e54cea37e42139a1198a1385cf4e0d37c704352aa3551a13","addr":"e019149a5036bbaadf18788e3be72fa5292a2bed"},{"mnemonic":"stumble army virtual virtual plunge until pudding universe suspect palace bacon dream","master":"32da9154b165c960e927f0b01be8435f2b6ace7dcecda4416a449a50aaa56774","seed":"72bd5c92a8ab4478fa1dad0761118bd3d9a1ce6322c00f81b527701a74e0c4aeea63238017e64d4acaa92bc61af2c41a734d90567799ddfd15deecefba60988b","priv":"63c7d3a6da6149655588c4fab367f187f940101e99618de1d01963aac0dc639b","pub":"03df276b793ee770816ffd90ce2c45b6f24558bb90cedeb19f17264beb53344b29","addr":"03c20b0d41439a374a8a84ed7f139382b6b012f7"},{"mnemonic":"label script force inside outer pulse style nut meadow design receive panel","master":"bb084bcc5df57ad10abb3342888508e399cf723415d35f5440d0eaf808a56d1e","seed":"07029905fd6a538b5ba773384b0084bd11b5ede855a98189b8ca1b3b0457add4b365f98bdc75874ccaf85882c5f1aa59f0f9b77b5a823178cacbb4ff72d0969c","priv":"91eaffd2ddcb6d055c1ab3c7c87e313ba520c263312a6f3d267d41018d7cdec0","pub":"035bbb055ca818cf974da73d5d87d7cc447ff5b9dcbdd39552fb28c925c2077636","addr":"baa25da619099b41aebbbf1282dc6af9dc268664"},{"mnemonic":"nest decorate update alcohol system panel cool grape mind ivory ski dance","master":"64666caf25c290b5f46e27737e61124c34cd428b0d1a09e88ec47cd059765729","seed":"8db4806ada7b82f0811b24aca3b0e11d087cfc27e3e83b77e29c7d5695a126f577304e443f71b3de9239ca743acd05563c1f08f071eca5de4a9961fec463c372","priv":"eadb5c2704fe1eec4f121714b3a6d655d9eb985fae7d535c6543df13214bbfaa","pub":"022bcbc7676ad7693e97a587886293b6190edea96a339e225adaf3f3d6c493851f","addr":"5310b04cdfc366f6268deaaec22d7c628dc4b1f2"},{"mnemonic":"section supreme grit scan arrow flower rebel trend film sting govern museum","master":"29616b872561d14ef56f4761a29da1c5dc768092cf7eeb4ac28aad39e35ab274","seed":"4b8d6961db3f7b123dd71ba5fdc1b7809a19d84dcf25bd1b443b610cdbe44e5d5391aaaa4374ae9d6ca988b5898dadaf5fb79fcc09859851538842cec7acd36e","priv":"da2a60ed2f49ed3b6c1ff78698e3eedb2d9cbe9a707dd91e047f8a17db4f8e92","pub":"0304262df894cfd35a5330eed4008630b6527971f58075282290a070906c0d69a8","addr":"656996e8dc55902fc01bd95e93edb12e1e7dc440"},{"mnemonic":"vacant peanut senior skill helmet absorb turtle regular inmate hidden captain street","master":"7c329d40208ae70f5ecfe8b3a5930adfd09a2f618098e549c972036bea9fa4e1","seed":"b7fb706e9e43c671d401c374984ba22ab5465e15d8572eef3c3302a3fdc77ec8b5cbe7b2a8e42fca582a74fbefe6b755e442e6389592a0845aadf56975a4b212","priv":"29ea2c32ecc076c6e25dd9cc06b9736d730a8306a007df2410143153ec0d7402","pub":"020ee0b300f1714f378676bb533ed50b8336bd288180f4b55a338bb1ada82e0054","addr":"dfba016ba98cae2160c861d8e5117b5afb76a50b"},{"mnemonic":"setup asset fan host pride decide museum fashion disorder coconut school cause","master":"53bdc111a1d4208f6d04234dcdb764ca24c2f42d7dd1de46cb69dd00594f9c67","seed":"0039f1f4e2000001b1af4c47f72dc1f8347a6b7c0559a9625881eb6f7492c2e1fd186b778fe30540ec9dae03de4b8e4ad414ff5692490a547e1127ab03dfadc8","priv":"899611b8bfbc35a6bbf5cb80c193463849fa665aaad680d576f910bec97dc8f4","pub":"031a099725389ba4d2fbe5509cdeb5893a14a7d743a6f87be7af37701e99be18d1","addr":"5d12852d8132e60b6ed5707c4a589107c7c40c72"},{"mnemonic":"debris bus thought unhappy coconut sing sign piano exact favorite zoo title","master":"c2d02edb9583033a0db1b44443769d5c7b9d545aca03ce9d1db0c90c97e648b7","seed":"411ae07dd870bb2c367b72b5d131853088b501476fe0e09896004271dec37068722bd8952aede6c4ea32371361842f9507c5854f7e95b6e1685d8315c4a635fb","priv":"91047f9554ccc47f0c641022c8779e064ccbdf969827d374dc3419fd462c9ca6","pub":"02a6a4280980aa2a570d54d10c295a94acc7d22040a2299c79b9e72808274dd0e1","addr":"f1c8da3f0438f82da710f6e2604b5adc033cc0d0"},{"mnemonic":"stove romance diet season ramp mango swear behave rotate steak alter parent","master":"039f8ff7fd7e498c643ebecc5cd54018fbe4aceb34a92877746471c3d9446517","seed":"2df95585063422c193cafab822373fbcebb38780acb2349ba1e3d5b98f3a5c63f1631fad81649fd22a5acb3673c3c1cc4c93c6fac5e28bf9ce2c2d25a8215543","priv":"251fc43c061854edae6e1bfd0748770965d44ba5c0ba1cd9784aaa07a17ebed1","pub":"035b5a07e862224a2324a8bf3af20fd4dba7157baefaae03124b51274c4b50b48f","addr":"14f3a5e955fe78fdd87fa3b0eb3ef3195b7bad3b"},{"mnemonic":"cruel equip glow protect trade clever charge gadget valid inspire canal unable","master":"e47ebf7c8d4b5f5b80555c25c8fc89bdcfe7eec0d39b2c18adabfc81c90b676d","seed":"5eb48012a0412a9911b697a3b838605813f73a885a967be55432e73870d703f8db4649a59483b1ba26b739fc39af73e4f3f12d78648e78215c98c08428e5cf15","priv":"fa28e24225703620c1dafbcc09015b04b3839f8dbf170e454a8f6216c01f7800","pub":"027b56b3e5859e3df96d60366bd54a5024ec84efbba102ab1b4c85383f34b61d48","addr":"23890ab09f410c91db179e68ea1d942d25bc0c34"},{"mnemonic":"nest wool midnight tragic exit enemy knock oil tenant survey opera sense","master":"7074c03dfebcb8ed77af28e9b01b77d803c6f2ac88b61a17ae902797c82cbab7","seed":"c4740919291e1af1c7986906a374b081f0386c40601e4f832cdd3f5c4a453a0dfafa1aaa02b00d98f49803a16baa8cb64bcb186c4cf045eb803d8ffab66fd54b","priv":"1f0dbcbe498866989dc0e0b55e6f4b83b93ed2191df2db3ccaddb3f789e434f9","pub":"0396454c50b1a4ce149ed251ebfc6ab07f0d4c42ae84a80c90ca1b64112bb3ca57","addr":"8198e949ce71c8a950f39a8a691f2ec180106997"},{"mnemonic":"brush sustain penalty chalk palace slab learn decide agent private pigeon then","master":"3acf99c19afbfe290a99911c085a656eec61af6f976623c9b6d2d1500e7033dd","seed":"38ed979eea68a00495e0e4c045cfdd1cbe5aabefe628538c35a6debec1be144d41745cecb2003dd870dd87c4246b64e6fa4662173078ad7a4fe471bbc14ab9e9","priv":"1424627b12902bbb162cef56ce5609ac356e68e3ada9005bd92541d0d8766559","pub":"036155ad03bacc613c9fbfb87294091a9bdb7845e58231f4d585603153871a8c3a","addr":"1792e857fca4355189ade1f45066dad9c986e7d6"},{"mnemonic":"autumn sudden learn laundry erode claim exchange jelly jaguar vault deal humble","master":"1a616c74e30a912dad799fe8d65d6ffa77245f89e81a367310fc02d08be13522","seed":"976e55f1fbcebbd1e448edbe90d68d407d80bd5ae197082bcd7ae8e7a640f3246e0057c65271e9e403297b3725a895f15c502284ab342ce1416f40c892bd73aa","priv":"701e7206d44ca9269e1bca00dca53d7287d55fc39214ed4c7e8f7201a68d6792","pub":"031a31e47cc6d75f0652de6698757b8fb2ed1ac181697158f0bd50ec6e7abdcf65","addr":"a73ac9e548e47d6f1f3ec200593a6693297a9143"},{"mnemonic":"priority dinner offer glimpse sudden light work absurd unknown process gas tooth","master":"d969ece198e95be043e46dd8ecb45cd2e5bcc09d8e6b00bfd7aeb59eabcb0ce2","seed":"aa9cc6daf79e31c5e3ed594dd896b1ca39161add5e5a7dba0159f4a8fe262c51d742e66a19f28cf01f32a90fafe5195b0b359e87f5a5a60e31d883ebca08d433","priv":"81d13a5954925641ace6c24f38c68954d782b094002a689500f015a401d5c6cd","pub":"029b1e4dfd01689451ea069e8a193de0b506d87faae6eabd9edf5dc49633c0a03e","addr":"bb2704f3f0270cab3a5fc918b58561bc1505f718"},{"mnemonic":"glide sadness text grunt burst balance ask hair include refuse mom advice","master":"5a105765bef30fb458b9cdc3d6758479f003f96bdfc1d0c21ea1e4987f768ccf","seed":"0131a60482c920093bf7b7375a70bea607a2015bd0bc9deb04e99d214a0c3a4966b21c3bac01544f816a8f4c3583920758e70f8991506cea52c9450c1972a9b7","priv":"41505f80b9b0941d93341815a72fb32dea916912e3dc1b7b7c763fdfb5c541f8","pub":"039df863578cf71fd48dccaed45c21d1cf176c924bd5ed8ec5fd8dc1bd6fcd1a46","addr":"396984e26d5b3a4cc3cf4a5a868ac88776541564"},{"mnemonic":"jealous subject gap april eagle goose double door dynamic robust impose ordinary","master":"ceef22480f535024fa3fc2a7cea96559f4fe8133e45301807d3213ff7e49e0d4","seed":"52d4a03cd2da0a541450a4530565a5901953d1f3ea0ee9440748c1796a5b8ec8ff674a8cf3ee2fda215a720f0fed119ccaa97619f6fe76b736b6ff804c2dc299","priv":"308bee98e778b1037cfd69c0691b6cce81b1935c776a8473a1b3a49bef313305","pub":"02ff9d7bab97fa367a753ded100c11ca4bee7173c04ddb242fd928502a58149587","addr":"7bc8cb221d4de586491bee3016d9129a42fe0527"},{"mnemonic":"panther camp coconut patch blanket census able melody bid sketch protect illness","master":"aa867cfcb578d828df3a6cc4ed1496f3af72f94635ea82574bedf2d88f9fb0ae","seed":"1bf0752a4872e6a4bdbf9f15dcda591184c8e1c61910d958642b376086cb9db6902d7ec0997afa3a0872ae3fa4fa7751605a4b3a3ccb3e4fb5a6afe26e2aafad","priv":"ce6de5f65b6a0cc1e9c4f7751230aec5f2b5401686e7e42b81f1d8eb55f77303","pub":"03f6c0da8154df0baeb15a7bccdd79252c38901ce2dc59e6e08d2d292bf6668a71","addr":"38a888c98b1f68797a879b64e5907b909f81c386"},{"mnemonic":"great history exit include clean have vague stick victory else iron trim","master":"6fce540ed685440130d194a3e8af78417f9b73df783721ccf184807b3973e384","seed":"2459cdc80eda19acec0c704f020082b617952f652b109c268035607139ba2710dcb8dfaf546257f09f5a1b19dce62e83f603f561d2cc2fefacdac6fc902d311d","priv":"26d08c2b95d15b5e1313aa62cc275b10544f0aad3c2ca677426551d5a039a551","pub":"02d165d97ddc4cb451d52895521d7c0cc217d1a004b9a760aa3eee40edcba4ca37","addr":"7bccaf7fc14e648667e8d7001f7b0777bef7813a"},{"mnemonic":"pause you skirt bundle opinion soap wall doctor head method tent lava","master":"b97cd03b20895737ec084f536ba06f459831e6bf2eab51fc4097ca943014f29f","seed":"b661487c12002df5c65a204ef12698be70837ec522fa1bf17d789d0d0cd0be443a819e4c6a494ad8d66a8ebe25ddd833d6ef7d9dd80e3e5e276ab94e0d572e5e","priv":"6860cbc7b6017128bff9c6d48abb20200aea06a7e8c9168d46f51260dd7125a9","pub":"03d7666fd2ac98121523262fa6695c719d3ea6fbf8abac8266b7c8550a498a55fc","addr":"6a2c9c329b85c35721b69d2885cb8ffa3006ef1c"},{"mnemonic":"senior liquid release beauty echo castle honey limb junk carry clarify high","master":"b3dd9a9379270f2bee11afa64bd9e49e4d9f44fd997c383d651fce6b54e8a82f","seed":"4caef4408f37ba86781693fb979534b9c9534972c7b866f74318930f180a2a36875960ceab41e8725ee4e25f56d160455f7d372a7d08282ddb5d7c1d24f14daf","priv":"6d9ad9c1011761fedce7f7947b5325622ffb1cd6283eeb22cf5cfa3cbf214e69","pub":"03f173aac293bdfd7a98b5055feef56e70d07d3e0549bf278bcc7fef559c0a413a","addr":"93ef2c58e7de60d861c0dc994add27a914477d20"},{"mnemonic":"scrub pupil rural fat taxi area example spring doctor ripple obscure asthma","master":"bf805260160dc14eb96077258ac64d1f67979f7702c99c411fa075a3813ad57d","seed":"ece2913f94e791b8c5c37dff29cd19f9725bbb0a1d84e7c3958eca1b646858de1b3188c8dfade823903a4b4fd12b892bf55e570ed68286741dd02aa4ccb08820","priv":"d158bf7adfec3d4d7f941fd9ffccc1c089075fea66fca2039dc4e2b2a7d1a000","pub":"02d5c76872253c3890a8e1276ec4df0c874fcd46d1f7b84462893776b6d14fe972","addr":"a98c98b13f7cfe6fea7de31de3fbd325648a9357"},{"mnemonic":"first shallow crawl asset vocal special rural bomb random pair shock live","master":"a0f6894a4375e267aae6dc2d23843375250b44bdccbc63d1436a2f172214f928","seed":"7518a5b622fa57389790c2484ad833c95e5cf2caa12f71ffb0fad4c9fe044854ff1f7e97b188545679ea936816217d2a26204a0bde6eb7335328dd0c86814bcb","priv":"027d54b7a844be318ea4442113e4cecd464455e239c0726236e2cbbd4c559fe3","pub":"03f5c6a2e2a82d331268c789527b5ae6d3f36e3fdcb344fdfd7e200d5243b075a3","addr":"bd4e60a76b171fde2684d4c7690e8feb7ad06854"},{"mnemonic":"famous vital monitor opera strike coffee shield throw emotion enlist east smart","master":"f1a0708b891c80724310e95b29183394390ec56c3a6828bb4ec394a39726c256","seed":"61f06f35b43abe9256e635720f4e74c8e3796ed4222c8d914c3ceb0f26e48d9ff772040475acfefda1a907f24c369190b48f50feb2fbebd3a84c0c9d3850ff14","priv":"8c2d6f4673846749f8d2e2f9902f28f66d33625d0ba04a11477335390f908552","pub":"03f8139b274b297d1d669fa505ab797a7caea82e76c5d7a3341c71133fe3dae164","addr":"bc940ec509f5275207ae9b086be155154aefa3ad"},{"mnemonic":"flat cushion trend region glove humor below edit ticket west multiply black","master":"2e72ddd445cd917369177b7060dfc92883b4b56e301dd6b0c7049517c102ac22","seed":"85ca476c295a5b708beeb6af45aad1eb6bb691fab82fae7c6d4dca48723f7819551d04395581ff769554ddb94e0d065f4c710afa7674f0c3480c1c2c4299591b","priv":"a57387ddae40887dbb0f99e8c84c092ac1fb8e245ddf3c9909e189ca2b70d52d","pub":"02d19eb0bd72884a3d753121d0d4489215a369aaab5ad3bbecf47f2246c5ebe928","addr":"84141ec76f71f2bb4dcfc9f81fb5333b9cd1ea8e"},{"mnemonic":"domain produce address tunnel burst emerge divorce health frog rare cook series","master":"983fc11c91dcbfcb3c1869da88972b03f7cc51f54db49533c012238ba89ea234","seed":"9d7cf4d9d3c664b8e51db516449d3dac01d290d774cafa90326e0464290faaa6ed6b780f792e80955ee5e6d7aa8ce0efdec13c20ea0fd88e5e40367f6df818a5","priv":"b96264f6b7f9d01e386ae43893c2a6b8683162394bbfc8048dedd4ce129e52cf","pub":"02ac9b86bcb1d8c6991572ce5044b58560ddfcc25a26dc4c74b12271c263e9f1e0","addr":"345821fe95bca3c777328a7148106d46afad6861"},{"mnemonic":"dutch oyster switch layer rapid fat prefer bamboo stereo staff spin midnight","master":"47d4c05e953b7636bdaa099a136986544444911d1fa720575872370f2aaec934","seed":"f120c319991b7564a6bf0086d918b39aef44877b361883f58db6f95551a66bfffd1f9708140c07135d40d624ab78bae8969883a2239b4cb6de5270aa5eef59d9","priv":"968356e312506427072e2e628a136e6e0104e3b9f74d8a00f384da0d62e58a30","pub":"03efbe8d47bd3c1c6ed07bbb357e6ade29f46d70d204f4af19e5ccba2dbec7c811","addr":"27bbceb99a49bc927eb0d6434b41c873ecdbe782"},{"mnemonic":"green claw tiny bring meadow tone improve advance federal talent drop fruit","master":"f0d9b5313bed52a853a177c338cdfa1080fca511d1a3157e3aafac06a6a753e7","seed":"8acbd6c36b27634ea9017b1ff25913a3b6aee3ba578272ea70d753dd1390ee31e9b0a7685c76aae5bd0e3cefb34fe6d077a7aa0a1da2fe3a2b4d8592907f7c9b","priv":"633d8cb5c8aac8d9e8f3e540ffae0f9a2fe54ec4b9f95c4378927be49f785bb5","pub":"03479063239cddb13d026158bb3519ecb95590d0be4abe036668f3bd134ce8b0b4","addr":"5a6321ea26d9fe346e9af87801f30f823cae4e5f"},{"mnemonic":"model famous make lawn wrist busy food envelope town menu hint dove","master":"034f244b9742152cc762f84ab5fcd03ea6020e30d766d209240f4a1a4bbf4859","seed":"79c41d550c0fa03c15114feb0492e362030a17a72d2e3d05064d459ff8a5ae877c2d94243615ea0f41bb82030e0401ea6a51eebef49c520cdf9bd923f9427e12","priv":"3dc937a202f6c5f20a3d57c657f16269b84f52a4701da93bb1786ea0711335b5","pub":"03e26c7ba82177671230c877902563ed09283148d9f83f400006e11c735620d94b","addr":"b4faab756175074173121e758b65bf2663b792c4"},{"mnemonic":"leisure buddy divert feature soda reward moon doctor fence neutral bomb truly","master":"9e8c30422c780174c05f3a5c333e116be6d54acdcfa666db96e0bc3587fa457a","seed":"728465a73b67017cff82a9e1d5b3cc77276f286e491e9621c21317485b78766fe8828fd0f03016ec67a9e9a42c355804c875874206b60d474c09e49e1eaec89c","priv":"90c91a0f640add78f765fa475ba8267e5e3533b0175d29150138b659397b0a47","pub":"02c0b78775eaf3515a49cf8ee65dd95e8fea30340601229dcdf2d2dcb3d39b3839","addr":"0c300d4bc57ff741c4c634a063c24823a18b1ac9"},{"mnemonic":"excite cargo radar baby paddle century average nature tackle blue rhythm garbage","master":"6a4cd79ab70b5555d3815424bbb8c232351a14511aaa3708dc4449ea80fa7330","seed":"7356daf4bbcbf682469878ee2a8e7a35d659d8f19095059e7b59fe14d9893c054559bc2beba994c527e8417f86c3f57a69b3f42954aa9a4647c91155fcbe2488","priv":"ae2aca6963de88ac0a4e709c4f84f5ebbc2d1a18f55be9c036e97fd46200ef48","pub":"0304f4343dc04ad6ea1c528296ac17c9d47a42cfb744e311f206bb154abab6ff59","addr":"ed8d1537a6fcf980fd7297ba56f1638935ae0fc9"},{"mnemonic":"must trophy era antique goddess local green rhythm gift van target island","master":"52e55a55dbb99a2b170c489c99d50811c47be205294704a2d6e7f234b2a938c6","seed":"9797425288539f83d965bea50c769e5a681c7fd6860502bc7d7d953a36fe16d8f0af0e6441a92b421cca44ff0fdc17d6118801dd17814308af5f6f1436a2e28c","priv":"8eacce7419f6f8b94e426adcae21818ce6525f0ba624bafdae44f0838d36676b","pub":"0244ae10f79e38d499c76996fd6ace738b1fc3dfa60042775f200315cb1e827855","addr":"15b8bec456e7346a6446c9679afb13a7e4e82079"},{"mnemonic":"day include route train grow number traffic across acoustic render save gadget","master":"553843ecb6e4e0383bea60a245b7f34c46d8d505806f4d900c7344b2dd4e1787","seed":"abdb30b82471a0c81df74e7d8f9fc2315b7ed04580689d5ad91f8947cffa9375ef2b6c315b695e642f43d08edcda3712afcd48e86583b00bdf5085d2920ddfcb","priv":"ea826d758734cf1965b67fe0133a2b78aecf582aef9efa46c96c61cb512ba593","pub":"0304501989badca08ee05c3984c8e299e5ecfc91feea52daf24cca7f236684ca81","addr":"9bd24b970d41b73640a86beb27f3533d2bf35c82"},{"mnemonic":"safe favorite ticket bus picture tomato unaware lucky spy creek upgrade duty","master":"8be9a1fc81f80c427683964bc29c2eeb135a3ddda8bad041399e63053cc37fac","seed":"3b7f10be92522ba2544356227f415046ba8b2faae9c3dbef1563aee039d00afe8b476743cce4495c264ed01fc095fdd09e3c2159b9b91ae01f49e5610f3dc375","priv":"114c0269408ee0ad873b847793743f06dee7be10da15d0db533fa682a644a017","pub":"03876eec35fcf39732629c5b3ea22c2309a28549335b9f221001ceb0097ee8565d","addr":"fc82a1a044603663dc758d6987b8b699d56af1fc"},{"mnemonic":"slam jar adult liberty small adjust right sheriff cover below space fiction","master":"75e789f7c7da1a83a34d2a2a9b54d4af6403292156cc775be81ade0edec4d566","seed":"ce1684c7045cbd4ee4c6c23d52ad78dca82e426256dcdb3a5f5fd9c635e0dafff12612e981dbe983e1ec5d88d6bc3294b84f8705cfb553923e397da5044b896a","priv":"bae08dd84c10433159fb11a08f8e3df9fdc503e5cd543a4e9231e96468094a4a","pub":"02269218f35c468c3fead430880577410b580b9dd979d68c94f6531adba7dab809","addr":"5e44c323c10036262a3b02974a6d69f953d0e359"},{"mnemonic":"real acid movie gadget duty hole apple inner essence confirm laptop duty","master":"132081c3acbf9bcedb0a237fbd41c882232976e1bf5467c067892a80f5d30691","seed":"495b41f5b0f22b227458857db55d2787c126b832dfae01384ad0213eb28d79baaadd13a365e63cc7c250504c5f9a2fc5bf38e174769c33ddb629a012219a38e2","priv":"44b3ef5a4c7005846196bd9b7987308ba1bb7923687749509cfb733b3aebc95a","pub":"022803c31147ee31f5fbcfbdb2313c5ef39b80b505cc21275cc01e0527dc6ed6de","addr":"063cf369f1f4122821f7ba400ba1e8248535fd44"},{"mnemonic":"banner indicate tell thing elbow mechanic express stairs robust rival shadow matrix","master":"6e76cc6fe8099d9232c107ffb8959c3c6a24badc35579975ffdc29316ecb2b5e","seed":"f1224c30cb0141c0da3f5cb31632ef8cbd88896e5ce98a5290ab708f5c0c084043fb19a4e360c17e161a3e6122e8fb9d3991c9ed7129dd5ee26bbb2388e9b7f0","priv":"215dad8e633e3ebbacdca2ba68a9747ec69de4d5bf794748500768272445d516","pub":"0259f48c2e291b1d0b29890c10ca516ae8e186d06bec8dd2d966d0b336b9a68a8c","addr":"7863b183b3f98f4ed5ca402c3f1bce45a9d58aee"},{"mnemonic":"boat minute dutch sadness globe congress color sort feature boost regret gallery","master":"6be1882f4d3812eb5cc92b5ec4ae762b565596a01b1c4216f16337663d33f85f","seed":"dbcdc6e305e0330f5fcaf159763664a8decb12dc27003831213b93c241d886ce26175c726b6f899e8de4f2b15aea6af2be816eda613f00a3f8bb3ef3c162027f","priv":"e30847af4ca7d0bf9f76d2c15906c955de0d89ce994abf7696ebbe0880171675","pub":"02a6f99d68bb927000aa3cb6847e349fc7f0412a75869cecbbcbf223707b7fe8c7","addr":"eaa5c8da5482c10d473be2c62206eb82312f3ac6"},{"mnemonic":"icon echo become average ramp undo actress sea water struggle interest trash","master":"d07e7e040dc9b1ce70fa78ff50d10345880fcabac783c380ed43885532d79ab5","seed":"9498c9409da005532ea8fa71aa658c9b160c6630498514e52aec48589ab60207f2770e4cf0f47a04a2d46a878b3b2a2f0f58c478d708ec9dc8f54b51ed1f0506","priv":"33a881e07441283721c695c58caadeb68e5576a526ae465ef48812b98d66bd9a","pub":"03226330049e98e5513799ded19923809dbed40226e958f9c36218e8eeb5cf47dd","addr":"b02c8d95cbc1417b891ba5d5c912a6e3b8cb6748"},{"mnemonic":"scan book mean egg situate dash chair water surge major sugar shield","master":"a50dba88cae4daa6db49e8cdbe710a305429ed2e4ff43c0b87cb0b88956f8f02","seed":"ca8bf187bbde692601b88a74c124c967cdd17810a5b4db55254a22278add4880b8360a66b5d91c0ce1c105f78873994361d2169a3d39bac0807a6ab7cb6b894b","priv":"4ecb295b77c3b1296fc214e554e77fb47df10cbfb22b980ba6e9436a2d884ab5","pub":"02c302c47bb2ead02062861ddb4c876b797607ed2a775317c7ad258c97139767bd","addr":"6f6f55426f790072f9752fd182a68710c2b3e72f"},{"mnemonic":"hint sign broom plate brown beauty figure song stumble setup polar road","master":"e4721371d82355bc7be6836a7915a19917d2efb313eab36abca855fc00f4cc7a","seed":"7f654f0582ce0c83d46e01477fafaecdaa7321d095ba1468ecd9fd6c04c67471a2e32187c02178522d11d9b9160de10c6cfd74eef79d6c50d013044a5e6562ed","priv":"612986c34ddfc5e93d93337f68645bcfaa2bdd37c8a6beeb7d58cab6e54ce3b7","pub":"0309c0b133a0af4f468285b0399a3c3cdaaf8c2b29ef61a4f8ef19d526b23eae6e","addr":"dbd39ec36261d32e313a82b4745c47489de5e955"},{"mnemonic":"eager item digital loop loud drill script ethics crystal tornado pride cattle","master":"1ed90fe65b73b2b50464a59268cc2a7a9bac67f2fb167c5b4714dfcb354a24ba","seed":"2e5bce8308d9ee56a168da570cfbe30f0dfa341df84cbd7674f198b4e419d48c65e1ec2b8600a2e7608bd148291c54ba29e5e7ed0a39d4418eb212ac6d7811bd","priv":"ab27d9960f7821dce58d2271652b42f8ddab5edbc87a23ce3177a0454b775167","pub":"02e1ed58d8c50877a6133c16e793fb6608515accbeb46ba07cbd3972c274534066","addr":"54b513aaef1aba872f8f521bd3b86c885563cde9"},{"mnemonic":"asset toilet hazard chief boy over trap session abandon jump wheat group","master":"43ca7686bc87728e62a5406222efe3ff40d4364a7904f7307437d1b2b13ced43","seed":"e04b7a46a47cf1c4a9382aacf36a32da16724eb1ba82f65a3c66679d793d410d3952fd7bb0c735bf96a089521acf7ec4e1f41b179b09dd75645b7bdeeb539292","priv":"e7295badc4984f21bc64f9ba723a92799ebb18acd8315686b5040feb603f03e4","pub":"02cda17b0a54b09d9389a06259a44004a569a7d862a9397d33f9fb598fe374bccd","addr":"f69a0e9ead6daf22623a1235062510360f0dc7fe"},{"mnemonic":"flat eagle owner ladder enlist chair next good solar drum service escape","master":"2de24f772282ea286aa716777f39a9233b38a5a8018dcd730b74bca33c5bcbdf","seed":"d571b7aca82b969fff273b5d4e876188c5b1124684d3ab8056f69bd521b1d030b617d201313ee42068f48dac836443ed6e8725ae2369a955133cf74682e6090a","priv":"232c2f9a62655637fc64e4173855506ddb4d3530807f4dd441a137981d636c11","pub":"025996bfa0d3593c05503476f4c340ff2bc32290affa52a130f2038b72deba930a","addr":"ea8a8d16976a6d922be30695d49a670027cc065b"},{"mnemonic":"hamster such legal analyst despair robot tumble embody coin taxi liquid cart","master":"f78ba19a1149f8dd5ff019f40fe5efaf8e0c5f9df5ef2a1b32df2b9a0cdaed8e","seed":"9d863569bb0a87d17b02c10eef8aa06edbd9ed37ecff427001f2e43cd4f101def938da306ecac02bc5ee83b886857e43f6248eca72e65e67828f243c625de0bc","priv":"5a2a5c105c9393cbec8cbdd79022c23407c556a503ede10645d744f20ec9ebce","pub":"03a14ba5b2261911010d2b2a7602b37dee944891b1e49d075b6729e62627a252b8","addr":"73ff0ff918c11d261453041ee18b38194d3aa57d"},{"mnemonic":"gun monitor turkey humble private essence limit member bike person cook ahead","master":"c3d138412cb4861effe93888a20e5072f887b2b3d3feac310fc8f40bb523f98b","seed":"6c79ddee8365c1c293e6424cd0c4ad5fa00256e9f8377e5692c3c60c1550cd4e00d3f08aa61441609b3954c271404888677aa4f7e075d7e93ada2f452984133a","priv":"865fdc61a6559f4ef787eb57210c09bcfd82ba9aa87a13a09e62746470eff4b1","pub":"03777c19e60200e1fd48d07f17c58c29bf6440aecefe503421bb13cd347bcd3e6c","addr":"a77712c1f028f11782d2805950c79e11d2229002"},{"mnemonic":"bargain doll comic scan fancy soap fragile benefit private sword share milk","master":"b26f239a994fc404b1aeb31ffd7f0bbcb625c881585dc57247cea88ed890b042","seed":"928a043d2007258b4cea3a478dd6b1cb133ca290142366af0ac60086f880cdec35541f080c8cc1d8d76cae811b5138d9de189557b37dc6726ac1df11ccc9ef92","priv":"ad650db8c2457981a143a3cf400ef1eadb5790368965a5fb8f28e8e0dae1991c","pub":"027ce8003309913c6f99fc6a5eb2020400118e3e253f618a418816e772b5008a75","addr":"67996609609bda5dfb179da0fe5e6c7614ffa922"},{"mnemonic":"father accident gaze obvious visa deal plug narrow shrimp motor pigeon sheriff","master":"643240ce9abd6d36e330c0cf47343823c3a3d4b533f6887aaac16d737c8a1a4a","seed":"9ebd83a564ca724a559e57e896940ac08d28a71613e9b414170539b29a5187a2ee91e3fd4bf258256e26ec5c41af2a57fd8dfd30f054403599cf9b4f45af5839","priv":"adc7eba12216571143e05626980ef0644521269bbe8870545b7cab11838537a8","pub":"023b065c65ef208f46ff43bd1051b494f60b1a395543952e14a3d53a6d1f347e96","addr":"7a7b0429f9706215b02ec49c205ec4710705a68f"},{"mnemonic":"reflect slab donkey village mushroom style brown pen mother pipe raccoon mass","master":"bfc2912b21b64143fa0c5a924573da251a9ca151aafc79a9038b96e21551dee4","seed":"fc21dffbf43c67a07c5333e57d238f07d0e1b987bf4f0ec763f1abce471a2e0fb27e733d5098fbeb81ed9cb2d4093ebc9c565b196c9900f39faf4da5448a2b15","priv":"d34fe09f482ae273ca07b2623d5b13180db5d14693025b57aadd6c7c51e640ce","pub":"0329edd6f8ab6a57ade9179889b4f54306a45f89b0007cf9843755b3aaab725586","addr":"c69fbd3b6e36a75ac8583713c1e3207253ec53de"},{"mnemonic":"lunch process rice hazard word vault surprise useful fiber trouble pride mean","master":"12caee441e7ec1c4109c53e42c8cad66704ca395108237f68953b137072d1aeb","seed":"19033ccf459d27009a9072905bae12152c877115e145eb5469f20ac8d763570d2d0ef57cfa6a482da6a1f2c38e7dd43fb6260a4826b54c0f03f0501df94e4132","priv":"4a2616ff7d529e66e3fb200e7531b4a08911a338e6a80c80182a0b98803eb14f","pub":"03e996278cd3c0374adb59287c00a526fa8a409a53a2606fb230748cedbed12f14","addr":"0f96e89ff4109143a838165bfaa158dd64603fa8"},{"mnemonic":"boring unaware cram sun mistake rule view rubber gravity humble detect zone","master":"23b29bcf96e849e44c0e8848e86596eb41908018dccdb91b9fd81b35cfe24523","seed":"25d1e2d98bbe47da86d732e8975f5c2ecdf2e107b641c6e9a259a49014dc35dcbb83ded97117bde45b0e78379ab0b7785aa8e45e2a628442be1ccc9a98e78a5c","priv":"d2c91726674b440f3aa7f105c17848c1e63d123bdc6ddaf88ecf0e6db40b7d1e","pub":"0367113b62388057da87fe1c781210074e0200b872a7243e05a8c9f39ced994acd","addr":"264fa5eeac6f6b37e249f8ba03168cd17aa7e258"},{"mnemonic":"extra hobby pond foil below injury light brief struggle gun visual recall","master":"80cfd73c33f507495340ad9370aa922b436b84d3f584d7f65cf6173b367331c2","seed":"d965ec811bf471bbdeb7aeb4c0fc43d710cb47fa63806f29661bc1aef4873455c6a97f85e675f6da0e975ffabb1356d310daaad51da951de68927933937e85be","priv":"67654951ada1ef3a6e15b3941d0eebbd1bcecb831bb084dac0d70d610ecac13b","pub":"02a1ad9bcf4e359f15d3a447b61b9f18bf2dfd56c52c20f267ae13b04bd60b0d25","addr":"13fe548ac9d9ecfd28e5c5b5d0b865b89b36e8a3"},{"mnemonic":"copy thank warfare visa else rally shuffle gauge method favorite dirt mushroom","master":"f76da13cf3b11641e547c33aed72ab423b7dbfed236da81ff3759d4ba3ba3aa0","seed":"24e7ebdd3792e56171fc46aa5112514874b67fce474a0ea4399b6cab23ead2dd6bc5201826f9127bae7419504de04342357c90a34884015edf094e52a7080d0b","priv":"0bd271e0b2adf4aa3f1b0ea862eb4efe72958d40ef2153e784ede4ffed2d4b51","pub":"03b42c815258c481e1e994ce430135aca9e8546585e82927066067a7f3eacf0223","addr":"95ee4a4c887ab69a23000fa3bb062d1bdd96371d"},{"mnemonic":"rude wolf aim frozen bargain false remember circle axis arrive virus echo","master":"98d35496c8e4f142a6be9c704611257b0520a14b328203fcc0b6b9419a71e366","seed":"ca47d7e6f88717ebac85734beded4a18c6a46e6775cb64b7ea5aa167559f90bb5d8eb9254599df6e09999d8dddc1e487c657c95eab703f756199ddc3196a5962","priv":"9dbde9c5f35f2fdd7bb33208c733021a8ed055af962137c23e06e252cb999456","pub":"02ed94e8e6ff816a2b053b959b261e7d8f8809f58bae0cfb84459d885da88355f3","addr":"38a0dc2d9bdffd96930010699ba2f39fd244c3d7"},{"mnemonic":"deputy among shuffle online fence mouse clutch joy away bean hybrid void","master":"e13cc05ed1c7f3415610c4011f994446c9c9c65df5e1568af347d42b31e36d30","seed":"f3b73f8483fd0cf17bba1032397207d4b593f54140391a91df47c5b8960fe5918b0160a18a1a2da8f3acc6585fccc19911c613424c91b47afab4eef5f06bb569","priv":"d323538934f97f44d23c78be6a5f6005a882126475ba4a7c953b19bec7678142","pub":"02e6c50799013ab284a676715c3c575be75806a5676281144cafd4c17481ea053c","addr":"788f0092868345453e40b0f38d44f4ff4af0f2a8"},{"mnemonic":"panda rule subway ceiling awake decorate forum cluster place club surge lunch","master":"f0aa8e87884a3e3462bd3a230081a29739fc62fafca9aadd9353986d27de4509","seed":"7ad436a119093e3862065629b195087e0162f2060d6e2a1e653be2e894cc9c3c4ddc2bae40f447ef87c0f3b2232420fd938c155938b4ff5fedb3fc7bd26e9eb6","priv":"9db3eddb02be190b266cd3bc93f5e45d126577bfdfb1df60ea9f2f3bc21cd2ce","pub":"03c4e1511881edd8d598fa65bfb4f9dfd93dc1f2f4944c790c2abc650492ce0a20","addr":"c61ee0480e8379e854a631caec02572b91c2b23a"},{"mnemonic":"addict foster exclude debris moral uphold couple surge reopen blind trash real","master":"9c7714714335b5d3bc2057f206da041c5b0e74213413c2cb9c98f521d2890209","seed":"4905780290404b998ba3ea764cf22ff5ee689aa9d783a7f6ccf57c9d2b4b27e4312941a2e4328232b6e0d2e7729cf30978b094dfa6ea369b34b6da35ee2ef73a","priv":"4e5be9010cf1a4ec010712d82bb0d18d5b1b1cd3095a56cced0ce00f430e81e1","pub":"02a18e4eb8623e1f0fc37434d1e18531ebf5e2dc9bf93af3f831cc72389cb3ed83","addr":"7acf8d7f9f6fe56e21ad77cc6e41b3b49bb542dc"},{"mnemonic":"bracket dragon until token cotton giant enter lyrics apart supreme pupil fashion","master":"dc8282dcc0f6d147d01f8ac326a3017380d56e242fe415fd17c0b6ea92dfca0a","seed":"b1a0043eff67b480d9b3b2c0b6676dc17da38225428cec06ca7884060b830ae243d50b659cba06166b6e8eae8d9c9d67a38554f5feee3315e90859b544833dc6","priv":"7c19323897d7640d225bbcab428731abe01c7b6160557476fc0bf97799f6cbc7","pub":"03f1a65a290bf4a7ad8585680304d187f5aeb3e51d44c9941443450270c457edb7","addr":"72caa875e043f9f2d3712a87317cf12c34980ace"},{"mnemonic":"catch unfair toy shadow hobby tuition remain leaf put blanket fall diagram","master":"611504571157c7451ce639658fb04945cbcfde1b2e487f9cb97ad430ad3c3801","seed":"b1b9002dcfec6d7bf1d7068a45615abb4aa076ad65e34f15d3f4006ec82384c3bb7d737fe7680e58089281ce9305ffc178bd1a23e95087c2fed495a20316ddcc","priv":"3fabb4604bf9163d245a293a4b50a4f844277afb9b260100ecf406fdb24a6d9c","pub":"032568275e2158b5b88f191d77cfc23742157a4c03863da61ccba04a29d6a5fc43","addr":"061151483994a2a2f420b081148754d5807cfe96"},{"mnemonic":"divert spot love tragic vast error crucial print snow filter fantasy forward","master":"817b4fb465a25b5dd9921ff72634202f30b98ac3040cd5006ca5e18fa851f4f6","seed":"824e5275f61c11ca6db812ffadec349e61afa0313d4d299c911eaba5ddd38ccbfa39a42d323f43aa4999bf95b997958a6ed0522930bff6968dc9cca2adaaa204","priv":"43919dba40cfbbdc53b2f8c097b6c66a6a391c28d9478fcfe23f29daa4f80194","pub":"02c32a7eec00f33e70c83aa4281d312bfba257bbe920f349dd3b674decf43e3aab","addr":"fb3e6b782cd14938a296f8986daefcb9c1424232"},{"mnemonic":"marble start nest primary author steel video science wire sister tonight invite","master":"8d62341b89e0c045322c270870d8c438ab41ca077b96681b9288ce2b04160b8f","seed":"ff79b45850f134169e1d12bc2c95c5f48933815e3062296a93644c8e88ec70f2faac59c5e0e20b1fe8799989509190442356a67596657156dd7b1eaaeb976adc","priv":"75adc55e735bce443ba38fa066c269d20c986d18d31b9c67a6f41215dc6205e2","pub":"0262ad481271c2b42b162d09eb549bf2e09ff953d78cc3b58f9633f0a2f0a1cb32","addr":"289c5796cb64589fc90d10c269093d9525249ae4"},{"mnemonic":"mesh rose keen want voyage net brave bargain session creek shoulder glimpse","master":"d3230ab8890910c45a3bf9d9d21b8c24a6a1aca2b87467b42c75cdb9204e1f2f","seed":"d61ef67df124c9b43132bf496bb3b18220a28c7c540247a11e25c2dff3ab8b7d0dabbfcd8125f03496a8fc4f888d6b8f8df9828ca406a3864881029e95578c2b","priv":"92d844eea97086fb63381e19e56e3b494af47e7cad3257a5ef1b46e21c4cc4ed","pub":"03be77c3a96734aed00ac4a0a18151670a213a911f3a9d78cf6f4e1fc33b7d0aca","addr":"e3a1325741de4de93501261a3850b374423ec97f"},{"mnemonic":"host increase panel pact gorilla alter cause cook voice ugly crop that","master":"22daa7841a31b77e2d006277ba1afd48ad7f066b4cc2b778926b4d4b8931271a","seed":"c1b9b9f1d4097d76288576869071b7efedc756fbc81bc62965c462fb0ac49ede2fba8110e4afaee3d9e187933fc28783aecfc9ceeaf87f63e75f4bc1eefc1860","priv":"2aedb3ffca9d76ee5070f107bf5c0dcb583bef571b1f498baa8708495f8f466c","pub":"027c929945ff29b6a5df3d4ad096849a270ae3052aa1dc74b7a14d4288421e47fc","addr":"97944948d7d679a5c9658168f6b1ea9772c49ce5"},{"mnemonic":"shy garage devote private degree cradle special fee plastic lonely legal agree","master":"b2150fb985a296a6548cd57d30f25bdb2a51c7163e96207353ad064ed0eba53d","seed":"474ce9dae1748e7f1c4096dc603c17696ec21f329b508083ead0651fe00dbd404a1703a7a90f0bd2f66553af28224c6abb93563527a6413732ec636f234b472d","priv":"2c079aefe8f9d45940fa7ca547243a229ac8aead5570a310ff0ea50e9579416b","pub":"03368684efade7cbe5d1017c8cb099718ee9b7ef52e7ec384d507117d1716faf3a","addr":"e0a6539483dfd061a878096e5cd0efd475b9318e"},{"mnemonic":"marine local subway mixed width zone palm lake sort radar matrix pumpkin","master":"5b1142363291deddd7fda0bd7775c7f2b1bdab5959d17d87830d96c3d07c15f6","seed":"c49978eee2d39326d8950c89a69ce6cfd4d51dd84973bdadb5dc517bb60185bb4354b3c5fca5dd0d10a9d8793c205304d1569af0b739bb796cc3f604edfd8959","priv":"84f09a48e36698ca0fa65597368284089059688c2cca84c72a22510f37989c85","pub":"0262798b5fba21efde82c22dd36df8261745c8f7046704e239996c634302efe8ff","addr":"6d81cb6953042af66fc1fa7755f48f3c3b529495"},{"mnemonic":"morning vast nut patrol owner body between neither earth always trouble mechanic","master":"abe0226f5383b2e40ac23a3cb7b486521f7b7af6b1108f24941fcdeef71edd81","seed":"14189de5d7d30504ea20b94fcdfa6054f70ff63f4378cb3a6715126216b571075879cd9fa1c1694ee16c656d8f8a2020adeef01f56dc814cf341aca1ee9e8e33","priv":"8da48fadffb800299535e930330f1c2f9dfeb45772c58764451079696ab3275f","pub":"0283e5b3d662399b88cac949cd41d65e33dac46101c6be4ab6718d7b7d4c1c2df8","addr":"bece5507c72c79ddee993158241c20ffeb20596d"},{"mnemonic":"weasel emerge sight shell cook develop entry truth era radar panther prepare","master":"2233dae87c1e1a6a98e1df4a573f6139dcfe49db3f2fc663b44503ee267b0c95","seed":"787e8fd15da3e7723f91521e3fe4b501b070ff5bbfbcd2b4af147a6067d751d5d1d992716519ad71b59a41ce329eb282a94cbd15bdef52567c8279c327651bf2","priv":"ef6ec780a7823965a871595f4f0c2e2e7ab07409f39ed825b1efafea19f39440","pub":"03a545388da649a8800ff9fff4bb33f70d94000e4b1a767ceec92f5c3f7b880783","addr":"57222240ca41ace976ea1ac308bb027ea4c64d36"},{"mnemonic":"switch sea bomb symbol foster flag grain bicycle case crystal august crazy","master":"32694a657bac54bb8b77e7d0d84014e41adafde6023723aa5779645c7c798d65","seed":"2719e5e2d4ea727d045817bb8cff56c62360b3c1c66522ee74d1b3e5c8d6ebd98700887d532f9d1f17a64bf683622b44df8dca30ac1bae5e296422cbb7741790","priv":"47b1b2ec336e0257687c8837c9aefdca2f45394bace57de882d7eba6c61da49b","pub":"034ad373c9e20284f233959b09432c82b0e7b430eb625c9edd1d5371a7038baba4","addr":"0900f4003360d4641626e75f3fedd19874b11671"},{"mnemonic":"asthma make clump clap tongue away used shift fiction siege tooth purchase","master":"0f28a391e22257fcc97aa8c229209ad0734e9d0ec8ecd67a203582f2c0ce7289","seed":"006b61f87ea0d6f9f87b0410ebb5bb54c9b8af72d3dc6283152b6e66a299b8ae0650ae528dea7b6fe5c6cf1652bd1b2c67b7e1c9ba5ccdd4111589216bdd02d7","priv":"6ad416539a8a969ee72e48e1b20e9502b90078dce0b5a4245d7cf12d4857eb5d","pub":"0274de9f743f31744d6e7ecf30c74ef56201c71b2ab56d03eb849f2adec2e3dbfd","addr":"67e73523c5eab9e70230fb7a806793419d28df99"},{"mnemonic":"nephew kick predict rotate maximum giant fit love float kitten embark another","master":"dd3cc8f83542c0fab49c660198ab42f48681db60661015e15fe4da87840b371a","seed":"5795b7fa476bc8f7b07738d313716d991a7bc2fb303fcd7012dc54e411bf7111d9c9159c9b28d74d5614b1f3a738bcdd63666b6b14b896311df18609521695ef","priv":"d84c0f29a4b95296e349bdc8bc9283367f5f68155fe92192a74f8a08e3c6e38f","pub":"02bc5af041b0710cedf1cb8895da55349d68ef4677670e89ce5da29f43bb063027","addr":"ad020570cc250019ba70e84f13a0b0c388443c08"},{"mnemonic":"filter vendor slice outside win urge welcome behave valley merge gun talent","master":"e20ace834dc8b88a259a3c6f983a8065ec612205e25da42103e40e968d1bbf98","seed":"1cedd43d959db14714c7e6f2f2caac10f548115f54bf7fb10ff4f178bb410530d8ade24d2dd770f92ccb459ba2dcf433d064c9c24f0d59137a2f808421e189d6","priv":"ca111d268b05839d504787ab4173f2d53cc459ea69c4965bc267db40b3499f18","pub":"0316b77b50cc08af7251303e190a4a12a96ce586631188d5f2ead491825db0b27f","addr":"c691a61bf6a5626bfa6b11f79a36c89e5f7efdf9"},{"mnemonic":"salt vote cook live accident leave define home section loop fiction sport","master":"30f08d7392ec4b37ec8fe00847aaaecc975ad1c98d64625b6e83525fd363b89d","seed":"85abff82357508cc583ff2c4cdfda7867467cc6889fb46caba56624f8c14e6141231c6b26ddd373b9e3504d90ce8b01da123ee72ae5a4db46aebf4ac7b8dda44","priv":"297a3c7969c15e6a3b4325ec6b4c768128aeb99e81dd4aa3cdbbd488e124b73f","pub":"02191258d0ce26b1e6adb0b84d19317fba6818f06993a46df1829a61a682a93185","addr":"a1082e1177f32b0b369429050324ae1c06461e44"},{"mnemonic":"model today toward awful apple actress hard reject discover type must member","master":"58168653609c2e12f079d799a7a344292edb46cfb7cf69a85f8a608acc6e47b0","seed":"bf3a70e5a322c0fad6db542bd4ffee2ed3ff85073e6d3ae01ddb7cf30773250c294529d69dc31f86ef390f30907c6da925cac78d10091d9df0fc97a6e48d9860","priv":"0a7c2b48dd3ec606816404246a0e28c36790c3b2f398531ddb7f1b7aa7e7d624","pub":"03f12f02b0cd5d3146eb28fe6a57eafcb542ac30833b7153e1a9121c3817d0854a","addr":"06eaa20c1fb4487be17eed4bcc57d49f1eeba446"},{"mnemonic":"popular among unable purchase matter athlete fever acquire mom install glance where","master":"fedb71f6c870bf049aa1355f4858675ca0c9a6268be575844d2313365df45382","seed":"be3448251aef8d22e97fa58862ff534bbe7a854eb0f1d574ebb49c4197328783c9f7a1b51202e5a37bf5b2410e3b6e11322977898c75241ed4806d1972102457","priv":"3f27d257bf6a625ea3dd1cc4ca9787c29027c105bda25d3fb44df992baa4ea45","pub":"026abcb82486454ef9ef70f5991f76cb263684624b040f9c7b1265569e65087036","addr":"197ff1aedd06d9015acb4712a4a3ed76b420be68"},{"mnemonic":"kiwi rail hen destroy path mistake protect carpet occur jewel pizza lazy","master":"7690775869756887b1866a93233ce2188202d12a4f0e01501e381b8aa120fd2b","seed":"82e3b78430fbad5184c4c7bcb1873d922de0758894d770edcc7a487ad5c10dd381345aee23f7d996dc8fbd44ed171b3e6e9b6dc19ba5c093925991aff3b303be","priv":"b0af5290094803ecbd0076266db8a65837d363be36738f267df6a5c37ea87b26","pub":"03a4b20c1179246419b5b5cd861ed440f3856b616c4bd5a04e0f9d45de91e25daf","addr":"ba2734783c80b277d6196850cfdbb7f1d599fd3e"},{"mnemonic":"cannon hill absorb ozone play derive duty quick unknown divorce history march","master":"668302ce757bac9a084220ac55e22027595a5bbf777dd344351fcfe668e58ff8","seed":"9282bc012e007bb31f889b9b284ed8dd02bcfe5b14528ffa0e128fe0b3d2bc27d3ce5240d14d581b5a530f66ba3c7146d891595a215b8faca2a0093287155171","priv":"82f9994e259551b52e63de92d93f21222b01c9f371c8cb0e9af15a6ac93b3fa9","pub":"030c0ca2aa6353264f3683210199ee7ebc1c051dc657a47f8ed9e95d50ecca2840","addr":"285debf5e963ce3fbd66a5fbb0841cb8d0a67745"},{"mnemonic":"wild saddle spring meadow spray lobster enroll album coconut chat marble follow","master":"14f5a8838df5b6546b7179704bcd40d5a168393bf9a65d0d5b80658e750b9cc4","seed":"565ab133d78d7fe7e8763fd73fd89ce7a5eeabe6841e5cdebb9a86f867c63f1ac7f3e1ea44029409bd48befc187f762480c3555d62fe9ab653ec2f8523b55516","priv":"229e28ae8746b90e772aa80afbe866cc08b0f49e40d4b1a512be21ea728ee0a5","pub":"026f08a2daea40b6a076b79c26de11bb1a5f74b9d127e79e1310d5a40675d5da0c","addr":"b262603b81f2f0ea718ee4fbcc9c807cb0317e70"},{"mnemonic":"firm mystery spoon brown rely mutual isolate degree stay brick brown abstract","master":"ffae4ec244b67e40036dceb4241614869beecad4e84fe6e41645159d3d5edb23","seed":"4e88efeeda99c5136e145dc0fc827d1a8edc96839311ae7c13e80443b4f8e7a907040d9a38be8d789200314110a91404119e33797e4ff5fdc790404322a7479f","priv":"be1343cf39f3758c560e38fb2b949c86225aa5a32af5328af3f476c94186e1c1","pub":"0379e9a16c9624525c15070ee3730fa02a9b8dac0d1847263789ce4df4ad22b533","addr":"2defd48b2cf9556c1bf6fde9307b17bad70018ab"},{"mnemonic":"shell open sing action exact cream scatter slim right sausage victory case","master":"d0bd4329ae716aebd1dbc4b75a06a4e6103540eb1185de24e180af67174cfc61","seed":"e55f447b58f363276a8f67672f8a4cd6a3bb014b5cda555f8d94e701dc775c4092e313e1aa102f36c98edc9f1c76d863afcec6dada643667f8dc612c43cba71a","priv":"31818b15c3b42238821b8a127a33e90100c6599d6c2ea10797f111b5a741860d","pub":"03c749cbf61f0e5b3cf815c454804486f64dc15e73c53b8957f4a1b0c1b3f36942","addr":"586fd2221b5f4dd31469ce689ba34160ecb002e1"},{"mnemonic":"mistake eye absorb midnight box nose bronze joy body trim give purchase","master":"8a97dbdb939254072731791791f1cb5f86bd61bee1b1a7b1c0220362b73f9048","seed":"ff955704f42fc8451d66092b720eee4153c1edfad5ac3b96bc87d0e1ff27a1655eb4c1127aba45906799197e1a92dfbb040304cc5acbb228f20c828d0f28689a","priv":"81b5ed5d49563e225a164180c53a55ee86432ee9e59ff5c6b1ba2dfdee8ecc87","pub":"0214a81bb7326df6f884b465b655f497c20bc68d2ac499d931945a56a20b21bab3","addr":"e4d30cd4f5b383401bdd02a01bdf1e7003ff9e7b"},{"mnemonic":"stadium blouse more trend reopen sick test trash glass bounce brain total","master":"a47cb7d914af1a75ca7ff6bc0192725a7b4b4daf386a039e9aefd8679f8a9f66","seed":"2a9aaff54cc77a16b4ab472b006768beb7403cbd11cc78aea80e19765ba685abadc03dc27c6444960bcffca5e206dc28f5564fdd05292f68ed825bb06ed6fe5a","priv":"7125901a72c60386b41bb65e8bb4aff64334ba8f2e032d2c032869b3b3a648a8","pub":"03a74cd7b3d21dd8698c7cfa4c30d81a454a55ce294171f30aa70f564f4ed71751","addr":"4a8f9540cb406aa75b0d68c2eb40869a8c25da92"},{"mnemonic":"fetch use target promote later more increase logic oxygen provide original high","master":"f06c1e5b33b4d18d65ca7e0b7627c23ae19da34a6aa55ccc8509fbe9fa25de3d","seed":"8ca3dcf901cddd77ad4f6db2a2e3a48fc1a00a81b372fde0dc926c4006c8cf81862013008d9e119d811512b9f98a84c7c655b071d28c295a5dd565491b961d45","priv":"44bff7bd7e57b709b5adfc54ec47d084d80ab9549479f4707a27e06a06083f2b","pub":"028d649230f94064c7837760706a615e7a714cae79a7b2363d493f9d4300b9a2e2","addr":"23b883cc57bdf88831c021ad62b2ae475e09d365"},{"mnemonic":"boat cause tooth danger box anxiety luggage panther engage human army language","master":"2c0c2474241d615780d2a1f34c4cda2a98e138c7bdfd13c97b341ddb8f5e87e6","seed":"98246a445ad873a5e8ac532ad64643c7e4d0ecabe60c7683996d58afbeea843c61cb9518461270cd2786453ce2ef39cac5818cb1aee0f336da3112be523349e6","priv":"f94665aaee7b5a07c328d74e3f5a51bdc0896f899c739c284bb9d882636c9b67","pub":"039f75b5dd06095b39778b0b5126907ad39a9c034dd5fc5e33f53cc00ecbecd8d3","addr":"af2307aaf8e07bc2feb04eaece0063867e64c4e5"},{"mnemonic":"much youth team what empty door language travel attitude rose furnace all","master":"df555390632d0ff6d8e472ef734e8e3f8f83061d5ddbbb2034f9370310356e35","seed":"f450c859e941b9d5e84126dd4710bd0113adabda8f962d383f8ba54bcc53d0e6e1da264d1841547ebd7c1bdfb8c29089a57ce05b64093653aa57e0ba51b0084e","priv":"89705fd7c86cbe5c18758ab9d4dcb7b1b6df12979c77a61c128ec13672b4433b","pub":"027949604d41872f518c8fabd333f8f351f16d68cd7e79e341f1b8368fe1b79842","addr":"36d1cbb6eb2510e0e3c2e76c2400dacfd9eae736"},{"mnemonic":"hamster adjust rally crew clinic skull private oval vast object school liar","master":"face99969ad94de93d7979a246a8e69e85dc6249bfc71f58ab6d774449e4f18b","seed":"ecc06609969bc31a47adc214324b7f7d81d09e0e3cb32eaf6b7be548f74eac5a9397300f0ff5650bff02ca895db55241d49b7037a54cf70e3fa62a3edd7206c4","priv":"c1d424295f77f3eb9f3a71c3f800d9a5292a2df311456daa694f5f6e12a7abad","pub":"0334e88812c848228b83e80283f709bd9827e991db6076a22f7497a3e73b641ee3","addr":"5f1a48e1eab155c3a698b69f11c0db64a556140d"},{"mnemonic":"dove grab grow giraffe pulp lift judge pluck dignity theme cigar annual","master":"3bb034fc63ce92269589e21c4fe89e16081e7cb3a29ec91f5ffb30bc077d914c","seed":"6f44f1782162a9d78af64e243dfe4d44c1ac521dbc8a00977e5260b6ea5d7aba6c205bc51b6c56b5139274d8b07bb31a728702df2dc2efd8f4f07c09bbff19b2","priv":"c2d5188d3db0a2dd9853104e3978c27d490eec8c3601259c4a4bf6e0fc30260a","pub":"03f7de67b6490d9cfe61818b22380450d5b5c815767c4efd821f3962ef4d430b58","addr":"0b5513fa903ae028a8bc3153b5f50b2df555a77d"},{"mnemonic":"wire silver blouse theme lumber modify muscle among orphan genius diary crystal","master":"28064c9af3e4436ebc8e71b424d749bdc6599b56f7ef1ead765606b4920d81cf","seed":"2a132c76e5b88181c24491f83f72b215b7963972f98c3d165c3a452f88165b459bb6e3756a511f40f9de0d47df6a030e91484a2fecb1648b9f194199143ce49b","priv":"232ec9cf0fce12247cc6335c9c8d54418a7db5aae86365558646d9d69b64af02","pub":"033e30397518d760b53821e3c0b3b43b324853c919b77a855250abe95d3924741f","addr":"dc7c6c94e8f7823485edd555741cbf224087f137"},{"mnemonic":"pattern syrup now tired gentle accuse rib cruel cluster wagon sting situate","master":"39f3af4487b768e1f9c7b04b0f713d4c56a5250994850ea4b20ec010a0879028","seed":"387138abf6c255b137a365dec7b8141ada4fe9fc55d75af013270f2df78328048981e69487873ee8740da3548ba611cc90f5a9315efafff651ec41df50732068","priv":"7270c0bd092550db36c7f5787dc20d17fd98edcf34d3d662085af7dfe604c8ec","pub":"026d65397b9ec78af76ec8a6ca1270cd0caded21aebef86160d4ea446b3dcc2f6c","addr":"35566b676261d80bd15792cbb348b79da3b10f56"},{"mnemonic":"blind force awesome radar law patch warfare defy device exist chuckle because","master":"b5eb133b2b7cdeb1bf5e6d3210f6a26b79b544ecf911f6f8cd838c7a6383e0ab","seed":"8a4539eb40090aa2cee32979ca6e8a23c1dcff202c935319db667cef1d2d49cd2a71f9cc54bdacbbed179b20feab254b932bc3c900d24216c089ac4f5c2cbac5","priv":"45e109f71861222311afe9d12b8a2a26d6f3fd0484b97a96bce464bec83346a0","pub":"03fd6c933a364638f867e6fa329d5cbf35aa9701061743ce5f1f6f6daa7137b3c1","addr":"dc3b76c2afeb877b256d7a9375618d0ec526fd6a"},{"mnemonic":"chef flock stem illegal later shadow tragic story tongue also fade core","master":"b7e82f75da29acb35a7714d3bf3aea45196e1857b5597a25b8a7ef6b69e9271f","seed":"7d02c419d5370133b6a0d0bda76a70b784e530c9a0b389cf2f6eebaa07ccaf946859cf4a7b2076814909f71c9c84ce3c0e45ee8caca9a753d5c2240029ca8847","priv":"555a830f9fc1f99debe0fbefcf34df402655484e5054c3fbd6c6a127e3356675","pub":"0238bc6cfb2c3c335b1564fe159e478d700a95ecc34ef23b7af3d571da8d136214","addr":"d3e9edf902c8dc5fabd17c17db492b15bdc33ae4"},{"mnemonic":"paddle appear actress output peace maid foam share afraid quick into erosion","master":"a3eb9cf3115d6b2f3cbe4bcc4f06e879b837d3b8960853a955f1231b8f95318e","seed":"a6b3ea2da0b83408010911cc091f9bb6d296fb13c1607cabb850824591ee5f69d0a2d4576a4361f3b368d34469f53282a1f9adadab3f8ab12956efa6d323cd5b","priv":"a37a2cf232918206e68593863c195d4319548c85d113456a0531b160b1c4509f","pub":"02a129fb596143418f94ec7bb1272aa1fda227e606c99f86cde12e8e7dd9b06755","addr":"69cfe226958b42832adcf69c7c84b734459af9f2"},{"mnemonic":"they garment wave wolf rubber firm toast hidden grit puzzle march rebel","master":"9c20ee12718c0fea98422c9ae0fa861da154552ffeb9e9991443edf224557309","seed":"99880bead4bf15beec406d9e980b46db9cfccd80473fe36d3471a0be1cce8f13bab732ace2e3589b1edbc5900c6641e088dc7a972bf11541ad475d97a66bd61c","priv":"b38db625f8ee7badcd89d159fa867b7d30ae946f199141f63af8e36c59750150","pub":"03ba880b842c952123b8bdb306fb0ec8c3c39e6bae28f2241242858c5c9c8c574a","addr":"24b75369a914827ee1e2697d5f591a58cf3f7be5"},{"mnemonic":"virus stand margin found heavy gadget depart idle guess siren mandate sock","master":"b6489aba56cfbac38041a70c7442bd298928cc37706dd01481fae719a2cc1222","seed":"fe240f7a830cd984b4b07cd77ba9a4f6b25e753cd2c981231e1458ed6775969a6b032be398838d2b5a706563d575177812361fa7cd35798e9a260b5454f3cc53","priv":"801663a31b3fa9f6788c826388b6d7272c53b0c331843c3ad19ab8f97eafb1b9","pub":"03067a334f5db13f9918aca85c5465042a8e994b835d6491604ea7c6b5d8a4403c","addr":"10cbc824bf4e61e2eb4091c0b1afe0f24ffec681"},{"mnemonic":"logic drip eternal frozen equal defense pudding prosper destroy chase faculty position","master":"df13ceb0854b9a18c97c8c972bc42e85231d26c4cdc87dfd3b8870b8ae0bda01","seed":"df990ef85f0d21de059f96b7037b905062b9e098a5f401afe29ae379a60c611a45cdd93f98f4994f231e549f739478566e71e7793fa750e92630aaa661b30e99","priv":"0395a33ce515a68172c9d8a324fdcb81073cd903f092581beb8ca73e8fd3016b","pub":"025a43eb1e0914d6f3c9269123280ec49ad469058d623230885b1f5dbb5f8dbcfa","addr":"6fa784b66d9a3c27073fc463e5a306916bd64374"},{"mnemonic":"nephew august wise enjoy age comfort hurdle cross feel depend south current","master":"9c01203e9921c9cbc2a05aff4cb90757f3d2e615ee6c6ef2d79100b48a48214d","seed":"19b2972d829bab57e706d21f00356d24cbbce556251aec246c36cd7a5243898371c92ef562ab2619244ab5e4854b9f76f76e2886b35cbf591a154a2e915a8a11","priv":"29af8262b1361dad291ed3e682a77a6bb09378c6503037da5c236b5eee1ccc69","pub":"02bc9c65596cc3f49aadad747651387a44d922de3f8b68a9876fb55e50372f1fd0","addr":"c4e1dd670e6c2ffb3a964315b0f7a51b2116126c"},{"mnemonic":"elder badge muscle tunnel sunny ring kite glide post slot injury crime","master":"e5dd0863b56bb3058b0aa457e17bed226f7f8afbc09c7ebf3cde93ac5912d22d","seed":"cd12f2dd94caf3a76292863e9528acd822c915385d8b84a09326b498ad5f1a60a1750686204b2c51093a3a3003ea558bd490cec607837675d2561a0b6f666a81","priv":"0f8717c113f78a6aaf7d57a93d5e7ec3a0326c119f792e8d16dee61b485beb16","pub":"02be9b54e62d1d26d08c1a2126c813a3a3a1a8d399440471491534dba209b3b8db","addr":"dde70795b05c51858f513bb59e2e0aa9d0330aa1"},{"mnemonic":"lunch cereal approve swing poet fresh sphere spray tower scale clerk main","master":"3c7e4e9876b819aad6e94d6decb42f615923873a72a2ca8b6df3b8b0ee1c77b5","seed":"0f9fb7102299f4b02874a785f60009c616ffc1e74e4386e78ab3abe2124257c7aec23b8926883dfd343f7260bad204f1261bb76cf0233dae8785c5e3dc9b015a","priv":"17b7b6f6184325c77195a60bcb15358b318a53ec2990dd46d8f60d0bf7e2e245","pub":"03eddd35bf621d1a943edeae5f5a5242687ee7f99f14be22f694653e449b77c177","addr":"06e8ee97a22bb6b2d458bc408bee7384749ada83"},{"mnemonic":"night law title fitness critic soap runway patrol carry drift damp state","master":"f7cc66a4812f3a394f9d52a0d83777f22eaf8fef4575561e26b0c636c4beff55","seed":"99acca4b65136a2b94c935892e265d125a1e8ef834e52efdb7b2ad09d973806dc318c43b0805924f5b239b74e6e516615ebf42d0379baee78ab63a2a24d03bb3","priv":"14506c9564b199203e8222c7508dac642fc6f15c981a7ed0fd21658c18660f04","pub":"0205f6b2c6ac7c0785d7f0c9aa85258167a314bacafa71f478c2577b5f9a3f9dc9","addr":"b380fefd78145bbe311a87e314ddf3b33d9bb34b"},{"mnemonic":"predict either bean grace myth scout number used void clown route member","master":"c7cba4de1441602a0b8ea2e11a4d72d7a21cae827db034ed4e43cbb38e608a51","seed":"8e80bededc4b64dac814dcb6e8dc5ce3acfb6f59988f13e24106fa7b3205c72eca6a16ee44ab51a54ab0a07d1e7d855fc75e3bcdd5d652e10a8fe33f623b15a1","priv":"6577584c26c25b3d6b11a1f669030008793f3d173721acc811f2dfd470d9e136","pub":"02e7f1c5213aded8dc3a44b14874cd9098a41e5cf0a7c83b7b3e045b8707d1d306","addr":"17614a88c0e044659cb6f99334fd1d8a83390df6"},{"mnemonic":"actual between river curve keep sing hollow bread theme corn mad easily","master":"e5498c15a99ef460088da7513360cc0e8ed3de095027783154425011575afd70","seed":"55fdc52505724e42ec76e0871860226daee30280de52f3d0538b8cbcc426ecd2d44287b4f1f11c01889ef63a6012896311a81f202c41e70725f3dff333f357c0","priv":"05b5a9a68afd24c6970b1686297582b3cb806729a277a056853f8918a706b0df","pub":"021a01e00670749567cd09de2ed8d0a66f0a0cb00cebb969ec43dcc9d6718da372","addr":"fb0c39ecab019c2d259baeba4819d924f8b9d97c"},{"mnemonic":"route aunt shed razor invite board ignore tower penalty claw absent solar","master":"c0f943565964df86bc140e8a8099ccb23417e7b86bf3c9f4d8aabdf7271cc721","seed":"111f3c5d234f0c02921ba5b30149d1913956a6c37e93fafaddbb3bf437b6709599bd623ad6ca97610717db77802f9c591ba352e7b08f4a06a4b897b9ac25c8ab","priv":"bba974522cb69e90b6b10ddd32f3b313bf5dfc129628bd2f10ad84a742a22cf8","pub":"0341c52f99a97637d09d68695b7b28f0c99d3fc5218d297e7bd95b267d2d7cac6c","addr":"5b4e4a18db22862daf7c43ec209bcb61ee139904"},{"mnemonic":"roof select rather approve must trumpet during more outside off owner blanket","master":"840894a95b0850e37a7424cdf10f73361387fffd96783a988a5d0e27012cb2cd","seed":"9eb1782d3ddbca4be52803a2dfdc85ef8ed55bc9b939246b9220dd911360c7323908996bfdcebf51b87c31c55cf2109c4792cf54b60374bff8f2c46bdfb97973","priv":"2db028d5651025a18a06e2c9bf77282f4bf35a8f54788624ffaadcb0caf34474","pub":"031c85b1faa9a2c9b3ad80328c54eb24cf27837d1418dba04fce05565f91e3344e","addr":"a7e4da90a801adcb7b3d9b947e760966fb4aadd6"},{"mnemonic":"album ball volume coffee motion cattle album wing unusual tornado bread stairs","master":"8bdb565fdd586d6aa72a53ecf88e2c81d48552034401bed5d130c862f179d159","seed":"aa0aeb0065b4c8e008fc9b1363fd4b32c0405359dd99f3a27670874bee96e8f1d76fdc807bd903289fb66b33138b92902ecb0d2c1627ef39353eb973b21b0003","priv":"54288cb0b5530aacba3ae1b16945a783e76ffde7e7c523c0c1e1293f00b5adc7","pub":"036974570620961a4e32d0329c851cb1e4218566056249c534ae92d77aabb73438","addr":"d7e65a2d95bb5d705ee894e16e4b6e4aea4821ec"},{"mnemonic":"start staff chalk volume emotion liar route lady sample mind casual involve","master":"aa479da35fc7c15a84e37a118102c41bb62012d872e34fb4f1317b67f9d7c452","seed":"70a8a8b15f77356e12438aef9fc97e6e6279be885fdcb28968db25d5c7bd2a3685aae1ee882d49658414af583c4339fc97f75f70f5b6ab23d184768cf12472b5","priv":"e1f12833fe2e792a0d959de815678a79e1e86342c7a092faba765979fde1d93f","pub":"02f127e13853937be361e47873d965fb8a6d602426c89389ffb45ee712e86e8231","addr":"4fdff2b288741e9f96b6595136c780d979403e2c"},{"mnemonic":"canvas fashion mandate will phrase spend galaxy good advance dismiss inhale holiday","master":"71707593bfe88f2751e6b381282fd71177be82bdc7b930c89c3f30606e0fd356","seed":"c0367432ce6b26e2d0b279b008b1d7d55e89b50b3dc55244360eb611d3af8c4e2dc6ee92f38e5e32309d4ca3b0b5c9eb9f8ba5edff66650dd052ac01f65ffc7c","priv":"0d53e4411bf7c498836412991515876c671967b55704e2928d87f3559a922911","pub":"03bccf2d3a8927babc9cdb6ae16addef1734739941071149122e780c9afd83877e","addr":"e1f22608018d5a6ad02dcac24a9ff28e065ce2c1"},{"mnemonic":"area thumb debate bracket unhappy muffin liar cute subject resource oppose nice","master":"416206edbc49f77c17405abe51397e5d5b547d300d296334b9848e4a844f355e","seed":"a08e97cf029eef0c4bcb3b2dca43e64b7a358199ced33a114c390ea81bdeef23aa7a4d6255993367426d051a56106e485d78f9b4057b4c50dc242d95484b39ba","priv":"9379dd5b24819205a9c7cc6a30ca2a416e6008af93817087b16778e9fa022fba","pub":"03e0796e8edc870070f179c669ef8acac6ba5d745c954762e5738e6db4d73317b4","addr":"ba2f7b307d6c8ba32f9f39174616def7551c4dc5"},{"mnemonic":"ahead face gloom dutch simple battle either hour abandon slush episode view","master":"5c953db2136db4be64531ea6556d5b93f1731332727eafa12630307dbc65c587","seed":"31d751f855507457129f25ecfa2ab8a50db37da0fb13b62ea4e232fdb8c7093c236502da769a0b3474a9436351b87df03a69c70b1b96c61f1675b8fec00f8ab1","priv":"aed4993762d4e8e31a12b500f8beecc1a3e747c2ff290c4e70141de4ed12be8b","pub":"02c922d80cccb9faa955b2ea0a90d3f72a88d8dd203a51e0aafb36c38af1f4c880","addr":"cb41fed3b24d89ef058d25d7264b6113e0481ce6"},{"mnemonic":"van custom clump rug floor what joy live art weekend unfold frame","master":"ab89a9c945f11e8ba88683d2a13cab657a9c938bd9014f19cf552bfd1db49bae","seed":"fffc2e2b6c4e1ff826e0d68ef4a2660417278cfce527ca55e48c5d3286d78ab4d6ca874514d70164e9040641281478b8c3b078bee6447d78262cc0556b463c4c","priv":"cfea30906faf51cc15f5ea6fd96ed92a40dc4bf80737a20ba37280e63ff1ddc0","pub":"020bcb8f7581415d4fe27dc7d0dcb25e4e4883d1290284f9d3028a6d0d618daa0d","addr":"57563ee5328ec10f7af2d0c44b95e5084afca64e"},{"mnemonic":"icon series document grass dutch green blossom report violin beauty window luggage","master":"9a203cb69ec2d8d19660947de9dd0b46ccbb07c9fcccb63da50fd3383c5f31e0","seed":"4acb08487e8a407ea10685ffa35b1c040e4dbdcb7e18a25c94a459bc7a2224246a00b66b88e6bea84948ed07f818e6e1a8fd4ebd102339773e704ce048a359ea","priv":"64d25c6a43d0aae389e2bc5b8f7d260098d85dd6a8ce929e42597490e5240ef8","pub":"03602214319ab01e65bda4711f9d03be60da39e092472d50492397e8f38d90f8fc","addr":"21fed5aa21ab9fdad79aa757d1408c0921d08cf0"},{"mnemonic":"upon legal wear defy path object fold security stem face question hint","master":"efa4834167d9f43a0807a950687e79ccf9327ec707fa4324ce8bdb40ed65e692","seed":"da5371985f4c48954726882bb278971512f9e4ee681645fea98415bd3ed4c7b049bfed3a3105f4d064b61de443500f53b4996c1fd7d2835d6b3e5b52cf67df5f","priv":"963ebebc47e1bf6c8f8cb515d7044f2095f61a8f77ecc2c7d5f8d1900af3b41e","pub":"0267d73ad34ba786e92207f5485f8aed4c634bccefe1a6c6a018dd30a9969bf1b9","addr":"f7b39221ff5352c17537d201c7d8422ea4c2f256"},{"mnemonic":"adjust symbol absorb winter dilemma reflect private all eager naive bundle lucky","master":"f8469edc4fc1bc6f3b934bc6ff8658f03fe2bae4d9be0b2689caea9f23d708e2","seed":"cfcf7299ef520c324a79db53e24326523e1d2346f173ecdd2bfdb38462a83c290cf80260353ceac5089efdfd9c819c3f0f15ed653ac3c4719b0ee6f0481335de","priv":"44025bd2acfbc6710d64d8b71eeec4934e054ab201419fbd553f6427e33d5197","pub":"02bbe2326c3d6c372c22c3aaf8118742442d237830428824160c5e703c268e06bc","addr":"81986a5c30d253a2b2ad8cec56dfd56ee3435772"},{"mnemonic":"fringe betray observe subway nation dignity stem omit topic lyrics index cause","master":"b8656cb35da2ecaf6b5189d8d252a08a15495afbf756ad1365ed757bcb46945b","seed":"cf0cce225311bc1fae42b654561de73cd2720d5a2e280cf39a1391cda8937fba9e69bb5b73b31e929d39a5f58f9505351f752d7666aa81211f69945ad81feba2","priv":"d55bc330b3ab7d09b0da10c1640c6fdf10909e5c6318801c3e7f877654b8576f","pub":"0222c2696c6480e840a7ff5d106f025d87309a0754a3638fcec93a6c7b8ab1f48e","addr":"2bbcd167f45d4f265075a2aac85d0ab7582d435e"},{"mnemonic":"ski labor urge doctor repair purity winter pond virtual salon number supreme","master":"283171546741970d2804029ce72b5848cc479f32f719b4f28670b00729c9ebf4","seed":"4aff8616a56b882083dc3f586afe1128f17aaae7b0c751bd24109094144c0f7aba69dd63cc4490301a72ac950e6a9c71959fd387629429a65178d1d4c7850322","priv":"2a0f5db45dca9a199102d2b920615cf2cd2c3a1d06d3fe72d5a64291fecfa116","pub":"0294a39a5a6f878929b7c18b0df75c7f42318864d84eaaaa68891f075f51906231","addr":"5173ecedd00d5de79bacab582a5b3de6f0534765"},{"mnemonic":"surge move forum tongue female cart foam coffee hole screen short clever","master":"57dd827d6deb98495732fbf12e0098970959ecdf113d441bbe6bd5064abc07f2","seed":"606c47f8d6984ce47270900cadf4cf5df3461f9293beeeaddc537c2e4b1d3ee7456ec7165c51e267d3c02a8cbbb5a2478626e475483f121ca5856005d0cccac3","priv":"3895a34ceb1de14e7e863759517cad044901cc7c8323e8565bbba98f5f3719b0","pub":"03a30052a8169da7d2342be9b0e2788df3e5ba7b4e6fef048662427476d875f537","addr":"9d9d8be022457576a9bf8a6a48f760fe346f22e1"},{"mnemonic":"ladder now flat food giraffe myth tattoo client party address tip avocado","master":"9986ab1b096cc4a635c2f99e7b191ee4d786b090cb1e00bed2cf18d6ff919aff","seed":"2bdf711ea898c4d62fc1c30a4a55dcec4928186c9d118befa4afd8c52d14291b3254ed926b1b1bbbcfe5ae775f74da99fe2112c7e2c64013b8f3b9de5adc18b2","priv":"cd0cf663053d6ac0d9785c3a56ae190fb8d0da670d6529e2f4572c1388dc6d8b","pub":"02ea2969ffa84be7d76fa55f4a897ecc63ebd61858b7561d41e179a38c7dbf8b79","addr":"a640cc723fd1d903e60a9de68e0a009b5e215812"},{"mnemonic":"change velvet mobile copy column cabin mountain shoe hub collect gym armed","master":"f80e68b799c63dd914912454f68a3c6ee5e01530bc48c130f1a4cfe46fdf2265","seed":"1bf846591febdca13c576bcdadd352b4b8b2ab8e346ab7db8213120d5b2f7a8031144adfe06a47f1d200f69c46bf9dd6dfae8e2d8dc94089b4974275960964d5","priv":"370af5ea565ec8725dbb8f63e141b12480bf43d39c219d612ff28e2a5fef031f","pub":"024f70c3096eeaa522240b50c1ad7347f1df1e764a305b8e618489788bf15865d7","addr":"e5226a6737202e5ea8d44f84620317f65fcd4ffe"},{"mnemonic":"crystal impose connect thing cement grow gospel reopen hand frame child shuffle","master":"a8d5b74cb00dc99c4fefff90a2f203b7e73daec3c7edfc71723894db050771f1","seed":"4e7c12a432766826d61cd07bec71147cd4282b2777b8ada1d09be5b873b9c51fb90ff4f4ea75739254fe7124e24696f66313d75289dcfb64ba5f5c8988b27ff8","priv":"7bae6919d134d0f150972cb0d96b0cbb3002d0d3b70efb2f9b03541c3830ae21","pub":"02daefc7677b5d77ec5fd27cead44fb3bd2d089be2b2e9744c1dcdc2e7def701e4","addr":"dd3ece1b6e903523289949e7aff1de580a536746"},{"mnemonic":"seek rain danger defy olive pluck people trumpet wide pave still cactus","master":"9d45b99a256e90347877aa27845d7ce7a259a8b50f7039852c60c16c372202c4","seed":"9c3f7dcb4aada2a8c204bef9a28c039dddd431f3daf5e70feb240be712cbb3dee3e5b65ed1e681255e9bb53bf762d82b95dad1bdedb27d0e18801ef1c5edd7bd","priv":"f43ce1484840f98f862f7d9c835bb3987fbc0413cf9121233bc29e829c779d45","pub":"02d82770b2af7ebb2a5eec49138178dd7899783a1ae1ea43ec3b2a13d6acd90c4c","addr":"49c6feff9794634c9fa66c76150375637f52ccc2"},{"mnemonic":"cat bid just hat diagram mimic field engine light elder resource render","master":"bf8a65e5cde0094db2ec4a5d776acfc944b0b482343bbe167a4bcb0a3492a9dc","seed":"780befda0890785a11f947a7da4280b897ddac841fa65e7cfbb01b09a46af665c25dba88abf759bac86e02d25d90c41347cd872f8abaedb158743dca746e87c7","priv":"b3f9f0ea5881318a1e011283a4e845ef6fa8e1ec5110bcdbb02cd37c4321c0b8","pub":"0214709b38a99a173a8b030bf9392534ae50d157e9e247f83d271be86872846336","addr":"9a7dc12f808fc5e599e2c03f73147317e381822e"},{"mnemonic":"eye thing material display own coral ankle spell hurry empty pitch sadness","master":"1a7c1facdec5151ca8d52af1f507f45c6614d12836d2604421138339c81dee2e","seed":"9c741558ad4c72086738a34898567312930af3221d13b160a39467d966862405a7f9b0b8718207bff6e26929cd33c578457b0d43e2e6358d488016c6ed7754bc","priv":"960704fe746bbf00a1c8d6bada8e500f2a7155af9f8328b7e4da7fc89fe079cf","pub":"0217e48b2a7ca750baac93ffa241b6fd3cd2422989096e0ff5eaf89f23277efcdd","addr":"13c55c8720eb51b5638331330ca19291213fdcfd"},{"mnemonic":"attend analyst stage network secret matter tackle safe stumble rifle lemon minimum","master":"e23dd8723b90971d4e03e21655e597b5f8110f0388392eff572e88db7f644cad","seed":"cfde90f605bace06583d24be20b13f73b3fd0acc60fcd93c2cb7d4eb6fcf70c885da2da7b709ba036ba20c275d99dd3a6af434b00932addbbd7b51a10cb5ddf4","priv":"ee54ee95a349da703f6d192fec6f776db6141a0cfa80372be04ef8b12ab65f82","pub":"020850e7d1011e08d7fd3ce20083b6c2658dcbdfdc067c979bea22d86403da9992","addr":"d834b0d108165f814c2616c91e18ba8b76a0ce92"},{"mnemonic":"student list element dilemma air faint eternal beach approve virtual fold large","master":"0dbc34013e5fddd9a1fc2d3e67a2d6d7445bc31e8343b4bf1a9c4941a24a2691","seed":"61b310aaa1875695f855a341f64b849774e3746db36303ada42eb60bbc91bc0fa7199c10f853e1def5fbf0a9ff2c38dcd803866d5473808a5b6340d88260cf57","priv":"ece1069e2cec7f5d270c3504e0cd9d8806eeb7ce8ce48a138c92d93d68fc9b7b","pub":"037989ae45a6a1f0ffcf9f73f1910a91bdb1ec39101810f3916d29a70b92232949","addr":"10c79559de51b7b96a7e0aa97f567289c41df1b7"},{"mnemonic":"ordinary fade chapter cheese patch injury better toddler rare manual rug opera","master":"ef81a17192ebb6e980676cacc7c9ace6af5d449a3c976d4f9a8a541dcef9d7a9","seed":"5a277523f2cd468b96db9dc30f8dec2d006035e388ef5348bb327eecd108d9e2815b3575b0f6d0da7560fdee6244194eefedb25edafd6f53019a91063478dca4","priv":"86e5fbe3136bcb11f0ed6dd97e3fc30afc0590d38b637fb19589947bd33f26a1","pub":"032fc8cd996500910443186db8432f24eddd6e04e00aac15db80cb5fcd73b7ec5e","addr":"db0aaf4c44693b2b93a8901640b940104d4931c4"},{"mnemonic":"leg easy evil ceiling candy okay afford apology around duck access ostrich","master":"098f864a847ca737aa5866f14fa96e9e5a6958758b56bc205d5c45f77b2f6fa5","seed":"7e6d013d39c652c2d57ccbec782fd0b9da7610d3c716b1c5f374daabf44f0a21726cf39b503850a5fe7daac263cd12dafe5c81a38b47e59b254027ceb298b520","priv":"1b5e814a954729ec4d4d25e01b52e6a48fc3beec84e43153cf9e5b4d5e61b852","pub":"0207214c051cc66259f234100e278a89b7ca3185ecf264d596ac8a4d3baddea28f","addr":"45cc1c7df7fb67a482dde6285b4dff7087857970"},{"mnemonic":"episode suspect cinnamon recall shell search allow hedgehog web avoid hero expand","master":"ede0db7b34ead2b35bd378d62d1b202ec206a389e27ba6d70813e3f98544f7ea","seed":"186c47e08e2fa1151bdafa4c8d16c5f6d8e9a61600a7ed76257cd3b41338a6d158d34ab84448c34c871243e211fc5082d3a6e199749ecf5bcc3fd8341e2b7784","priv":"d19884813f89a780962d2bdb40f36debddb81d132baa29795022b9498f04de0b","pub":"035f028dd1b126d6ea1b8091ac9dee9a3f44589a166d84a88ee982bc040c67d1eb","addr":"77b6f1f39bd0c5c636763b855396d1fcc5109778"},{"mnemonic":"safe run differ offer valve sing stomach table update base pitch pyramid","master":"1f6e07713ac34f997bbbfa0148cf2cfded624ee8eb4c89a66e2a88af2becaa6c","seed":"9c07c30f9b29fccb62670c57b8bc2210851ae9c80a3aee48c03e6bd35357626ebc6af1226f236508624fffbb52a8cc56fd21d8d2ab72a893a931c4891a33bc09","priv":"94c75ada800b2f73bc43625d569caf9f59f3afab6c2a8f9b023abf169c1a50e7","pub":"03263f919a4f79646ba17e1521c15f30d62c545d59c12344d4ce7d7561f8dd8428","addr":"17a63a29abe177f8bd93648ae4283b175b83c841"},{"mnemonic":"bubble bracket panda fury turkey decide obvious nest carpet defense side destroy","master":"d429dd03c2aac3ad66e8ea577ff48889d6ee006906f0d74be45d935c11f95c4e","seed":"d665e949ccba3afe3d3e14c8328f9d2eed1b3838e97a12d137bb188b4480b31f5f8ff388c4ea3aae961e6e98ae40177bd7ae075fe09aabfbab8140da075e8702","priv":"651abfb657e1b400e230b0fa3de8c022fc6fe33c2a80e425b13a3485aca1bef2","pub":"039d2e95484a02e3be5176e31ad41d9d38fd616aa37bc2f3032594f99b1d4225b7","addr":"cdd7ea2dfee41bc45d88e147ca87f15cf0278778"},{"mnemonic":"magnet setup unhappy slide human frequent notice unfold use ticket raccoon worry","master":"6a50fb7353ff7e3eff6054bee3ed8a156e3f4d65d712ef024ebbd58c11b16223","seed":"15195988c4a41524602465915d8c66b71acb07f8681a81bfcc77f5e8ae0071da3d900792c6666ed7f42e5362d1b22ec5de2856019e1d98d34f3bd977e5d6e712","priv":"e2e5997cea44fa966ed05107ee5347fe245ed436396a54dbd7bb0dcd45b02a5d","pub":"0251022b3f87060b140337f8a192c3037fa423b86f761c8e8b9abe13fdc7e954de","addr":"fb33e8b4227a4e31ee6d062f14129d86c190b864"},{"mnemonic":"extend expect crunch wear narrow crater opera dumb poet tone crunch eyebrow","master":"3a18fd4a5605d4a691097909a8fad033a9eacf3a8a6abbffbea184cb43bc4054","seed":"37661f80614a95188f9bf047b8b78201ba0512421b3fdbdb079d36cff88be9fcc6b2ee25a98495eec605c23eca528535adb4381b524ead9327671006a34d81e2","priv":"66b6e15ade42ef203b614a0d4db859263aab55cf9d98ae2118cbae7a2a8ba190","pub":"0318a0e61048878782f581429fdb2acfb382c59ede2a9c9f96112fc0a4dce78702","addr":"d3cbc69596f7f398a77be321ab4b306cad08798e"},{"mnemonic":"genius genius letter space share rich lava tenant drastic today vivid attract","master":"b1cf44f330ef51b5bfc09c224b83f3f678381b54328d6e407368f34f6b96a7f0","seed":"adbba0a0b7e15f2e7a8f95b0cc9e3b212fd3db246c0dd0b2dc41fe740c2d045aad24b9113dadc5b72d7e53d6c681fd702ae46b6bac877303e1ef4f9b1daa2822","priv":"4bc6a6a787283d7110cf4dd8e5f41b5abfbb302a5bd627cdc78cc419bd77ecf2","pub":"02fd610c024bf89e83940d0a5142c1b716786ae7c02e8779de11b72d3474b27260","addr":"f31609b8ee21b0da14e6d7ebab364b57230a8cc5"},{"mnemonic":"shadow ramp scan elbow cinnamon intact flash bulk squirrel pill zero tail","master":"46e4cc1975a8a363b8834ef06ff7a413a6158244a769ef15a9fcfe8981a0a6de","seed":"a8e143c8945640084294cee0afa09fbe4607059c8497259afe64dadc11b18b2d0eea33617b28b0f80419fed842afcb83fd1ab72c163c65e798bd1668cda9ba43","priv":"914a656705241622201d5ec8893d0d2484de7f4546847b3b2b2bc5afff743547","pub":"02f44993307ba52f2a927c5e7f7aa0baa6036a1e396d1d8593be5fecfd330e8d70","addr":"f966ac61247fc88e7d8a8eeaa2e682a669f17e81"},{"mnemonic":"wire list water over regret much ketchup slim capable proud then bike","master":"161946d516fc549a577b76ca6361f97b95ec58ec3bd2486dcef7f0d9ac9de062","seed":"c9af9f1c0f7fdcd56a69faf1274e563dc8ab739fad639e2032b4c0de10081544112b54ffb36fa1f6dc6419a7c073e0f3b4f2fc1a9ed95e4ee7dd300ea15d48c5","priv":"9f7f59143beb62116a592e3884d34d28a845c557be670278877c34f3749e74dd","pub":"027ab6afbdf54f5e952ac1d254cab364ffd91d49838354b02415a97421f9b9bdff","addr":"3824d1afbe44568f2ff4762157046e8f9bb561be"},{"mnemonic":"elder stereo hurt upon process furnace treat tool hole return base protect","master":"331d45143f0f94ba73de22ff235fec62132559735071ef806fb696e36f113352","seed":"4967f2af0a49298099ac49d75a3d99b99edf1165e3507c9055a9cb39a69aa05f6c07c192984e86f6abec6ab9b7fe8e66d22451aed158a6664ecd59b48932d9d2","priv":"7d547ee935de522967f92d0114dd40bb5c25d4f5aa2a1f70ad291601b7d0eaf3","pub":"03caf4c539853b640bf55c9db886e9906888e05fad3e18668f6c6d529434a73f32","addr":"816e255b2ca6837ba06d35fb834c3c246563d638"},{"mnemonic":"faith ski shell chest left entry admit smooth since hire pipe firm","master":"65f1eb6d72553cefc6fa5202583bb6db0af228fc0f008af45a3301cfbd279e05","seed":"2b778002d9097d84bb24e0dc577059a08e0dc24b47d401a37ece9b43c45585d49ccf9fdc6dfd87dfa2c4a70a226b9879f0927b0f3bf33b8f25573c1b6da98679","priv":"249dd8ddb06d455e6883a7126084aeccba0193a8ca0eadc6f924c16922ad891c","pub":"0390281dd22e02560114169d73fd72ae58ac7a83681a8d985cbf25fb39b485ba1e","addr":"9fb024edfc6a4e72e4fee5a4387c7bf09583eb1e"},{"mnemonic":"junior bracket pigeon swamp morning kitchen friend bike question emerge month faculty","master":"7a3d1634588a1d344986c5bdb8e5aade22a0fe74b5d234bce3591edfbc2279e9","seed":"4429c5b3dbd4db57f6ce8cf79533a746db6c28e1494de3610f225eeb00d2a6fef327aa17d68c75ae552c9c76b0dec4e06c583d531e45d6ab1f7d5dbcc259ae29","priv":"20b7253a740bf61bdee294c67b31aae21f90a41b2bd31a02267a773af049f983","pub":"03531e337b7ed416851867015996fe06b19a82bab432137ac32c914503fdf7ef58","addr":"e225e41ab3e0798b3631d71e753179bcd9226ede"},{"mnemonic":"farm frog apple capital foam behind grid project vague rural ugly sail","master":"22f4185158d434b8084c21d62c2fe3e653f9f1c5e2d592d72188bc36e9194e57","seed":"b92f9f3c0d496fc264acc1c04a42bca773f34137c92bb0f8fae52009166f48ed36d81c15be9e8eee8fe5f1ea2e7e0311a2d2b683285730cd6657ff862947ec4f","priv":"696f26ebb007bf4615ffedcb8a08ebc1b92be88955fb34eb5f08210970d566a0","pub":"03bb83731e190bdf7777058603180bc89a85f4bdd68fab3ecbd5c8a43f0e9bdc93","addr":"9c9f3d7c144c33f06ab476c752227c12149d9217"},{"mnemonic":"spare twenty above tape monster topple brush excuse squirrel pigeon maple fun","master":"a1ee9e1be2cb0f318e9cfca44f99ce405115ff3336d1678d94904efdb71f65c6","seed":"e90734515d14ab1b96bccb6f823abf76f21d47b450841ed1fe9ab7bec8a0e673828d09ee61b6a3f9bac0dfca778287abd21d70d45c596cd606261bd4baacc98e","priv":"d8239cc87c27ee5b6aa13d55505a8b0b2785392d26b0945976b575867b3aa068","pub":"0314db00f6e43e36e5f9e6a30cb2bb595cf4abc4cf26ada7d3bc7502b0e6be8919","addr":"fa50a1e20f2f4e490359a011ae4277ec61ca2a61"},{"mnemonic":"token cruel spot firm initial trouble slogan arrive steak inner champion affair","master":"4fd49883fd0f3b32564fa038cb60f762bcf4e65d3e297649cda474a6de9e16c1","seed":"c8b7b6807f2cef122125ddccd237435abeb2370a33db98f34336a28763996b81c336e7405e782d61f6b391b0ab2792b3788e27e67cf467127a50a6b2603820ad","priv":"e57e8f46f2eabf828cd024b4c7935126c95661bcbaf58488ddf7954b1a4486d2","pub":"03d959dd4d72e64be96260d31018ff3b3cc626ea3b80af1d6c3f9f8ed6452f9da6","addr":"e03c8d22c2e4513ffebefa5ed6e89245d36c1741"},{"mnemonic":"gentle whale exist height dress develop beef lounge apple gadget foil sea","master":"ed29987b8768b2f2636556eb1db2a69d48e6969f8b5ed455e39d6239ef376537","seed":"f4a08df5d89dd733e9b73df8a8518a0f3b632debdea655ea75b8b5b6afcc7c52d8bc0a2cf1337226c2e065ca0d71b6854109e360da8037b9c2a01156b2ca2b86","priv":"656e7a54258d7e2f4c493ae80e28c4eb08452175635cf0cf5a9111bdb6f76695","pub":"02f5f6c66a11efe81e76e7a5d440b9ca1b0dd73429426f4a27f3493f5dc7140927","addr":"e01072fa64ebf18099a46ee3799bffb49b990972"},{"mnemonic":"warm offer tattoo home elegant sausage sister cancel rocket struggle insane theme","master":"a58d8e3b8c25c182f6ba0e9e61b8aab35c04d846d1e44ccf3b305bbc03d839f7","seed":"ae94ef9d748fc2b348be876474f261458e3653cdd3f10448af8ee2caab848195cb802050f7d5d098e737672e331f1e48ee0e14c5924665f0aba855b89544f1a0","priv":"4534e2a9248df1bf1882da1a11ac8401b2db9cd92e5c3698d4610d120e6ff882","pub":"0246a4a61fd11a856a818f3726163b7f2f5f41b95f5ec513554f7237d8c85c867c","addr":"dbcf36e66ca99566f38ab8fb86930494c28405fe"},{"mnemonic":"ill orbit raise deliver fat age remind throw stomach country duck neglect","master":"9899f940702cfb78dbb9fe8d743301e2de5129f943c8dcfc4215e937c59280d8","seed":"789537517312103fd88f70345425c402bf0c665c34baf7d3e24c2c969162afae078adf365a0bc732de7abecda4ef5b12e213f4027a9e0ae621dbb6a16532ecd5","priv":"cb4acbee9d41eff9ef210ca73ed0ac71f353464210fc29b30c863a0c23214653","pub":"032779afee4e50503db9c67efc858d521ad8454cd691febc52540c4cf96ca92231","addr":"bc60e5da2c9e96698f32bbd087bf1b3b599a94d5"},{"mnemonic":"fold concert earth alley broom render ranch worry motor virtual industry bullet","master":"3eaddb6d4a2a73a1f0d094957901b9a53f4b36ef00451c9157a3dc159b523cb7","seed":"479d7ca92dade2e47b3f410fa563624cb9a7419921c687e93aba27d82af323bf1d0f04d12faa018732a476fc626df000f705525706a5e5958afe59891f10e43a","priv":"d0e151f6b58c2f48d0311fb2800e66db4fbd9ec14c92f84654907c5018f81c98","pub":"0372820ca8fc7a193815e924dc1e7fd405afd0b03e39ed8cd01a33bdcd35f899c6","addr":"90b134c6bb272ff804b6117fc1d6f3dba538e3d8"},{"mnemonic":"grid street boss erosion spike bunker indicate erase path mixture inflict group","master":"c5063e2bcf9fea3164cc8bacdac300a35b0b1dccef63e1de233ab39356249b9d","seed":"2c98b2b7703e3cc2fbf089d78184f2cdfcabc7bf269ba3b57e7b033629fd149263063e3f08c0d7fd3a785ceeab1f9b2f7e383fd2dffd7d9e982e7342ec90ee64","priv":"b6082dee45243a3fcf3313715ee9a644bb95d550cf8f275a99930372bf265e59","pub":"0282b6a0a9dfbbe648db6afcb9596fed1c02b8d7264925c88ba7007cd5cecc10c1","addr":"e9e9b9eb2c9d88b080af25d6c5fbf425e86c8f9b"},{"mnemonic":"flock entire rent cricket shadow inhale organ pioneer pottery faculty west umbrella","master":"e1beb66b50360f8bf5253b40e1fae368fe8ce267dd992a951b06896ec8e44404","seed":"267dd95caf4834b42cc69941de4dbeb3b37321af83548c865efda2b3cf9eb983c8244dbe65af863f0c88d2e0bb530d7580a0641d23a2bb98c4b64ac4b38d84c9","priv":"b35f776a36af618b48658829c0a914f8ee193070fd9b88ab34f3b4c35197ea97","pub":"03e030c12765cdf97520be291bd25d0a34aefb295f7749904b9aaef1ece99cb3aa","addr":"5c842dfe540f09579539e1fa6e961f929a5b7b60"},{"mnemonic":"all hurt survey laundry follow earn car music online reopen boring monkey","master":"56a9ee4a3e11b98885540ffd3e639369e2124f9d9b7108894cdfcb154279921c","seed":"ad2252df70bfa330e6a7c48da592336d202ff2f91d1654d34e9139ab644d54a04f88f3664822aecf8565453b58ab77a6785e81ecd7156bd7d560ddbfecd8a287","priv":"4181c26d8062eb8cdd8464524bbd2d82b56f423ee8aff8fe49385ccf98130a4d","pub":"0336b154ca3bca67a440c55add8c0ec34bdda413d57e8488ec58402a61eb93f861","addr":"2de1dd6ffa17618df2f9361a427dfc9689d7df99"},{"mnemonic":"obvious spot fuel leaf company birth drill baby lucky oven since fringe","master":"c75aa6398d3568764b147d2a951f2a93a38ca76f3e380e0574f35a6a69d0967d","seed":"d2793c736f85dac48f03f67c39b2b943b297744268dfad708ce9eddb74c649515632a25468a3d444bd07a0b9c4c9d650ae8676737e8373edd1b0f672206d7b72","priv":"cc9cbdf4b34dfcafad90d774b31313b08c6861e6409d659ee77afb75a1ebfb86","pub":"0251043d6ed5e0325ed3d7cf2caa3db8eec2a63c4c5472421a37831e96fc5a2bb3","addr":"9f75fc6e07b3935e5e8f3a39fadba8252e10cb41"},{"mnemonic":"funny online improve knife crumble critic grain vessel wood inspire venture ostrich","master":"83a4036503ba3499d266352b5d7736d5a16519870f9cac08d4706bb3a57e5d7e","seed":"23ab1c440ecfdba702427c5024503232b28aca8de6cba59d7ee1e070e84a4ce15cfa84e06c84c9907fb6bdc9d73c94abff5ce5c4828da89631cf77a3b091cb7e","priv":"e7cff4b876f286e6a8181763e453faac2d92582b0f9caa41b5aad8235f79ee86","pub":"03f2a9ed2bcd20f9ab0b50a3ed8f7ecca7c172997cbc877a896dc9ac740ebe03ea","addr":"ef1badd2e02541f774b7ccfccf8f550a0da31f48"},{"mnemonic":"elevator scan glimpse immense shoe buyer punch tomato chuckle art catalog coach","master":"ce00293fa3230ba3fff5f53d163acb0a06bcebc77606c6c22166f29d4f84d290","seed":"e06c12a0d1f8bb93596839e0c3c566b5b59421226c1523cb54f86e93e391883486e86807472313115c366495a9973d34b2c7cefd919f0023bf2039e95f22ba72","priv":"94e11d645e24aa3653caecfa6cafb3404a6b107c076fa2fc03d3a2d3127c8e95","pub":"036ff6332fa0db2db68b6a74a68ba0eba2cdff43f896de3d4b3b0d26ad1017b608","addr":"82ea6dd1ca5f8bd08633e5b69cffd8dacbdc3993"},{"mnemonic":"emotion super skull trade tell drum lake scrap alley reopen true prosper","master":"8bd8b2834c0aae5a8a207a40ece04ebf9fec51892b8c75dc7e4dfb256fba3b6e","seed":"6d9fa2ef59c1cd981a97e8d3e788b8bfb9738ebb23561d2eb72fd3bf3741e90eaca1c4e821e711756ad8adfb3c5d355f55fa8f7a41ddf260a85288416228d257","priv":"5adc84e56a3d3e6b43e1d42d01f2c7ab1bc340cbf8ce99c30cd94323e1107d9a","pub":"029aecdc08e10d442234814770ddd891241afabbb088e7dfe41f6ee0edc30a7581","addr":"19ce22a905e023e40b9a090b750870bb4d220d4a"},{"mnemonic":"federal math bicycle copy diary bind clap dose clown fabric hover draft","master":"05e5ae86313b56b4083a77339441c22cac4d675f18089028b841e12d0be35480","seed":"bfc46d250c423dfd4f123a91d8c7d556d484f1b8091132cc6e288fffb4b786d721a87d93414f71fb87457ef7b4f17d65d751fa43d7d67523d95997e357141ce0","priv":"760e1221ff1a283d14bc3fef817244affa4787036a46d3009d53911bb873dd4d","pub":"03286bd104bff54d0d01837e72b47e1bb582c13c78311a73a08dcffdf5d5e6bb42","addr":"d03ae88abf654c466a93dc167be85b7d1d172e38"},{"mnemonic":"parrot poem unique trim auto april under pear brown flag critic ship","master":"438ae7958c45b13e2f2d275f52ef71e6ce20d00545051101fdb5be7e235d49d2","seed":"85ca4c5faa1bd0c0a3b74b8a9f5afcc0849be00a0d1e67222a7b70a9f6343c0c637843756750852dd6247d311ae14f581b642e5c3c4cfea3b689dd1c9d4dd18a","priv":"f725a96177c31ae08f065255578e34f58145b921267c2a2e26f09a3fe0d58e61","pub":"02fb792c0736e01eff225a1cfc6f56ccb8ce70fbbb9c050da326ee5475fde784df","addr":"d096954bbd94038190e6aa959ebb8e6d4c5cafc7"},{"mnemonic":"expand enough goose wrestle title hamster purpose illegal peace patch moon spin","master":"fcd43f2a177b9c6f19b22a5864b41a30e9e4ff29cffad7663a6d5e5574910a2e","seed":"0dcfb2c19f6b6b6560db73bcc164ff84e117fac8a11027b0c8c2caf5c97256961e019dc1ae14752af47abd7290cddcb8400084eb59b8ebe5fe1b148806c422ac","priv":"645c6babf5d7abdf9a111ce1ef7a860466b73c47d2afc83d5091265dec741fcf","pub":"039d7f9485265190c0986c0ea74c065beefaf0b8a567c2502c122139f4f7d0f834","addr":"9de7c6791416a501bc1b3dfa5940e4ede894bca3"},{"mnemonic":"property grow toilet hollow slogan pioneer gate fresh still notable happy peanut","master":"9e289e0abc03cfab28e00b885be5328d88886a24e71d88c120cfcf697e1573ff","seed":"3deae69499f305108ec27c7ac5e844140b59316a354d08a9571e671d5f71ed8a35e060b084deb4ac2f55c3968184f7b625246c5635e8ae85cb511ed87582a712","priv":"3765a9eaffda6c370a95ca1c2ecd178a5a7799034fed7d051a37f658e1db0fab","pub":"039bbdd61b3e1570f585fe38ef1ff516a4d1ea27c9d9a2b11775f9f462b5e1e764","addr":"c0a75bc9853ea8ff8070b22b5e6b22c57ca2e820"},{"mnemonic":"grape arena buddy shrug foot fiscal move transfer beach else alone city","master":"903560571ef0d4cc0fc20d79ff830f6cd360a1ff387bcd893b436b8d8cc4a4c4","seed":"6b232fcb4175b92836ad60e8cb9bdc82856d663558adad2fd001fb71db4eecc55d0a9b0cb62c938c8e699f0bd55f3e773080cb3804d74e4c7503420b2f0640e6","priv":"b693be937db9f0aafcf2b68b9c3ad8dff86d250f4d7c7ce0bee4fec7cc164035","pub":"034178d1a76406edcea9b3e501aa11161cdd14d6760769cbd0070862148192ed81","addr":"91379f6876f01696ede09b112da349125ae3db9f"},{"mnemonic":"spirit march luxury planet review rhythm mother food orphan inhale dinosaur ginger","master":"88b72d270aaad97e466b4c6cc2d5376e0bd9d5d4389bf1c5e5fe3cd60eda1cdc","seed":"ae53ffbf1695fe13e7590e3c0d225621f392ba5885387cc5ba1ddbdff13f83051293be338369236cd2cefb39682019b257a4766eef632cb2f805c226a611d5c4","priv":"8cd4d3c8a6a6a18eef4b30056d4c23908d100a30566ee7ed486f96831be8657f","pub":"030dbc527c5e03ce3a6ba9caf81c44f0dd0c0b0374617efa819a71319879027fef","addr":"345000ace68ff89bef2f2c197da7f50329c739a9"},{"mnemonic":"cause enact push shove account orchard grunt sausage mosquito deny relief sun","master":"d66d0216c675ef09072623aa75fd8a9df788af3cf26b16d38091ba5ec8cc8cb8","seed":"07d83a41e284788319bc0e5b9b7b1849485b2bdb8cf408843184f09b1dededf8ca56160aff2f6ed2e0559e0c005f5f0dab7b3e36500db5e45c55612091818f60","priv":"bcd7f078131f5644373c0e0ced2f33822c116df476cfab34c39dc9a8d5b9aec2","pub":"026c0d381a709b557135d33bd1760de196b604b5d720269ba4e8d749b7737da2e9","addr":"7e268fec12b43d71998eba89c8e0df3205c094d6"},{"mnemonic":"faint jelly paper blush cute hope project giraffe muffin strike pistol blood","master":"3e2eece9505cdbdd0e44e237a90a023837b45c6305c01802fa278d6690afe9bc","seed":"7ff4975b81e3165068c8b861a748013e93614bd56c4af844080373a3c60d0e763d5c934ed4d4941f195e97eaad4257eb55ef4842d43ae648ebadfb82421d5b7c","priv":"d2e9c0441d876bc0c189a109a564404e00e3a7540cb2f84095da70e38321adc2","pub":"02a49b4d38662800e8aadabc72fc7fd3ff080c9c9aef5cc3c3970d6411ca92d2f3","addr":"b0bfe3ee05d361865a65678fa612cc64ba633789"},{"mnemonic":"jazz ten exchange horn junior frog surface blur color pill bonus science","master":"037073838661b05747c80ed9a91ef9fc07db4f4b9a89c56a26a517d74615a83d","seed":"92333a0fcd8cc74457ded4de145027c19de4d04d4e791c0418092ff599869c5a0f7f585692c0de272362e6ef3a8d31fd793e83701f1aaf41a0355a818ec061d1","priv":"04cb6c660a8006068ae929e97db3b29cf55093f52bb7292d212774db7b6544a9","pub":"034a39172b568cbecfe119e7c751086392e0a6b8c5ffc755453596ed74a75bd1c0","addr":"bde2747790882434b15deea070cd36c696c73bbc"},{"mnemonic":"chair practice neglect hawk panic sponsor ritual bid sick fiction vendor defy","master":"1f908e1559b37dc8ffde2f89ca0dbba2202260f6a848461d75cdc8791f53a1f5","seed":"0fcf390d0c757b52a520a2fc8c30dc740b0c481adf1e17a6e8d445f355c3c266bad1671bcdba99fba9c69e473a294c5e3f6ac51027a1048987cd3dc7a52dd3e8","priv":"6444a8b09434528113de487508dc7e30cd184c3a9f52ce20b30c7b6f40d5a031","pub":"0344d47049e125a655b9dff7de696e72689ee478b8b4f13a0bcdc71df4737689d1","addr":"3ad17b540fa37171f21fb9d4cf6cc061008ce652"},{"mnemonic":"dilemma main solar balcony differ bring close popular couple educate hobby mule","master":"2a9a19b24310a9019114beb8d3222df214ff8eef4ce190e7017bae4e45861092","seed":"ed8bd81a4515d1c43c24d69aca3ceb065d0552b79ad01db75ad19c2af3cd23a6a213163f9db3743d3b2fab6bc166954b2285bead616d1a50f036bf144856e762","priv":"1c8c89946f2dee6c92348f5d82506ddd9065f83b2eb8f8d173cf9642b971a0c4","pub":"02855f225d510b6b0d64fa5abfc9639488358272957b9003b1bc697d474577c45b","addr":"df365a12508a519bdf095aa5979b93acf59681c4"},{"mnemonic":"sudden cattle enough output make code tonight matter reduce enjoy file prison","master":"ab474b0afda779ae957963eb8643db33d1f2d879a5ebc2a79b5d8f2f9946223f","seed":"f732b62445528f4d96e0c95b58c4459e8ab7528d47ec2a925e3f5515e1459c952abbfa40fa5cd7f8b7c2f059e3df2c2a5a3813b4c37e322c9f2c8f55e66ce3cc","priv":"5d5af8bd1921fe03619088250bd74a2a1f58bcac8158230c0cc0e7ad304790e8","pub":"03ce0673f40df25344d5f2d85a374d6d40b6ab5b8bddeb5f9e2adc9120e2242c17","addr":"a9f1d96cfeeeeb011efc76ac43d3d121a2e7195e"},{"mnemonic":"oblige broccoli transfer midnight display talk jazz wall fit harsh kick ahead","master":"b5e760adc086f5be87b58aeabc63d74d018aaf2f673205620685c4ec32776769","seed":"3fd39274348d2cf5ea5ab4239dfa66dc65b33a7f4975b25e334d26b67e32ccb4865599f9b4fddfe8cf8a2630cd5787ef0188371d1563c8b9880b33201bf259a4","priv":"5e9b5b2a5628a5a57510469db849aea45ee2989c929bb1fc06918736f115edf8","pub":"039e5e293c463f16d26fd845e92d4503e551013864e5682e1c28bc21072589baeb","addr":"a784eadc4951c1e92e63a83204473dd467f5d558"},{"mnemonic":"prosper must remove pulse wink rabbit shadow harbor equal twenty air muscle","master":"ad8244b4d4221944b73939b681b275f280e1a8d42fe6583f63740865dc6483bb","seed":"a3258a6176d098bc96dced14718524f05669cc6c9f3ba5680a56c8c80b83bf50f32345843aab72e13df9bd8727408ec114bdc0099902857ff1889bd94a3a1388","priv":"32fde5f62df796263bd40267e1d1573f73d86d2fc98076008a5ea46092f8d01b","pub":"03ac2d243cf6580c8c0bdfc091c8ef1afffca6aede2ba5375e149efd2db54c23f4","addr":"504cf87560e4ccf69ce6f81aa5b0b3af45ec2899"},{"mnemonic":"harbor focus scare envelope slow margin boss giraffe daughter mouse hazard step","master":"28831264a522026221c9739fd286152e1123809699955d06149f34a0157a667c","seed":"bdb6f459beb7d6627a96b920ea39dd34b38b21cf45bafe88b66823c5ff02babd02b40ce25a9ce7b4d04696294910a967858fca74b18a5cb46f8afe294ff8d56c","priv":"4834d0601e457f6903e3dc08b3168411c351ed97df34a0932ba19f7bcecafc4b","pub":"03ba2538c15c37b3e0969adeabb0e5e1d093170f7e352ce0696aeb9e5e36150295","addr":"a259af3663c6ed69b149c94f73dddf22e4c91442"},{"mnemonic":"elite magic excite apology sleep cable refuse carpet ethics fortune assault hazard","master":"384338593c8198935c4bd0ced828784a7a26797b5e68212f7b142d25c5e8bef3","seed":"4ad678a061c1fa3351872cc3451c1410f5506919afce9ed62e5dfb05e9be36471fb80a5a94312ab603ec397cdb8ccf9acf8ce405fe7b834c9b14eddc570d5411","priv":"d07f63e9ed19bf7c7f89a598727dabde42bbe0e4cbdfc0dd889f8b5c4998a023","pub":"03d5199768e4a175f47831e46382232c217d58e94aa99f5cfcf7e85887865d4da9","addr":"427a4855b7d2222cc2d54dccc2de0b225b09c315"},{"mnemonic":"awake robust situate increase salmon tell roof agent grunt wear license kitchen","master":"c30d435feb0cf93a3cebc4584e94e00ff40ee2950cb3053ef2f7832799bab885","seed":"b49401408240429ba30ebfb5d9afd6fb74e79971be6b9f76e3810b83ab1993958f2d9f9fb5b75dee68607a2510ad621968d384873d16b4a194c939ff1358a67b","priv":"def35e61e636973967024d7cf9ee2ab0c232348c70fa25b945d6d4a6f220b9ba","pub":"032255b26a5ab86ade14eb9acd3c97e774aebd710b00e81719d04d7dfaad37251f","addr":"aafe58c581f30d3a55de219c15724e2b26dd2c5b"},{"mnemonic":"host proud little want shoulder guess acoustic spin since slight myth detail","master":"200f4964bac08715f0dc5bc750261c71ab2c5e5b70c6e20bf748aed10c4e6ae2","seed":"3fd02e2249ce332bd4f4bd3d9c0ab61e169d0f0c011a826d072153001c6f093e7fddebc437bfd7b9dd60093686147e069c4ff3806124cfeb02501b807205c47f","priv":"005e6a885009202c44f2dfd911fbd495214b9c53d2305b52c6bd7c1a2efbbb17","pub":"03a99eeec3b673289bf785c9482ee94fd906f992dbc11b6e0624e0c98c6b9ddefc","addr":"57a1472c9d2e1d80bad1e84b1a88356d973cac1f"},{"mnemonic":"chimney organ announce town worth finger donate hint vehicle sniff defense famous","master":"8059f2264cbba67a9868b20e25cd6ea7d5ac2c77a86b5f36b9890560b8ac9d42","seed":"a2317e376ede3b6bfc464a993815e5b32c7e2d896b462a3f636cad9e3837f7b454cfd3ce17e221a5f46a8b38a8eca74f6f1508d376ac9ebdbd92d6603178e8f9","priv":"e8e7e337feed5b08f418d6757b0cebc3cd2e037fddf8ecb51b42c1f71d83bce1","pub":"033ccaccdda15edadbe824e3340c73e27303df9c1e40037d0108bb2dea87e84235","addr":"13ae50b4bb386c1c5360404f5f43a2dfd95e1967"},{"mnemonic":"wolf found absurd device rare desk average water excite ring chest version","master":"5dec910d707536db8776b138103e97ed8a34d75e89d79c3657320ad9bd064d6b","seed":"421737ab059b231f6bac2f012f4472ec7215f94a5c9f5cafeeb43bb03d8b936c39afe6a712530fad6a5e4bac736b7ca12e488b3c377faf58476e9e8fe4897829","priv":"17e9344eade9c62a67b5d72af06616bc455ae6f9aa03dd48432efa2a242356e7","pub":"03776634e0508958ca0a9cf4f15b038f544a4d2d0497674ac7a1deef315d80ba81","addr":"63fde94bb741395136727075993a876ea1e59336"},{"mnemonic":"disorder improve say diamond present elegant evoke latin lonely muffin main resist","master":"e8e118fdfad2b3eaaecb31ccdb8ef3ef04e904c543245766a7bbc365dbe37174","seed":"c32d703d39d06d3c61464db0345ffe546f020678149496ee357acb0e93f9575d39ed2309f46917f89a2a299f1704958806f65404ad80aacb295242a91c0f6a53","priv":"947651ee70f613036de219df6d42b78dd5d1504af999c5c2ac7cccc656f578ce","pub":"02e0ca79766b0cdbe0cca0c4d4647e9d82740a6db151f0ad56df0881a0799e56b5","addr":"dd0179f1d538a9c67a42ca0fbc262edd506842db"},{"mnemonic":"define lion input friend used deny obvious basic fantasy initial grit jaguar","master":"e749606fd4eed5b54a718207b0c44af3dc32dafdc192d6f26744fe02b1cee804","seed":"2f67dd5c538358009d036e68d2205254ef898826613d01617abfdc83deca452603008226dcf4569f3faa21a18ba72e3f22ba0beedfc89888701ea2005be93912","priv":"59321cf870be317e697723d132c9f52b20ab43a84efa0f53d3af3b2e1bb075f9","pub":"02e681a3823e20e1482ae8888dd3fd54bf8b9843c1e480d36e72f6ec8f9311ef7a","addr":"c13389a74d1657b472efdd2fecfe736872952513"},{"mnemonic":"caution unable glue tissue toast august decide leisure foster session position match","master":"a0ae79723ea7b60a8234be8bae9acd64bad5472f789c7b8854d95862ffc441dd","seed":"9e1e3a5e11633be7f211cf442cf66b9350f2f4d84829ebe6da491e7749f2a9e6a3656feb5edd3584b723a9c4edbe1f2f530d4360f55bb1d32abe8a82d7383204","priv":"b2a560b474971b2ed48e47c0a27858b70c4485256ec288849a97be5d5eae26c5","pub":"03fe1ac82b75d9ce75fec2839d343954429207d4ffd7ad0e037c2bfe50d7f8c68f","addr":"85bf34297752337da3c79c124508daeab88faa11"},{"mnemonic":"pull drive tired success sorry raise top ship visual filter tag upon","master":"e5b018ed831659613748160d29f704367c0933b09ee12a8582f36ebac586ae78","seed":"1bcc9ff7923777f97fbcc49e5653ce6a7397668eb7b08aad407c77b5f7ddcc62323d8a566c15b51dd6032a57be69054c1273dd50e2c0698e42595258cdd05e7c","priv":"1a859101a7582121828f09eb02de30f34f6e1cda405cb36fda0279b25e1ffda7","pub":"028e0aafb274dcd1f7f8154bb6f1a6ee6207f69d8d7720c96a0d73e2fb2277f92b","addr":"ef934026abefbf19a96bab8f59b9f048ba4c14a1"},{"mnemonic":"grant enroll monster verb voice bench when certain kingdom nuclear save stem","master":"e8221f0b15c9ec7cac1bf373219481d9952b907ee29914d4506d079ae99ec17d","seed":"158737e586b7d0515efcf931d780a88fe0dbf150133a9f605bfa9c4f0df1b7d1c4f56f9745fe76b51640d45735b91e2a6391e3a53f1200824d58ea8cd9bf25ee","priv":"cb61489db37dc70695fdfd54887dcb61f17ba29925d6267f10999ef088acc11c","pub":"0272502a28dfa3e7ebef4c97ee7ee9817756e84733c1030a94820db6d25c82fb97","addr":"d941f06898ddb082c3f8dcdac5a455ba88be2dab"},{"mnemonic":"shrimp forward swarm olive laundry team fashion run tiger atom guitar blush","master":"e726598bbe78396d7d21a334ad1ddfb95285f72e5c6f015f6d76d7b018a8486f","seed":"7f59fa24106d19a2fc887bfdbd01f1f0c2e037869cdeddc6543354a29952785a31146ae4de6d7ceec9ea95df088dda0f195d491d8be3a6ff63bd427532a1d979","priv":"1bcf9039d65d76bac2b14698585db46cefc7de88f2724118dbf1b0597bea6960","pub":"021b8a68d6c12165a3c11dd81c93edcae4437c983751e8c2a4dc509f2e3bd4d400","addr":"9be822a10983a2c398dd72cb43eab3dcc2ee30f6"},{"mnemonic":"object lava wise decorate donate panther chicken enforce hood donkey lock better","master":"f2e88ff11892f72f22627d7cc7048909ff7403a121a23ebd9744a9017a013adb","seed":"9b7eef532cce30af1499362b675c2b6c3e6333f672c102d41459152f380661115461b1dee3613ee5be55beed081d1655b70d941e819754de304beed5269c5fc9","priv":"e19e47c990399d9bb11760b2b00847fe8b85d7a73c5c4fd99414ac37822b5ed6","pub":"02d0840b212aa20d204c8946877da8d6307b50c890a463a123d7eeaf877811f998","addr":"b85c15ec5abcbbb0991c18fbc788af88ff36e66d"},{"mnemonic":"blade reward angle predict text salad auto drum alert grace valve dove","master":"935ad9d81bdf740c8cec1414d56cba9a807d0d47d39b0d9169027cfa38491fd0","seed":"7888677a5dbd757788a5fa116a954610d3234aed529b85cce2bbc34413db5b7fa4b25ae8d9f4bbe367ac55b0dca61724399f70e5404e346506ea2e5708269639","priv":"a6f5a6d090cfb99f935d72d79e77d00c7eaac00b9d23ac1a4aacd6289fdd4604","pub":"0308cd34578b15b3f459d9c0507830af364ed359f27c1135ec0dce2fb9d256b65a","addr":"f05e198f7feacf7a2fdb37f598137f27dfbfafa3"},{"mnemonic":"icon aunt fiscal day never reflect rapid scatter exist fit prosper what","master":"9bf8057a5a94ecd164969fa719a846494e7fb8f40d6571ff0f021940bdb5567e","seed":"0532364343a12a5b821d7cb9c88317dbf802d8b3f24359b49ff32d79882f89f489a4f1f63e4c52ef1ba92a3789e971d56f056b39cc9b0821b3570ececeee9c3f","priv":"0b204e7b6e74dbf35602dd6914458af9860593d672f3409ceb133e431b3f6cc2","pub":"03d5efdd40e97200646f202db82895e2bbe0c16f2cb29bff1622169787433ffa56","addr":"472be066059dfe1d34abb3564037b0149137ff75"},{"mnemonic":"mass wing office match couch tent tumble rug beach mass october already","master":"1b63074ed73326c5629aa6bb9863f1a3cc2369f50f05aa1281d6b208a787adc5","seed":"8e96902f01dbbb458201370b5524fda040322026f83c8f77bc2e91e843ce6b63581b979f71368038e81aa627e3a10897692c1a215fe27a446ac914f043ff8f75","priv":"bf5a466ca37a2c297ba1ee4ff4ff26d62ff44b98b02a5713fc4b2f7427ce9e99","pub":"02827ec005329241a597b6c7faa5e92a0624179425549777ff922482d2a1f48d04","addr":"67f3445c15a8f34a0a5d374acfabc072c3fdf74b"},{"mnemonic":"lottery skull bleak sand drum domain rice eight card frown world much","master":"8a09b9b68f5f87795c60d6dc08146a2780f410f44560f4519194eb1dc6ed26be","seed":"f2dc56a6fc9f382d54b3d92785724815c9b78866ad586448cd9ca06e59d713dc136f41425b16b28d45ce094d3f817aed13bda99e73659a77c06064a1fc123d07","priv":"09b6ccac9c9109ada552b0982202838b3c1e53a816748176c2a3f6c04681300d","pub":"028211fce683bfffa2067cca19d0e003e9e86a066b40db4e16756723cbb525c042","addr":"9853d04f14981533312e56c75a32f10e98d543f8"},{"mnemonic":"advance poet beach endless idle castle inherit jaguar wife grief frequent wide","master":"c16f77a5a5931add45a26fb906cbffd87c7e5ef3d146b83df93e5a3d5b9ca9ef","seed":"26b3842ad77946bb585a05ef148b8ebde2994c800d30224adc7dc1110a4605c02a6651d30709f5f8c0a532c6976504344887bff1503e6afb6cb8b1ae0f909f66","priv":"58a69857570ddabf8a5454e97655e1a833194b64ec4421befe3e0d9e45ffe97a","pub":"033a877e03d2b871bb879b53196da3ca45459485eb38eac76e938c62979d23a1de","addr":"0bf6320bffe291c8f1c0676ed864232cc84b4e57"},{"mnemonic":"stove tennis wait major grass network mountain before inhale glare bird moon","master":"b1bb7df0cf5b8143e91787646825f92d175664fe68751c114824d5a374850672","seed":"73f5867400033e088b346620983d128294338a0988a8b4282999a2a960a26caa12686db680247520196fa9a1e34901841d999b4fdad40aee63834dab615cdf43","priv":"37af5d2736154cfef5c59e974f1954e541683331de3555976a9e9efffb7c960f","pub":"032c5fdf3604c6ef170e65007bdb75ded577aae6652f099ee41d4ecfd1020cc065","addr":"7ef3d9bcee0b3e3d131fab4dd7f79d6dad548889"},{"mnemonic":"sting nut gasp like spread sponsor march behave zoo vanish noble dirt","master":"9f74f4075e987922ac30b7f5f43bada33f0dd385a4a30a1ff42718fd43f76c93","seed":"4d6e6b8a41454924355067b754e619b663ea585f305482febb6db99d26d62fd1a1a5441b7fa1d02de242f0dd35c965ed62fb0d9bc7a857ba257dec94ce462a9c","priv":"53afc4f00fe2a5003c77e92b4d0837d7c8fc54b4ec1e76e0434ef38aa3712850","pub":"020f710a1596997eb3a95815ef79efb5a7204d3bc5fcff171e067f4c6b3692f5e1","addr":"f41ded9fb4ec7cae1a9e8aaaec7de6309644a2c8"},{"mnemonic":"tent trumpet jungle into loop target myth analyst symbol ask december rural","master":"3a8fc48e8e08afe8b32bc8e9c25ada84feb1b84922ea10135a590927eed2b3be","seed":"7c9d5d2681c85e71d49392aeb0502fee5643e8a6ed60c4b84bcc202a5bada19a99dad7f88e365abb6cce65985117d642ca1ae4733a0863e1cd15fad4edd1e8e0","priv":"56b266ef3f1a45b33ea1465c15dc6ec5779289522c8b2b6588c8cf2c182d2fbe","pub":"0206b8e7a5350358fd35bbf173d9ce5b0ec91ee8c710837b9198b5d5ef327a11e6","addr":"fb059b5167a4fb3bb07c0b3b3516bd6fc84f66c5"},{"mnemonic":"juice barely airport rigid miracle afraid funny combine address guard omit idle","master":"787086d46e0777b03c3774933f35e4fe65b4ff069de5ca9b09cb84caff915ddb","seed":"ed6db1f257a45468761be9dd26ce88f78ed7ed1c488e4affb3a8f8ff8550602848ba2fa284c930cd387188ec4f057c6865964ca93bd181bda40e4059c4fc4d28","priv":"9d6f46f7c329d6e57b2ae84150c23c983bab43e7e6ad7190bc95dbeac977c617","pub":"03ec60e506de8acf2a518ce07e3394421450db339cdb6b91ca52924b1e1c3afe22","addr":"0a4359701fca7026cfb2d196df28e34337a34960"},{"mnemonic":"uniform enter number remove obey arrive print version cake alcohol swallow mistake","master":"047c71cb3066ee3fc151a4dd961a06595d63b393c54e77c756966fbca8a749bb","seed":"3db076729af5e872e92581e3c8d8812b60dbe4ed85a59f034fed43c9c4e0015fc4363643dc8ee5ade53ddf68af54b3d63d6bd79457eba414f45bb0c809e90af7","priv":"557c62286ae6440a2a0b17ea98dbb4992333093a054b59a37345a61de1b871b8","pub":"03ad3f7e2e2279b486c88e7e12d2a97a3860aa31a3854987853a1d73cde6aa734d","addr":"ff0a8d5fca9824e71cdf434cd868c12957fc61c9"},{"mnemonic":"split lecture predict rich inflict flush bike sound credit girl pudding ridge","master":"12fb50c5a687fa1552f07cc9b56d6f5ecb7b68376c3cdae621190494ea279f9e","seed":"29d6e5b0c2cbb22e6048158990f14be89c6c2416b36761c2f4d4de70a3dee2c7f9e86bf6dcfb07e99ac1d15f66f7393fc48b00195b0981f0699652a9f3f0c340","priv":"b02635341dd14b0b5e701222337dce09c3426a6f80370b06dabc31c417d9cd2b","pub":"0365f2fe5611808dd6fcaea62ad335d9b992d1b8f91333d6dc7b96c0b3ac97b209","addr":"ee3da08bcfb0e2fd4331e8b1ea3c0905c6c2f005"},{"mnemonic":"fiscal deer minor dwarf measure goat enrich emerge act view cancel shrug","master":"4cb7b43c2efcc7f6e6d84d5b47ca352ff8aa3c1c44fd8d2de7dc75b3fcb310b5","seed":"f48a89c3f2dc87ad41069c06d0b8751881c993c5895cb548b06974194cb410122d1268a9f962790ca461e875148cba07c216439df21bb37a06600456f5bba35a","priv":"b77f4a13edd7f5ae33725c340b1f8982fd02829ba2756d70f4086dc4a38a5d21","pub":"029844babe3ab249b969895b2b0c6d3cf7a79104721e96ea3b24784a4593fcb7e1","addr":"20a6d611a9ea918d6697d2e09900cf4fc9f676c5"},{"mnemonic":"expect speak gasp outside word glue fluid neutral casual train left mountain","master":"a774f13c1b5a22667ed1d3954ef64f9ddf3f841890b894660bb291745f8c5d23","seed":"7e8078aab4d3b5d121cb17213ee1a06fe4b0ec7d95dbfccab17cd0cae6917151197385c2f75dfecc7221ad518d5899384c22d2641a66250dc581096ff5326a6c","priv":"663b4bbe218e2f6efaa30e02460985ec708e76abd845ca365de83d2bcf547680","pub":"02b78aee27b6c719f89f3f21c55e8c34b9b83e94864c894188a7e39c348622e5c2","addr":"1c716ff8774a14f48623598e80fed3877d974bed"},{"mnemonic":"grace clinic host vehicle drastic april sibling response laptop escape creek neglect","master":"0f2dd943aef0644bf150f38baddc31c3c2a95b813c1fd893ef936f36c6972aec","seed":"e21b62815782f3954ef2be4e9551f7ba47d6f471b566d3b9db6a07d29b42c2edd10e500c7e701ba60963315f21afc2a4ea0d4c187fe4e08f775d3439279572b1","priv":"df825cb149c95352cf0bb17fb8b12cb686ca246c76f7bdfd8ae4633fa18ec30c","pub":"029bb63c2664225dab9c6a93294891127728b77e7d9a9a8e187531f5f154ad36ac","addr":"55266b5a04683c1d61e2cbcf4180d7087550c9f1"},{"mnemonic":"neither help draw cup grief hood swing task okay wasp angle sweet","master":"5a89607cd2cdd7717fc0918d92e661dc7960b5f92a7083482079468afae827db","seed":"8a1d0d7f2799cf70744d682e734352e2330494cc309b2bf785cfe799f004b67c936f3987f75954e18f4eb3adece8e2a3c57ae24b3c8f747884f473cfdb671112","priv":"30a055fcbb2c88fd87963e2ed60117cdf5a82979a7829238f5093f0c27fd7380","pub":"02181e5dacd8408db30a736957d7b19448d5925417e4d38d487391dcdfb8ac4dab","addr":"9ee3469dbceacd60c741f1530646f7550b94be6c"},{"mnemonic":"fall laugh virtual service grit left clip betray wise correct walnut online","master":"7c11681ada91e9349c1e062d0036a29290bcf0bc1564428f7080ee0b81fc5a0c","seed":"c2ab87d2eab816dd1b81ae4acea81e034f2a7cd2cf7103ad3985e739d696248dc0cbc6ff2864e598ae736b58c6ac4f3898f1ddb7eff76413fa1383a63f6c7716","priv":"13edbf55d44ea6951f3825d67c2486a96030bc58ba15d282df4061a0d644a2a0","pub":"0386590dcb32fd11ada507c55069b5607182a1db6ec02c810c79668a27d60411be","addr":"71bdce836bd62d85f5a53f9fcfe2310d40bacc56"},{"mnemonic":"hedgehog light govern fruit season cousin shy tumble maple promote feature lonely","master":"f4575fea61d7539101b4f89674218bf8fb206563cd07d729a834bd7cd8e3cc62","seed":"147de64775c5b285b09b2f846212750577cd9cf77bdc64f198da75003dfbda9c9dc742bf9ef1de8390641ddf9b03db8958cea480e5b4660236e29ef5d2d6a6a1","priv":"9ce717cacb307400d04739f7431fbf02cdaa3ae9035e00e8a31d03d6cf7e193d","pub":"031b6e5958fd3a5883f0cff00cd6dd14ac6cd4d92611e97c4cdd751d76323ffe0c","addr":"775cfbe90a93b73c27172b699506e4b40020a47d"},{"mnemonic":"normal tuna cry human world wonder suit tribe company pink weird unable","master":"834e035154ca70f5719e0df0dea3581a2ea19c4f9c4f7e1348810e0a47eaaf81","seed":"c1682262a9bb26399355c5a226abf198db50fd6891e48afd60094127db569a3306b5e556fc166907a4ef90c80069d9c0027b74532491ca54560f7a85ee1c2934","priv":"035c6aa4e2ae3ca2d2a356112809945b068a21a4c3a448819d8b29ce406423f1","pub":"02a18ee68f4c04f7c9698d484b9e87a672f05ecb87d127746b67f3caa820406285","addr":"b6f3c63322c96f7cd1bc13195acd2a9485b45232"},{"mnemonic":"school kitten swap accuse vivid spirit team verb border write boss barely","master":"b97687333b05ee2da13ce7c5d488aa076a1cd16c8b21f43e38eb0606fa3887cc","seed":"7a770e511a21a4712fbb40f9cfbab467a97e5165e89f70b27dfc8bf5a6a69fcd8658bb6527d0203e93ac549a89dad65068f06e8699cc9748e6448eb8faafa2fd","priv":"de3f7ccc0001822d6320b5ccf27dd38dfdea7ba8fb5c73afe8b6f71982b06eb1","pub":"029d4b9f7e55bc7fa1e84f403a19bcff9eb9a9afb873476b082374e19d3e7c6589","addr":"2cff960c82af319d91e2b1fed8171fe04d47a491"},{"mnemonic":"banner lecture vacuum metal clutch return maid furnace beef armor excuse mother","master":"e944b1515fcab7dd33ccb6c027535d3e4d5db2798809fa6e9317587a1a9f8a07","seed":"6089209e2ba24a756beb9a5946df522adc87d9d98dab2c528d5469bb35ca2da36662d661b0daf50695322dab3578a5bc3cdd918a7097c0a10bca063568abe8a1","priv":"c0b5d1c2ba77450237956cccc68a162c2e32c62e662a0bcbc7e27f2ffa24743a","pub":"02b52a9589c4a631aeee16e8ce808a2c20c63134407bddd7986a517ecd46f6f1c7","addr":"d79746b3b45903cdefbfc4146489ea550bf9361d"},{"mnemonic":"lottery uncover blood that bench peace raccoon define scale fault erupt bean","master":"faee8490c1b9b5e79da43146bf8697b1aac582410ceccf66d1fa54a8b4e8c1aa","seed":"cb558b5816b5a3ec5d63468859b71f9d2b5c4b7ad07bc00e5e4e3dfeceb12fce337cf1acd97af6f5b8d9277cda0197dbac16c9700fd41df33d9d470cdb35e545","priv":"1f77e09b423c423043b8c41b93060c9e795b6b0e05ef0fe75eae4a53abdac019","pub":"022a4a7f860dc1ecb21faa1f827907b01b87a552f8cb0a085af3a6a0758d922390","addr":"7566766fb425c0d00ad475dcdca95e94b17faae6"},{"mnemonic":"bounce someone uniform blush plastic edge bachelor tenant office report lounge brick","master":"8766a5c2858ac393f9e73c6d842184953eb0806304fdcbccc43916ba70ce8924","seed":"cb6a680c6044a9bd171e97e38f4933a86f94a643a398e54ed042cb7d2039e11287876ec24794a0a078398e14cf471ec6357d02c83009eacbc377cf77385834a0","priv":"a5f252e60b69ac73744b617924ea8158b93d4dbdc2cba19db4506b86d413f6cc","pub":"038d3945d243fd90ab18ce1353e36b3c07143dcce74ae9670fc8e0ee12a2fd01a8","addr":"b184c47600390fb017cf60d2b5c89c28f72d64b1"},{"mnemonic":"alley wide siren matrix cigar paddle spin fame receive cave student tree","master":"2cacce92a105ed6a199a6d881ad7a43a7faa74f967b4e8330a55b263102fbd8e","seed":"c67bddd95507e4a9f9153f7da3de4e5951c53750a5842f11192328994742669c32cc61ed14139ddb72365ec7065436583b360ce6e2aee5c196beaab9b10e9991","priv":"f6dc107f30701827bf1f83113ea3853017e384d6995205dc9fd23176e802ef4d","pub":"02c3dc3ea3727f6f351a12d3f5b3fa52beb25ddcb5ec397042aea4e646d9aee6af","addr":"5ef50803371d9c915ddeee096f7131461323c489"},{"mnemonic":"pipe brisk focus nurse rare arrow seek spike guess enough unlock transfer","master":"ad585f1ab0b6e5f8d224fee37b6c3d1fdab1e6c757ea93a9df059a36b3f96646","seed":"5b76d0f7fa0ed23b52ec73d65d109d7026f7cc4c207988c6a003a142f3e6201fb1770f8e662fa8cf4acfc0f23e0620bf2f7b139fa9d8d71e5a3c5b5c2ab75e68","priv":"dfd55ba52a10f26aad26e7532f6631986acb0247fadb1b86c45ff9537924e42c","pub":"036bfbb102ab379a9dea1cc63dba5944b22d48a941a0d1e534170cca9a53d3fb0e","addr":"af337ff42bf6280f7e518df5f4f064a84fe209fe"},{"mnemonic":"coast opinion view orbit knife december pepper elbow boss junior wreck escape","master":"4eecc11aef13009bdfc444037aa185585c147be182442a33459b5a07b61aa555","seed":"f543bbe5ed92b75d06089c2335fd22db68f41e499634760dafaa6661e23178e7d075b2f8aa3630aa528ed77d85737601d041278d182458ae28c04420ddc25b5d","priv":"0fee3e3e025dc742e5a95f41f2e2c84d94bc8cf068bdc67db76e0378c1ff01af","pub":"03e58501a3f5052e4b7b1a4bb264c5f5a61d60c542a761a015606ffbf97f63c10d","addr":"c51fc7f607bb0e1cdba35f503f3e397346148784"},{"mnemonic":"indoor dinner fantasy cup move solve pride dust cross note raw balcony","master":"6346159218b27d00feda5a8fd63349956636147e058d9eafd60bd94bcd18efce","seed":"1c39176421e5c49e7fb6257ae70dd7d1ec60b3e2a1a4523bc4aec59b040708f0e48099520c0ae4de467da994082c82e0db6f1445c159f625559adefa55c7ce8d","priv":"74d7f00b88798ba5190b71e59dcc4bd7f2cb11e93669d7ba0372f4155308b947","pub":"03a07ad498d80dc84ce120f5518a541b5310e50bcbf0c669455c8ce2a0eb13e253","addr":"277346e420f814e9bb1a8ab16b11af318bd78d4a"},{"mnemonic":"please neither sister wrap comfort omit stamp roast lunch steel night report","master":"1f0fb7b99b38b57321f40b4327cc38f7c41c5688a478e4be908353df70477fcc","seed":"6d383d1ab8febb2334354e9e5261d6d4797bee2e6b9242521d59d22f982525ca87141e713b32cd60b6aea587caca213d8e0524c1d55cb209a6d06f607d7b74d2","priv":"95236694952fae12a92d15ca17c54cdfbd234109aadf6c295bf664115cc35a27","pub":"02f29a1a01ba6702e3a441386986ab5ef7227532704cbcfa08f2339c5273fe5f7e","addr":"048f26f774131d92ca52228106fe61d12e7d28c1"},{"mnemonic":"lawsuit trip betray slam tornado polar demise appear east dose produce market","master":"8e659f66e4dcd50dc7ba617e17e4dc45c75fe957b656039a73f3583944b16ac1","seed":"d982fe48080c3bee97fe1ae2ffdc0c5ff2445817d28b30bccd6f89bee138ef1e9828b04fd99cd70512cc8d0e58010ecd7c4460c0b2614211e7ebd8acd27d2061","priv":"4d053df57043c403659a370f486e8ebfd60fa2804430a6b97d95ecfde846d63c","pub":"035001c721d157c1af6dfa4d1de23852ba2d9be1133f30628588c5d9ec890a7662","addr":"bbd41b5af33ef8bd075e93a01f5377d486ddc475"},{"mnemonic":"hen build sand sister borrow victory syrup scrap rack aerobic shoot pole","master":"a4f3bc4a89dd86f38c5908d229f58a57c11f4a3d6872a0fd448043a6a214f938","seed":"3823745cd7589411813362179d13b2d2e1cb65bad1d53f34d512c349215e3cd5bef97ed86faf0096d2cfd5dd75556bdcbac1ac385c9caa9f928a19cb926082e3","priv":"5c14903308d7a83b6570ad2cbcffa3953b458572a72c3d5148a79a494fd90cf5","pub":"03b18bbcb61fe68f733542afa7c4c02214c8980ae4212caf818a8febce1166aeb2","addr":"fd5a9ed68124fee88f30a8d7f19e65e5ee47e681"},{"mnemonic":"chest hard axis own found relax skull bus frown distance gauge angle","master":"6eda34ed25b73c45cc0465aed51577fd35c45ef7e8d8e137c621c5bd6a726888","seed":"fd71ceb91c1c0c2176d7c75ef17010fca12beafc5a54feb3408a69461e1cbf1ad0421da9f31532aeb1f32ee6503899eb0e20fac3756d5c1d9fb23fa2738605c3","priv":"7ee2eab961362c9fb48f0cec5f63d1bfb0b38e819ae3fc1a4a3c6fe6d4d35725","pub":"03131e751282bed411e12a03c7b2ae4ba4c8f81fe5e62f3d40bba09ed7ff099509","addr":"f8a2d049f67222d673df66844d4355ca77a34db5"},{"mnemonic":"large merry tray craft fat clip album company nation tent increase armor","master":"c442b107b26f9c853ef65260fe813449152c2fc93d28774824153cfb4d67e1c2","seed":"bcdce56a81179b6fb0224a34b26583b1d1dc1d24a06bdeae60eb578df673d4d9ab5d8d639c494fcc024a945284be11ff55dd88d2470bb3740b3046155818a7ba","priv":"f359be0bbc26a121997cf2b6678b41c08d6815a5903c184c7743464e287e8557","pub":"032641e977e838507e61d0e85b1a2ff16f0b8d8a351f7958ea615bc2a8723cf1d0","addr":"924690289cc78854d75ddbcb2b06b241404fea7a"},{"mnemonic":"carry pipe make glory famous word shoot artwork ostrich slice blossom episode","master":"f6ad202d1f7acfe41ce8f97c809d0f8ab9c7959866c5a435faa9d551e98d921d","seed":"5b956478a0cf11e9e0bebfd97b3ca56a6cfd8499843d21f95a2ed58db8abb7b06c672e713a556c35258fba0533721cdeb38313565c8edbaedb17dbc1c8396a6b","priv":"0bf855554127bbd03b3779577449c37dfb82ca4457adaa0edf26f1e5e5d7ee27","pub":"03452b2268005ebdce5fb467e4ee5376624cb0dab31704c4725796dc68561b6f92","addr":"ce486d831a5c2e1b95a254c13393e50bea0cea66"},{"mnemonic":"inject more grid coach cause inner ordinary crucial mouse access attitude upgrade","master":"6556ec1bca4ce356846f9ad603e8b2e9a1ced7e2f875bb6330bac32baba3e820","seed":"c5248835bc868983d65e6009b983ec48b262a0da70dc66ba76cb167b9618730ff79b9da8e2321731b55ff63b8cfc8a2b59aa435146b5d2a21b8608bc14808bcb","priv":"3b783218c59cd664b88380619db7a4bfb4b3343fbf38d0a576849c60cb4eae41","pub":"038f88cb7546e49c3dec3d356b0bc70be0716a1b146c641447326aa077d91d055b","addr":"09e570c6a4c7439d6272bfd611dfe723d2fb632b"},{"mnemonic":"viable material flock borrow pear cup barrel fire exclude vintage economy force","master":"ed54a092853793849e78e0c42ef95242414a2dfaffc92d6b7c25efa46715e23a","seed":"013530be872ace250a72aabb73add7e4cc4568da3aac9447c094c49663be2cb6bbdc1fded3bffd41109eb14cf1e8ee48aa65da60166962aff17451bc86dc9bf9","priv":"669218899eadcca8823c6c10476cd25fe546f918495590051f8d45debeae3cf4","pub":"03f54a4a58259314bea899e9f6126305d13afc7e8de6b346e95934358b524a5b4b","addr":"b38f1873c88ab12cb5c839ab1e70639538b331a5"},{"mnemonic":"injury expose attend toward air brain carry neither amazing symptom number name","master":"769158e4432add662ca03b558828568f25369b5fff971076f7a303b8c89bb3f6","seed":"827d52b757b28ecee8ddbc402de54ed6911dfdf19abd00739766f70fb688f47575da03177ce2610263013c2d22e3ca7556c5aa134f74b8faf61dcfba1a4d5ee9","priv":"2d276c19d260ba43e8de8e4b982bb21e16f52b5c8e231cfb6bf71901a9137c62","pub":"0310fe6ba12f805a118c9052ba2cd3218418217e1e48da3daa5887bed6b2fe9bbf","addr":"0ca37f96efe4af7507cf85213a2aecd7dddfb51b"},{"mnemonic":"seat other color road pulse melody error hire scene lamp best analyst","master":"c4e172dcd2a54bbfd30fdea8363eb10b9f0bbdd0d1ff3d33ad3eb01e820d417b","seed":"32d43e6b794040093d6348fc46a452a8733e49a66a06cc8ed2045359c881630531e282ddd70a4d630a3ee69821764b45ab949650d4276a925cad0c3121c31074","priv":"828b3cddb3d902d31386264f84bc54d3574325f56df7d4e8e06b2145d60a0de1","pub":"0275e251466e97a728d0ab4527e04031e315de4d03d9cee50b5b52210fb697a9a9","addr":"c0e6ac260e64b92beed9f4370cb006e2697dea6b"},{"mnemonic":"tonight nature salute state carpet sad zero heart limit skill vehicle elephant","master":"7f116fc76af767fab661d90b8ce20b51cf5d0727ece353410e06409d79ebaea3","seed":"226457053ec313b3368e877c76f9f8a2cd5a7dbde6cfe91de075974f42f994d195f056d20802fef8bef78cdd49c6383e95933eb2517cde2bf353872a13d87da7","priv":"1f069518222310563fa736833f06041805cc0a9ada1ab2b704e85ad91b980ef5","pub":"0221fd13bb9d0177d081c7cc6b9012b0494ccc42ed79ffdcb2409c252f42b66b9f","addr":"401f8cd411f3c5475482430cd0c480ed383e8455"},{"mnemonic":"window awesome survey swear neutral tackle essence elephant weird emerge gesture click","master":"ffb27c19b7d6241a29a08c54605f0408d7de2af078a3eabde97ba6e973b9c31a","seed":"29aaedc60b8cdaeb799707830413942cac78b57c0fa1a4cae0542411a81efeb36d7e48e222f90b6d42bcae97202772d687c226a13143a9541b0d7a3bf7dbe600","priv":"68ab3dca6b53b32bfe8a1b2d428332415b6278cd258fecd927f9d8b371075789","pub":"0234cb69b2f76362ff4ff138f81499d5c2e0a1912fa47098c0d826f98f1be4facb","addr":"54637f8b0f2dad74bb46e7745d1957bb8b16f4fd"},{"mnemonic":"island pact measure trigger frost flee tape napkin wide kick select sense","master":"013a5ecc8a93bac063e18e79f5654cf0881e8c39fa43c467a8aad833b6a7ea76","seed":"19cee1ab2babcd2cc5cb4bc34acb350deaf24b997d603814a5509374a2f60ba133f498a20a9066cba31b4903a6c9da661dd459343004f69b2dc78ded2dde67d5","priv":"16b0960d535046bc5b95e335cd0326d0b0a902a3c81f70490453f75154a05e8a","pub":"03e6198bef79e7bbe034d1786e47f00fd53aa3132318ed99fef38b6f46bbdd9109","addr":"199fb6c909420f711c3b452df497d03da191911c"},{"mnemonic":"before shed sweet will sunset rapid color tattoo winter foil spring orchard","master":"29289b59bf6ad91e0f9b24900803f57d08b45194782e76102f5377c142c17f65","seed":"7b721e94ae18b7666bf293bdb8eaffd70c6bbd2c2ddc582a0939100f1f131009752be6759491e0006cfc424f88efd97868132fa2e6bee0b05a520c881c632951","priv":"f6d7fbb1fa8957d132b1d43414b0664cbc25020055c35635a5ae005e86e40767","pub":"0368c1403ed0df7c1f9faa90fcd60937094cc975d1ab5bc7a9eb03bdfe764dcb7e","addr":"6657bcebfa3816af66b1a0a92f8269cd3f515fe3"},{"mnemonic":"view forget toss steel right echo life candy fine unhappy document pulp","master":"5c6355a65617952bc05b16623992e81daf07695ee5cd3d9bb2b8fa600ffb2576","seed":"20909264d02b6b88a472678b6d457850ce4f67a228a4f6ad7f45be104029ecb68f25075f30680416e0e43469452ad903a1e7b0486932d0dea4b1c5f56b21406f","priv":"4495c90b188f706dbe1106966e49745c49676e5c54f78176eac166629a4c0815","pub":"03b828ccb3f9f1766cf1d1c1c57e8e5c9c96936adbcac4a8ea47b0a7e3139c5771","addr":"4a382d15c13a06adbf075cd847ae9e80dbdf4ca3"},{"mnemonic":"fetch planet injury lecture myth goat drill sea reflect tattoo story rival","master":"3725eab28e9f4275bf2dd2dd5a94aa550688b8d111798185383a58088d6f8b56","seed":"0d42a4096e20202bcaa4d1939ce86cc6975092d2e6081c149b374f3dbd6cda81188c442e1cc7b67032fee9effda37e20da0d809f0d969977ad2c547e9a075224","priv":"7abbbf9aa4375ec489d3ad3ef6041e9e371f4582eec1ed753f9d7de3b4fcb57a","pub":"0371b9cf4994f36ac2b5117a2daf84d7c072f63e51d9f7c5e547548bc2ce51a16f","addr":"d59315e071460c09d108bfa31e05cf37545b19d6"},{"mnemonic":"close raw empty danger educate metal vendor coil observe response scene army","master":"da1ffa0441ba19153f0f98af4092dbe68eb5ffc9d82823710dde6654684e8fec","seed":"f8ea358ea3a369cf72266a1f30e10c445817766080ba50991a2b10ae1f23d1fd3681ffd4cf4a7ac47b39ee9b04ea246cbf5337eb33e0d6e7c1da921d153e2cfa","priv":"5e3f256a55dbfbf2750e56067779fbc05503bea90e1a999c17a0bc27801a0bbb","pub":"02329640a5fbee753825fc310c06f9761cedfefb880d6e3dfb67eecc68ee269813","addr":"904c7b3d1cd8303fc3c8b0e3b0fd60fcb54807b7"},{"mnemonic":"ship puppy grab also merit doctor fine east venue resist loyal radar","master":"f7e49c26a890aa8deb888da48d82935a69730bfa0af67783b39d209ca803de9c","seed":"dd5c5df895a6663cea37b5e7c58c268420e290e4f20d7e0b7c98defa35fde4d372f52215b52bb2745481b8c63aa08c2ba163dd89f2a9e51a3bc92199be8d57ef","priv":"19a311da10e6f11ea3c91231a7e5bd22097701bb56c0248014958e6df186e596","pub":"023acf91dfb359e537f9183080ccd67f65b1b9efe314f682deebcbf718454d6bd4","addr":"618fb20184dd651d18d2e039ac0fa43e53feff61"},{"mnemonic":"beef hen spring repeat define hurry slab midnight liar either arch original","master":"85a6a3be23cc74b32c40f1dbe431584f8767f4116a98ace1a08c934956e8582e","seed":"cbe260dd75a3f8e7b7b9588f0a1325dd88b839a5536e39facf324cbbee3ae951903e2c17370ef673c770ff2e0fc3f1975a26f45d27c681a143f0e60fac8d18c8","priv":"42c6ccd133fbb7d3bd8bde8309f8202eb155c46829aaa558226b6e53abdb203e","pub":"02d1bd732a69043343e72e22432f7bc309e25e96d49b087572f021996297abba75","addr":"9eab0f06ec4e0a8058e4fde3ebd5a1b2f5ab043d"},{"mnemonic":"lend total guess ski divide diesel tumble heavy slight expose clump park","master":"6ad684d3e30778a46d5af816c3deaeaa0af5c4fc04cd74045dd80947faba053c","seed":"d63dd68a0b8296a41ff8698494d9823d18b4700b0564318f022b1bca641a8fd622ca403b48fb835c848f053557cb91fe4290f37ea9edc4f2428226983802e1cb","priv":"9625f841a7384f3fb64c643ee715ab0c5693d60132c4c9838c7f41e1c9163e1f","pub":"035e82a39dd7b61ad9f79ae31b0694af43378fe1b5cd6fa824ad2427da0834e00f","addr":"b88aca334f2bfafdb66c2e338a7d3b6c8be8bdcb"},{"mnemonic":"toss hand crystal buffalo during more laundry fantasy give dizzy bench want","master":"075697aef6de8c5b0b418fb3faa6038442349ded65421ae1089517423120ffac","seed":"4226da530678cd25633e2f87951c6f8f5bb4e3dda3172494dbc03ea15795b22d1042ba8265d67cfeddbc205b800ba7b7b05ed231845ad54cb3224c7ad0f9d8fe","priv":"8db99c4eb921431ead557ec1fc62bd6a9bc34eabb3516345a46bfe8c6106be6c","pub":"029eee00e90a02beca7c3813af59feaec320d26b585e5620de11efdc09a06d2c5d","addr":"e9a4a29d0e7267016b03bd23d6cc78b9eb1681be"},{"mnemonic":"camera gate trick sphere oven sick promote apology reason fiction item meadow","master":"7af52d41d0e35f2cad60fa2fb6c13d046f8aa4e0be104251dee489edce66a229","seed":"16ce2107f57bc5feff86b9dc81c98838cfb7b6274e835d6e35a46525d5870fd84c74cb528f6e2b87b0cef21bc6931793f472e5430b9582f036630c3b7c66df87","priv":"5f428e529d340883faceda659fdb36193f3cedbe2307dc4b8bee55a6845b9068","pub":"02c71ec0f9fc74db1da6d2a4a9d6a7f24980fa17e656c1d7f43a845a17625b2445","addr":"31dd6642a6d913d82b06c3793ae678670ea9bef1"},{"mnemonic":"slim guilt leader segment actor sick debate enough what rate fork rebuild","master":"674b90a421dab99750e982cd3c693668c45d7a39377cb82e3887552f047eadf8","seed":"115114f315f7af942dea64857c5bfe6a22c80031e6b1dd0c19a42a28526c0b9995b0eb39bf8e78ce849559eebdfa3c269783987bd4fd926e776984396a3c604e","priv":"2fdb1afdc8248d6afc69e387a698ef467dc0473323203445bf1dd5aaf5789936","pub":"03dd070062a8c3e65333572beea40f434d6f1b68e528ffefdfa8dd3d8b4c5a729c","addr":"8938c102cfbb8030cf69c660b04fee696a902f96"},{"mnemonic":"kind prefer arrow industry arrive cherry pupil arena strong tuition wide grunt","master":"c4b509d9b1e60d97cb8b862b96a2dfbf960b0553f0625af7430abd3951c59b2a","seed":"85ce840ce0f6625294d32cbd5f68b3c2abc3151db02b5a84b1d78ebd7c05ab24bd49a519a340cd19bdce6aee845ce59b6b5d2efd7a2b1640c7919177bed27b4f","priv":"ba8628565338b55d2a79b21fb9e47da978611095abcef86f305a0e2988e8128d","pub":"02bbbb0be37e3975749a095a9dcc025bd57368eee362cb896540c0dbebba42f0b9","addr":"4d8e97ff30d95baeb64ced528ab999c72aa4cbe1"},{"mnemonic":"slight bronze prevent civil junk van female movie vibrant soon grain suggest","master":"4d07291eea03d51cf9a3790ab0a77ebef383f2cdf184b0ebd872fdce93b0b889","seed":"4f770292818429f588226c4df9bf6053024a42f11a2499f0c2c5ce56f25d16489a2e554b99105c70fa57657b8d8b724d1879fabdfeea8aa43421d19849a0fad0","priv":"bc6ab78b16b831178cd9f2722bb8afb27664d1967cde464af0b951c3aea935b6","pub":"02673643c7fd4c12f47007a27a56537d152d607225a6d561fd0e18d30064752e38","addr":"3cd7ea7b1daecd3efdd14826508409791d8ce865"},{"mnemonic":"chief drill utility gauge tired alien bid deliver tooth amused busy run","master":"dbf20f3b945820a74898fd73218ed84a61ccbbb28d815d26dea7a7e9a9b0b430","seed":"93d2bcfeea8a87f021002ffadc33b664810eb8ed60342c8dd74a937cee64877d5823c45a4d34dddfb7d4381addeeff63e80a191b92dd7f1b4f0dbf5c5e8006a4","priv":"c38542f0dd692e74e8635dd784fe14d8c70ba931c354d6ea08f1e0b9080d74dc","pub":"0225dfa0e7d37e8903213d8d4900a2e56107e7dd02c66cdb7f86e9d9c0a05a835f","addr":"a94ac8358eca1fdb0ab8ded1cd80b492dda39dd6"},{"mnemonic":"large endless art unusual tornado loan planet excuse dolphin million reduce chair","master":"8f029c13f62099a1d280224f9af2d9458014903b3df1eb65647507e4a5262012","seed":"03d076444f817fb054603f746350c40c0551c3d155ded436620451c4f53ad1254d0b52bb0592197becf9e1fa14bdc65d04c7ab9c5bba7737841d800cb4f7c869","priv":"1cf63efe6800cfee972815f1fd71c68224594557d7894fe8902f56b40163ecd1","pub":"03cab792d05c87c205acd8d78771692507eab35d8c7bf729e2d36551ee0c7aac67","addr":"9f27d874704a788d3e3c3f63f9f1a42c27b83c18"},{"mnemonic":"recycle wine system erosion train make sting talent beauty decide beach pigeon","master":"d702a0785f59e080e2ec13280ec397e3af1c60a36bbf2c92c252da896caa7371","seed":"ffd0dd43668393be9b0949bb5872279ebd606be9ad58f8611ece8dd8b408c0714d5435c771ec87d23b83952af75a6853d94fb0ae88a9b9c1b506e3c0887f3bd6","priv":"d27a5cc824bc9e78ed2c991b8ca86498ed48775aec94dc79332057f2a36536db","pub":"02f85cda3ef9d19e68c4a3778ad99fe008904aa9a80c4dfa8d07355ffc840249a2","addr":"da42d3051e6dc70d85b5fa901e1a4c55ee12a47c"},{"mnemonic":"solve snake loyal grape island deputy monkey art pet candy enhance truck","master":"e866de4a10e7067fc8f6462938f3ea5fa7c88c93e2f630ca81dd07361c646fa6","seed":"82483d5e61c9eb2b0c588b438e24cb0a24922abc6cf0571cf3680474f1eb31496e387ae1c017d5a817c88e48020c5cc1298cfbd78d7175be0a1ebdfbf94853f9","priv":"919e4b231311f40772a47f03948b136879c13f5f0797c939e703b7082d65e637","pub":"0227c29a984f46d5a99c08f31355c3471eea9d231ad414286a25fb91bd8a3a6f92","addr":"e1ef4d05f41df82d47c287ad0347197e8deee0d6"},{"mnemonic":"energy buzz square deliver jaguar chapter analyst chat rare over bottom river","master":"3074c2d8f092896e7a197abaf388828f95eccde75986fd280c9b098586e18396","seed":"70be3c734ae665956abefaa3f94101b5863086c14d8c17ab288a3586bb69aadea314ff47dd19a4dd4295ecdab627a34d9bd56231180b20156b65660082e70d35","priv":"47ed2e3406d068624039f71e17f949c4b7865f4c8d006d6b4a635176b700bf2e","pub":"03786b91b237ba9c1c209d8386ab1fef86e0c667cf2a9a3cb25fbe06927ba3214e","addr":"67ba9f0de66103c6d6f1b799564ec38d4eb9f708"},{"mnemonic":"document move actress food guilt fence govern adjust supreme upon stay sibling","master":"6d110c56993597b6bd473eae083493e1a17b4cb971999b078e4c74c2a675f0d7","seed":"e6a300fc434aca28cb75f2113a8f7788778f2b9398290f82f8e5d989bd002659a645c18057ba64807f0d4ae3c064e56a2947d5aaeb83ff3c593e942fdd0542a3","priv":"fbf0d5b6e019bf7aa6745c4d95c0f9a428d0dd57b7af9e71eb2e39a6628b8d86","pub":"03725d6b7196d57cf1d3b193f1a6661613d02912981225beddd4e1db8de60682bb","addr":"9aad1b39fb3cd3fdef63130bb1a7c8d12bdcd866"},{"mnemonic":"express birth sweet kit special board rose sound place chimney awkward injury","master":"c60b7e5a1c89797d3ba7ce33ba487182144b4203379c04e51ec7ef4ee621f0f5","seed":"48274a66272c61abcdb72d36f16b6ae8a1853d299d9514516374096b443368656ec28f59c9f78f6707d1d1fd78c4aee00e046cbd3df66ee7b143b60e262ce162","priv":"972cf1431308c25e45efc26b86a87c85ade411bf3fe1cb6e88143684910dee6b","pub":"0243447732d68ec3287f154750f1b27df3ade846a0d4cda8e5e5f62f3875de6b86","addr":"c199f50b3c111205cc2c7309c9239393bc2c1e57"},{"mnemonic":"future desk scorpion enlist confirm favorite ill expire evidence cushion rapid staff","master":"0f15c9b1f3210c53c5c408329c3c028211660eaac42f27749a4e8901ee17dff5","seed":"c2db1a2615fb9b849717825a326e5bc2ffb8941755a529cf27903c0c3be806b4261cc3ed7afa8748d87d1ccdd36372fa02f92316f1adc28a354feeda7a0edaf0","priv":"39de89d88ac3f8b23ec57f82c83f9bf12a32762c2df4a612ad647ac9ba287c93","pub":"031abd39702f34958e3366a4d438a7285bb9d5ad5b8a29071ddf77ccea7f9c4358","addr":"a7bd49b9e2804e22072b1f336578334c53b6755a"},{"mnemonic":"interest judge only feel scissors illness quiz goddess transfer person position this","master":"f60677c75a51c5c9e8ebc4fc1320dbbc82e00a42507af218a71812d6f981344c","seed":"6e431ec0f7627bceab5dedf9165968ebfb03ca749aa8d021725338ca8e0e8ab3b00cd0395a68ab955068046c63daea7ba57117ebf7c99b242df8e63d01bfa625","priv":"41af5034dc87e11bb1cca3cca70f80fa057a5839b711927d3fab85048ff8620e","pub":"0321c6b392ae7a49201d0a7c89fc3541bf1c0c1287c051c405cf32a246df97c231","addr":"a71580dfa7773d8a2ce44c7dbbf03d285b46e56f"},{"mnemonic":"foil remember sample infant bread year evoke laptop buzz chuckle voyage gentle","master":"88ba5191913e778f76cbc28850f221e96f380724d29646f7cfd4fb6da20171c8","seed":"64485dc0ccee0c0b13c0bc76e44f8c3a26070a6c08fec558519503ed85769ce3f858978cdcd630b9c017a290ae4a7bdbeb0f66fa5e3fdf3ea227187a165ca654","priv":"117e2b0842cf25a1ee21eb2f244a2c1fcf2a3a6946b3b830707f7c96057616a9","pub":"02b349892030c73203e3fbadf870e1c8325ad0ba1747738706734f7a66e9c66ba7","addr":"1f6488347a7155806da3103c9a82954072a1abb7"},{"mnemonic":"pony super panther surround glow lounge kidney increase actual tray bulb device","master":"54c50d2520ae7023ffdd39740b46d029ae9e31211349193fef33cdaf373030a2","seed":"3d11ec99f173c1864ca6638a27554549c3f619a86e0099e5957972722b2937f5db767d86f5fa0c6b3e0a81d75a9aac5786cbf01f2245b51c9202cd4b4ea88a99","priv":"81741675b625a14760a1ee9e108a9ec6be183c480df05878cb31b45e0d0babcf","pub":"02b0bbfc4e33a79bec82682552fb4c0506528d121ef67a7a42d2ee26bd0b1661ae","addr":"8ec9b249788a123e1301100da2db3db71c913a78"},{"mnemonic":"achieve sail manual vibrant unhappy ripple aisle fossil pledge wrong cherry trim","master":"ca9ac46762b80571c25c2a9a6690181896f86ab3f728b4e372552fc9cf1f7e7a","seed":"4c1cf0279c8a29b8077b5797b6592397112b65e75e91b829a0a9f26b94803a53a02069ef774e7cb5c3cbb0a8e074c69b9afc5a4136e04913403b70046759471a","priv":"09503bd2da16f128b857cfc635cd90064446130c2477004a3870a0c5b1f1febe","pub":"022b34a4abc0a4288805719d72f0b64c3118d924d09a4dad4f26d39ed056349e00","addr":"ef2b6bfbe737261b45e770b5eb42d1950c556282"},{"mnemonic":"injury love grit wait junk bridge myself sister hidden dilemma gas paper","master":"b4781c7979c0b72d0c50c9889432fe2a54d6f08a4101778f88176dc661bb02a1","seed":"03bd824d7f4487af26d236950a69eef9c878361038f0e8be44145e558779d4accd58a8c5550bf5ea86ad169e5258947512c4b72f94bdf60b9135c28a4c779541","priv":"68354a2599b3be8ec6dd827b35290d9dfc068c267f1d89dd57851b22d69c95ea","pub":"028af1d826d45a920dcfcca8d9f86dad10d7356b3027d4051dd4c46ddaf32dc623","addr":"1f356a55f3d3fa48e5d5b36fa31f738bc8f83de3"},{"mnemonic":"domain congress cake cradle express despair devote swing meadow piece border cross","master":"a3ebb93b7fb0fac2b02408c0491f66800c220c7d47190c3c97023f3d6db86555","seed":"15494e78dec34f3fb759000cb0584e42addd40f1794bf2932c6bcbbba20e40a381bb9bc1b8dfd3a231d8e249aa3d51a257590a93188fbf116eed9321195a2267","priv":"1f1ae70c46a36ba70674c7b17e6cf0b8e08bda0a17473d8ae69bc54311239821","pub":"03d7d916b054c003413ac84402e59b976e5515f48bbc30ff8cb6bca7f4ee92c03e","addr":"54d0f98b9dad14550c844bbfce8a4031dd677a1a"},{"mnemonic":"pistol news assist poverty squirrel machine aisle sausage harbor garage truck type","master":"581d692fafd753f080fb83318856ccbf059b74a3f26ba22d4b93916e2165aec6","seed":"49abafbfd7b0c65ccf2e22eff01c78245c764d8ba7bd468fe1baf62a156aaa0a6af143c624241ac753ff8432712ea58f1df9e75cd969f905bea80c15b5fd84bf","priv":"f1d7e572b03a08cdf0ce00908c701053a5804fe566168436b90efd1302bd7f1b","pub":"03882ef7180679169f638a7da20a2b522c948b1979802cf4df83fe1b62581e4d4b","addr":"40bbf61a5ea5b704d02ae13d032f3dff4e597ba3"},{"mnemonic":"field tree license quality chase certain hedgehog alarm melt elbow screen pigeon","master":"dc22c189c264812f22664d39ea1fa2f7d986b981d59f1df2ec6f8582d640e196","seed":"37ab0888876ccb32b9ab73f144ba2a352b31b27fcf6b7f8fcc5a2d4802e7099a199242cd5f7f2a3c3a7d86e8c1abd871ca35881a6a47f605d04a063b589fb0b7","priv":"f82f484f92d1719d3e6832d49bbd493d5f7191acbc07872b345385c32f2d38ff","pub":"0390c62a3315cd02fa64216cfbcc1788d537818eab5cf932a24f9eafe6f4031f48","addr":"8933e5a789211fe61396f29fbc55be6ac7031550"},{"mnemonic":"wish vintage fiction false gap bonus abandon cloth usage hurry toss slender","master":"27f3a0c1791709a32f8ac4fc1e9c71eb24c06e2fcdd8dc959940cc1c8655a5ee","seed":"36932e48e1712c3d03261d432a17e940f1f21d730a3f22d37c1834ca0591b71b438d684c926ebdd51e6431502b8efba8e9c32cf457e68b71079864dcd0d1886a","priv":"bc0037a14a0297d3dd969b365a6d8dde9c6397dd3c8aeba6d701dfb1bc8b24f8","pub":"035ec8335e2f6ef0fa2dc6be7f3271b1117545ab02cf1c8cced03f9cfaaef7c602","addr":"5f64f8eccae09dd614ff9f7224a20eaad60c23d5"},{"mnemonic":"fatal strong idle grief present photo aware various april april card village","master":"ae83fc216ef4c81e2d128d90e91cba0b475be472d95ba77c2ab9cecaa511e308","seed":"3901e5518ac7cf29a42b94de334dc641e1db3b97b44a30d69f3865c050fdac8339dece5f9ed96a17e669d51d59ce856db902e918497ea8523e5ba49fbd06f621","priv":"1bef5a9ab2f2ebb16d9d08b958317a37f252f3de91a70b2c8b5b5ddc0a187ab5","pub":"0250e5876c37987b4189513c7a5dacb31a308c563bd09d7557f2584a3c86bc9d5d","addr":"bb82bd68b31663a75d0d007646e8575934991f43"},{"mnemonic":"error monkey argue fluid afraid hand cactus sand misery close laugh comfort","master":"1b4ea203fb592e2dad7f40b6cd4c8ab53c6a0a7656cb674f9e22d6a0e4e84efc","seed":"3c0544c9b9c32165fcaf9445e49518f8d0a2dc6ad672a01a15183ce1e2188f6fac026cebec0ac4ca58906d5599d781c18b2cd77d32992be9cfb01441d396faab","priv":"e0d0b452b3e1f760762f1bdc692225e7b14277d8227d619bda49bcc608658bb2","pub":"02e7a7156cd53cc7c8b4840772854e25b8c6c532c520770883da9d574c86551c7c","addr":"696d7a61a2ab18eb503cd724f0dd316340f96c90"},{"mnemonic":"demise know punch page upgrade gun smooth fruit machine long nominee radio","master":"b36ae5062ebe21f31bebf7b2078ec651ec579494eb764bedda7169095b73fce8","seed":"0f71fa966c1a56c3e11c54798052789cb0f450761a0227336ac50dc8206f032133937511e93fffd54103132d822b8e717ef15fcd4e68f391a398f14cc795cd76","priv":"6b9a3d2e63d666909216a0420709f127318f809549df2e99869fa70956e41dda","pub":"02d72eca95feaccd5a78567311e882d7b5eb2914d1d844e639b03c4cfa036155ab","addr":"9465a8f3afcc348d661bc198cf8220e74faa5895"},{"mnemonic":"install lawsuit guilt myself arena enable unable thumb domain lift feel object","master":"c033a48b64aff8d6c7fcabfab52087c0f7b9a4228837a7a21d8156358e5eb529","seed":"8075fb6cd8bfcc08f1678c005e9d2d0bcac710a6a62cfea46a1ccbf81747362a0e6a25cea2fa958fd320205e0f95eb8a5884c6f39cc3ad17d58fe49e43feb513","priv":"24e83fd857d2a0ef62052625d84e6aa37e96b14f2c8dbe5294107b647b369a7c","pub":"02d95869834be368c5bc37a45153135a1c4f003be6a44bb9af89e55485118826b7","addr":"631e72e50070f34e23ddd155ca0670c8c8db49d8"},{"mnemonic":"antique insect develop sheriff erosion appear easy fog kind apology stamp noodle","master":"72baea3e04811ee7447249a1140ba62e56bf473d5298b610235ec3178b388692","seed":"e751bd7ff01706f38b8d3a28ef3b1565f20a8ad221d521176347e7791d2cbcb9cecfbc8b51c2e36c303be55df280273711d94c416dd74a7e7a18ae52520cf89e","priv":"0ec2ef082498bbbf0a0686fd232a3b4bec66d867cca50bd0cb0e3221bc9223ad","pub":"03952fb023bb76ea74a6b5b9c4a035b193553a8adc1c0774f7ce4976ee2e8c7fae","addr":"9d63d52c57fd76c7036b882ed40f4a6714164c27"},{"mnemonic":"become tell dentist play light illegal work animal library dragon now gallery","master":"895a420763a2dd6fb934ef8d83762051b00235a83f621f57377a0d63b71bd43e","seed":"05975302d82f413289a1679cf6a69feaf8be733d7fd10deafe1470a08ed5796bfec454adde87e825ea80ff05586c12f5d0de69478cf72238b3e73851f691a3ed","priv":"f94266abb2a93d963a2505da57d66c36d37ea3f871654a0e4221ec911a6b507b","pub":"0256fe9203bb64e250fb0e68a7cd3b0d3c90cfa8f8db06c74524c63ebd66098ea2","addr":"4f73259b06b65db4afde238bf4b42a801178d92d"},{"mnemonic":"average anchor total witness carpet myth life admit gesture inject sustain valid","master":"aa36181d7a04a32433e6f4b1e4830d3e0796ea00b8b03d466087911931c16abc","seed":"e2bf601f15b7edaa2176e6a0e734c72f99ea63086ac463ba2dc317dd70466753fd1334cd27e28c382c99179db6a5b00003124f93a7a93da3a0018838b3b04595","priv":"235e293ad68581b4e24a554704eab59caf513b60b8af6b15fa5d8cfe4265e44b","pub":"03b9e9b4b67e3bd6500e6b0c3f0d0f69a15d0824f236553f7fa12a58111e5aee7e","addr":"3733ba0b6386f7534c7714e9e2382675e0dff54e"},{"mnemonic":"liberty cradle play vague cute borrow around that tongue wave solution share","master":"87869b74fcb6e5d4b0b5c5d53679737f275396d63cfceb1133e49458c9c74613","seed":"c60ac4201963706912996e289e5b6d886693f7277875b46ea166f4506bfc3a2652ae2fe5b466bc171c7c7f09f2920b8ecc6d9c7d2e0ba1ca2cb10b528119cfa8","priv":"a8cf8fb93cdc5c13402976952ddf2ba5c2b37d5756861536df21d02eb7d2c593","pub":"03c12a9f6ffe4d7b01364f266b835be4eda6515d601bd39399f6577c53b1289e12","addr":"cf72bf854dfe493a6c742d6941a4f22fbdabae1a"},{"mnemonic":"hip dose artefact tumble keen favorite truly stand accuse spin opera wire","master":"94ade552d985f2e8625e18360914a5046ad14b6cc5fa6abb4ada333de8973595","seed":"c1d9d325396486e588972df5ed2a281a1cef82184a90c7ed7ff1334e35ae92a15cbaec6d27c47742a28dd458474980dabcbc651d6a2eadcb97dcca08f295359c","priv":"9d3f309f684c2c61a0f05fc88e27894cfec51b738058bdb246f1a9fc65937fbe","pub":"02c1da3c5abf3dc4b52336b362614a1a7a24853759f72fae971b43940500badf86","addr":"cb143b40309bc078f3db3e24009ab54ec4741b9f"},{"mnemonic":"history team sight sibling art over pulse network sausage garbage october slogan","master":"2eacb1cbf92401aa2996b19c77a2f110faa835203cc6baa1c98204ad1740963f","seed":"70b0ab283cce0e7735ec8d05bad6178bbe5a19b747ca1d5d3f5a29c83fb634b43c39f621b11210a7d89ec988b94588b9d8b8f2f4c2a9ccb687cb807e230403ea","priv":"986837f4c2853f751c51e09e514d2d40b36d3995e9561b451474cec6ce431a5b","pub":"035ed85029803a151586b8b3da3f7b2208b257738dc43fd1af08c6f76798e82609","addr":"931b1e70776f50c1186cecec2dc8fcc917974e00"},{"mnemonic":"labor area outside toddler street now same obvious demise mammal puppy boost","master":"720c9f77cdac069406469500511e891b35f1a5782ed330f31ad1dde4bbdfe7e7","seed":"ddce9ca2ae36975072a321de56c51a6ba88b53c226d66006b81d4572af6c8c39303a5a8d56b1626510ad730d578105ee84ac079538118f9cf8e56b43e9da71e3","priv":"8182fafb8ffddf9b157f5a072e57d778e766f7fe5b1bf58ff6cf6bcef46e1d32","pub":"03399e5ef2e4a978be70fe20b7d44201b5130894588033d89e1c0b891576a7eccd","addr":"15a638bbd12f6cce559e0f03312fec99d8f5126a"},{"mnemonic":"coil room slice arrive lady world turkey huge point gorilla course oyster","master":"bf665f511652b19a5ba1b0a51137aa72e392a7149c2df6af31a0244dcdee4475","seed":"2abc97e164bca2a5f45001574f9781dd837304f949c28c102c9de3d713d8cb0443a3be55a324817e53d78b50f0a939346ad414eff0b6307cfabea6023c2258b0","priv":"dd27b678563eac5bd7565e130f6856fecfefe3b1364ee0afdace0408b5ac09a3","pub":"03ff0c0d776d27564be0a465e29923384215370508961a1a7c25c261d09115f8dd","addr":"c4e5450d737defbb8f4d406650c93d79b1820043"},{"mnemonic":"diamond empty network apple radio divide ritual flip correct phrase kidney say","master":"f451294347b6c2035d9cc0c635b777af0d1fa756e1a72c2e41863a753776bf49","seed":"9108fc851316d1f63bf92d68e1db688328b7ae4c5ddec9248d8b5012709dd14dda42ebfef74e61085ae56c64a9125e3a47184320e53ca82684074ea0d359e6d1","priv":"db4465c5493f98c16b002401e28422b630bfcfddf32f8112c10ba71787490e44","pub":"0370a09ad6af977beadc07793db44c7bbb94cdc060a12ab36949bd36a3aca9c776","addr":"b9a0c2f7fe9d2f416596b71538982206c70a38b6"},{"mnemonic":"cruel music theme kid pattern weather become same arch foot host region","master":"82dc215e8155458ad1f3c61deccef305932839a6087250839c41afc36a043f62","seed":"0bf672820da35a6601782bae8a773f4dc6381fda5fa60a3ded12cec851225042769cd147c614f0ad34515996bc1f90675c431a5517c2b5fed80552b2bba59d7c","priv":"a63537932e88d10143726eabb410b3fcf0baaa550892ec17fcef874a2df8b70c","pub":"03b01ab00751243c746766568875b948e12eb1b88e85dbbcf2b538cd65544b57c5","addr":"137ffba20e834d732918f15a7e8537f014d2f3e3"},{"mnemonic":"pass avocado year kick ticket chair pelican finish lamp eight latin hero","master":"5f0d43392033f39e4488d6d9ecf9cfc7cf358fd718c1534c30c67aac21ec94fe","seed":"577d6f62d28192b753fd00bfd3f5af506d7b9d1608eb31cad9f8b08019011dbd20aec03ad7ee731f74811ad060249113b9d2a4aaec0f9d3317a4e72745876822","priv":"5600cbd7c571ddf6d0493f88ea45ac92e33fca9e6644165365cd59f91e68eb21","pub":"036f3194e13694cb0cfa7af94b8a60cd641159d60130fd114cb496f5b828fc2132","addr":"d3b8b4027a87f928323589e9f5a85330a349b821"},{"mnemonic":"deny improve give spin carbon lobster shell lava romance jacket village canal","master":"8b58d86d8564a0f23f0d38e08f50c68ca12a7c55956ca8f34cf790b7260dfb60","seed":"1d5a8348a7c66d8d7f6b5b99f844a7ca23bfbd4558497c1eb72f6679df2e0a03404e99e97f68a3c0a47d56e8fbc0d565f4c1bd0f7da014845038466c7bd8386e","priv":"eacfcd11a571bcdfd73a64a8c0b935fa343b21c0044f8e4d9d2d882c75db1733","pub":"037fda0cd490d64febaebdf19a0236a1f7a1bc6d523d065cdb2626ca122e9d50a1","addr":"9dfc787aebcbfa396a0ac4fe9b1513ceb1cda121"},{"mnemonic":"target tunnel liar bargain bounce lesson silk lake artefact coin coffee degree","master":"86437b39d0a0db7f5b0a27f627146b1ba6ee9c2cfd4fc12663ec3a2fd06d6495","seed":"fe9740cbcde2cc458420431b44c8158a35c172637b748b4051b79dd1ac1d100ba0cc60d4928160ce8eb6cdd5232152f9b90439fa2f4a3aa40f1f884d79f0e520","priv":"5e56256b91d4e255d9a64d5e3fe5fd0cfc2eb558b683f2289d773d09008a41db","pub":"0273026ac3c43ee59dd6d703efc5fac4d31e6b6585e27820bd8d91185dc399cb36","addr":"a0d89229e673a6f6962045c70faffbfefb0764fd"},{"mnemonic":"rail ripple tuition once odor barrel winter antique woman merry nut offer","master":"33ed9b3e5babe3904c48a79769a0d8a8285fcd9b7c1154316429382876726bad","seed":"595dd0a7f36a71e38b37baf88967b9960baacf11b249edf1afa2f2bdcf68a96e867644b712a78173609202b7d8b7cf2a3cc82014ea28bb955ddc46027dd10f7c","priv":"de65d8250e9eba67bcc69a2840187c2ea7c64f44766c1b7ac0b648afa0f297c6","pub":"031a160d7d3b13d9190c2a0a684161bd00d7a3fd6f472368f5cc4bf5ef3f84cede","addr":"a0469ba7da8af387308cea748507999662a7f76e"},{"mnemonic":"mix you afford area also raw water fabric mother industry mystery victory","master":"d458f52e08056473bdc1a73f5ba148da38f58a53be4f7d5d8e5d2974da6474ef","seed":"fcfefea963149047cc195afa589c8a81189eb27bc30d6bdbcadc5a74495400eb12d7fbd3cede6ab7e67c42e308dbcb4f74cf2ba1335b873c8bdbd13ff19dde6c","priv":"d5ef3fde07814e0967f9ec90b44a749a1c2f4bae73f76af2e10a0f73681e58bf","pub":"03388e81cbddfdbad87b95d800bec6e1869bbae59b2098b51e083e97272ef82fe6","addr":"3570a61894c36414a607cc787e0eafa997ed0506"},{"mnemonic":"find fade drip oblige either deputy noodle trial hand clown athlete chapter","master":"1131d43aafe4c9a2314a3c41116a0ccc68080cfcc525fca0acc53d5a2d4c80fe","seed":"207bd6fc9c91ebe2521cb131c261de75c71aa28935feb420a2e9603659826c326e996074bdc78b7075bec54f4268c828ee8a62aafe993cd7cf481665a2303e29","priv":"22ca0a4c09e5d6a96ff37eae29507b62715a643d3ac24389217e35f4bea4d9cb","pub":"02ca3c47a5367b7c9d83057333cd716b44a429d7034bda65761ee1dc503038d520","addr":"64be7f76e0669905f362892b53491230aa4c6834"},{"mnemonic":"anger level recycle lemon material pear robust decide they hammer coyote fade","master":"0efa37efdf167ca18fe15ceace835d75ae94027d7cf4186b4ac7bb5b91d54fcd","seed":"8838fceccf5c30285bfff02ec64ee34d7518c30b9cd722ab8a732d1ced8135fe1919af7e3afab63a55f1551d43d4222f1f62d0349ec185e4d45076b849de8972","priv":"16f41120d317d7387aad821cd0374d715a1ec1049057268b3ee090210a00a6b2","pub":"02b13c5607cfd0675ec1f33f82a09a9cfd88ea6a212a84f9528fba9857d012f5fb","addr":"4cf25877cd8e38cf5a37a9dac81a9222e8cb5461"},{"mnemonic":"fall run bread slight rhythm flock pipe employ fault side kitchen position","master":"89394aaca338752755e33fde878862096328720570957a7c105ddb90599dd87c","seed":"a2fe89e4a22f8ff5dc458ff49870dfdd7be85afb9fdced1165efc1a2bc93ed44e4d0ea1be438f347f8bf7c9812ad6aa31f07c8eb3b5ec7cd40e37540876b12bc","priv":"c0c189d49e3735f5eb9c7007e1e0a841127998d7c462deaba60912a55c9f0de5","pub":"02199a2f84eab6e63c60f7aeaa56b5799c6013df61e51fd2b9e2be56e4d6e5b121","addr":"085ecfb2737f0ffc78f1ce0a15868b24d09fbda1"},{"mnemonic":"judge soccer grace train conduct duty arrest output roast candy total vacuum","master":"a5fe2db0c41ad910231deb8112f6e10998895d48655cd77b142ad9846fe62458","seed":"4ce2ea9a4984030e65ab6eaf3ce543a450881597d8585c79a66d324606c00cdcb2c3cba4fc83160f0426dfc5a89cd27a9c9d05f94e3a04e3bb550bf698076b0f","priv":"b9eceef7003d3258ec2bca498b34d3181b38aa493f8b3b1237588873751539e3","pub":"02bb8de097658d0e711f875089062c135df56e33fe97e2c828da5a5023ba634765","addr":"963bbc3ce38f6bcf2e15a3c300e7eef5cf2b648c"},{"mnemonic":"lumber lawsuit animal member stool claim know frown knock hotel noodle pulse","master":"fee5ba9a343f60a5f0f38b80c3208908e2db6f03c8a37dec5cf55d833e913fad","seed":"e1fbac7d494d3e1def8d193a71872395f24b8d62bc052ef2aa6a09220451ed59b1f74a2bd02ddc0fcc0ab0f4ad65bc17462497c431f2689d6bb9490573ce022d","priv":"8dfa11b3935e4e660e246fa935b438bf9aa9b5efded0e62db64f61cd678e71b3","pub":"036dc946490687b821115c280ff113002a160325f212b2ebde71628ebd27e418eb","addr":"3e6e6935d3d9715f525fc9a43eb1e7465a1178ee"},{"mnemonic":"city drastic advice adult taxi build local olive unknown leisure bounce umbrella","master":"0aecf2bf80c660dc6e9a987d260fd4f38daf6a00979e2e6ff0769907c6cbe893","seed":"f66f4fc74817a4edceed1cbfce8986d1cb9c9f77b23f5b33032616879c452e64b5b598518aad9216ff0b210b38cae0a6d417b7200df3fd7f2c8cac9cde2fb946","priv":"c8bb1e0db0df18c9a4254cac791a309045d9fbe6daee301d431ad9dfbdbfec38","pub":"0376d3fa96698c82b0ca3d704e8754838a80f05d01c6cc99894640da9aad067d47","addr":"9532ab7fb7493cf19a9d2e61a808fba45dea3ca8"},{"mnemonic":"assist obscure army approve salt tourist program raccoon coral economy connect around","master":"27262a815e351c2e583835dbcbb7fce7c5f96d7b8deec45a6325d02b095135f8","seed":"72315d5e5ae5936c29173566fe17da012160290050475356063fc678a8a41530edba5dafdc2404c410c4b5cebe8dfdf5cd0f6fd855d94a08ba7e856c984b7371","priv":"2849c2468ce054e94252fa34a7e704e04042dee4bda5fd82d6b38e17d2451c20","pub":"03a278a4623f9f8d32bc8198c694e961868709bb5f425f6000413e6be33cfab059","addr":"4bb9c78ec04e00e84fd3310d101f3af4949351d0"},{"mnemonic":"limb nerve equip power pyramid nest sure kitchen lady burst pig void","master":"47e667f4fa090bc0f8df1db86c5c7f835d7e43b8151b6ae51ea12b917d4b23c5","seed":"ee38177c8d3f2c0076cc84887f8ec20b9b6a874d67a0eed6dddb889c1c7af30ee9031215b6739d7858a3ec35253f0136217f888c20621b217b8aec2a900bbb1b","priv":"153335c0a20adc5347c99b869b1f1b2a30eebd4e1c71082b8f16a4641c88df14","pub":"02a2f7b5767ee89ba4aed85a5c198b9b7e62118433b61bed2f85c843576428683e","addr":"50c74e9486961c8b0bdf5b2289f5484ebd6554d7"},{"mnemonic":"toast fame primary broccoli valley fit chase critic life absent crucial chest","master":"f4a62f84c5ea1fd074494763e0a541015341f6e96d965b884fee68c0ef5e4f33","seed":"27302ff242190977db86f09e9399621c82a5f953e57dbc3a01a6c38ce8b5da4a61b0e6d5bb79bce239e5fe59f3dd12f62cb634f9347afddd89680b592872d348","priv":"7ebfe174b48e60f3809ee65cae852fbdbdc292fdb934d2dcd101f9f9be11f769","pub":"03b2b6586fe30ab7d00dd7a4da4bdc74c8092284f9d7a3e78eb9f298dc26b3b856","addr":"bfa414a410c1cbe1566a050fccc48c99a9b3c973"},{"mnemonic":"live mistake embrace other bar tell promote derive assist deposit stable chuckle","master":"d8dace20cfcf215f4cee2e55c6b9b8f65225291d629cc8f7e456778cb2f5b5df","seed":"0a5c716e273df360383a4e29cf2e2df63f47012be5f0acfac32d37241bc5580096e1538491b5daa0cb4929807a26b4225afa988057cd195d8180f5beae9a7b35","priv":"15330ed9be835c3ab25357f437b5809dad522ed0c5e1e19dc78ecbace52def0b","pub":"03b6ee1d8c8a1fe25b6982ae76008d65b5a1ee20a3537898d5c3ce528f55544315","addr":"b0a03a30af7c4a79cf777c64a86d66251d0b5b07"},{"mnemonic":"orbit recycle wedding rhythm write come apology plug blur pave job rice","master":"fc498e657b1ba22254ab35dc64173d6f9c790501b8cddd18f1edd625964c8f57","seed":"af14771135c60a6cea8c4790a008ba09c890d826c8606c94c5cc50bc8eb36f06bc8eb374fa18a67d738adab33cd849bf1d8bf744a7b33197055c75e924f8b1e8","priv":"94442c669d73ed4cfce1b2a87c76696f3954ff4fd3a867232c5f878f2fec1737","pub":"03db45a44b5dcd8b34b4a5125e54811b800879a45593af61a28a83180f75817a1e","addr":"20505c7aefd22f78b05bc45cecfae800fa1575bb"},{"mnemonic":"oppose brush collect swim cup age gate forward spirit boat century annual","master":"c156132e600a1d3c359813d2d3fab0cf5ff13d8713569cb3da35ec78a424e193","seed":"8a1ce5772eeba927d2f237acb22b9e86ed2fafc89c18e33d1fa040274d1dbce37bb2e93e1ec8e2dfbd32cb299fc966e43567f11bc0022811e6d43becb43e2e1c","priv":"f2c9a5337186920bd738336ee616ace6f7c21b68e731c8cd84dc023c89198525","pub":"021a7131768f1e6f03b1177153f36815503e411c54a6c33ee6a20281fa8bfbb8c0","addr":"50e772de1a2e1028fc46d8958f96ee5802d477c5"},{"mnemonic":"genre seminar green olive grow close siren sadness farm promote bottom few","master":"ce632e9a0596520a05d8c096928811ded1f9a09b461d2924f9e4ffaeadfed8c2","seed":"dba3b4f2981a61525481c49e34db737274b80b86ebd2eb6cc64b05d8e321f871a97938e56abadb178688373b8c29a7c752d7c53a55d7e26d660ca948c8ea76cf","priv":"14e58e498bf7d472247df7024c6465db0c2f7b390a65dd05028b42576a3d7678","pub":"02ab7825f84bb603bddf4325c2afd8f7497bd1d22b412576e8155f1fb91fb9b777","addr":"a2e64380682dcd5ba6a4a5e7347389da76ab39d1"},{"mnemonic":"radio minute vivid clean cost gadget ritual front tilt other valve now","master":"c1fc2d9a7484bbbf513ce72d4280d4d6f01ee0359c59f29a2910d44bd06b41fc","seed":"8d4a332dca82af94bdc825c3ab49b970c5a2263e8a07e848841392f4274b44cbbc57908d6522369b32a584de1d8fc012f8f7f763421cc309678386f593e2f819","priv":"fdb87e0dd6892d1b7e29e59dd43d7cc5bd7825329e569d5dad839836d551381c","pub":"0274c7216f289b5ace0f684dbd8f9360679909aee0244f5f16b65ae33b1f0d9737","addr":"ed20a72a5800b88c62873ded8f5e31bf0ae08944"},{"mnemonic":"clay verb soccer near actress august like venture goat rug brief scrap","master":"d888a8d4f3c351b37b6bf708f47ffa1f0d56dfa35f039d4c8c6e49531043c4f4","seed":"470399a3fdf3f7f113b6996468b4cd22524b05290e7e91dcedb0f8cb6d2fdd39ded069f3faa72799ed18d0692301a64a214fec0cab41b3bae69d121d06dfb2af","priv":"971aa66792510f25849cdc1a7ccfd7aa8fd82a0f42df4a947ab675fd96db7022","pub":"03f7c82b2ab42b8e221f661ee3eeebe6231f5d98ada0133431715db7302814d448","addr":"2d306db9a75411f5ee640e2778daeeac539b1a52"},{"mnemonic":"rose team vapor oyster embark shell six object rescue village rug retreat","master":"471f619784e65272a58248f67516ec85a69dbff66719eb5bd17948c4e2e27c94","seed":"39dc2669bc21baa81e45013e856e8289b858778d3b5ab601a26115beebacc708236e742bc105fbba968e364745e34a0c9fda0799b79b859c02efab3c3a4c7204","priv":"581e1940af1601b7ffc624a6465519cd6959234d112353d3a6f2ce4ab3c75711","pub":"02ba88784648b8476c55f9cc4be65140c478b835d79fa596abde69038f9b5a2b2f","addr":"bea24bf839a66b47497014c0f29f98bbd506e9c0"},{"mnemonic":"blossom turn knee oblige digital mail phrase fly soldier unaware corn journey","master":"d7f58c53d2b777e2f1162bf97573c03446afc51dc758bfaad0468c0edec615e4","seed":"f13ee4c99a6c39751bc6922c9be96321c7704c36ae6537f13146b4eda938fb8b2900e44e901223b2906db6392617d4e156554da83644731ff6e56b0b3fef24a2","priv":"c4231def1f2510c02388455fd0d5a2ccc80aacf2faefafb3534544f1b75630d6","pub":"02f0e5922755d841b79fb76f0f129ed3d10175ed4c377d02403cbfcc1c9ffd9c64","addr":"8c664b57dfede7168c0bde20acd37674a1922dcd"},{"mnemonic":"crisp joy brain treat actual later nice ensure village bind powder merit","master":"01058624d066cd1e0527da16937d9ad9bee8b7aeb76c279ea53f5c5d7e56f6d8","seed":"389060cdd3a98f5625f373a0a536f70f84cd0cc6a7d5bd8ee20fb94a2aab9652bdf61af9cc532ebcf217fb7d860c30ac1ccef4fa46b0478971653a42a1879811","priv":"7c0389b4564ae01f4c14da09842984f9b9720fca2d09fceb0244623db5cc07fb","pub":"03420010f464371dd52a34cc193d55de94a3ffb3e746c5566bf8a8e6bef686efec","addr":"c9ad4a84c23c753544d4c3972b0c3d2d86ae397f"},{"mnemonic":"three scare horse film rice divert frost gather photo weird nuclear hamster","master":"b5107f515bd7ce629e85b64264b2c9ec80595816d9bd47f04eaa6971dd565d8c","seed":"ee242699f11339f305818f44a171f79b174f45c09f2322f53ddf3094e830fddbf4e418bc3ade62f03164d8435036514791b936ccbf5f405defd33bf68984ca01","priv":"99513bf817cf2726237c70a70cf6bf5e2ffae1494b433e1d77c8b9c59a3e47e0","pub":"02641d322b89339dd17528573b100647bb082e91d7cf24bfc897e90b20f270f791","addr":"d8545d2e2a4ab61af14c04d40fcda9ad39bcaa33"},{"mnemonic":"circle pond sing route tribe grace exile leisure health cluster prevent year","master":"5cdab97cd5aecd22d671964282f6971ba4be01267c90677091d6db6b5adee0c9","seed":"929117b95286a76aa839e45e768b9f5cd23be5bfa73f929ab835df15cc1c96c2c57cad593b7e396296c0223d38c38b03a4ede097bf3b188a11631537dc6223a5","priv":"35fafc87a67c7547f256f7bffc5b19395349e1665e01a89f228f44af8086b118","pub":"03fee2e799ed5232ca3a29238e0140cfbe5f1bc6ed2c1429c0914c4000ad59fb3e","addr":"2bf9cf4c3f34de93078928aa8c6192450a29af02"},{"mnemonic":"rebuild address giggle city tired dice sorry danger onion cry cheap sock","master":"83df9579ad9f629ea3a09976302888929c52527620ec7041fc9d4e36380fa953","seed":"7cd7ab5cd9f450b45515985a2af469765286510461f42d4ee5258608aedb40b7f60365b685a706d0e0d82f775da38f0171bc8be56543113805227c5f9526e7bf","priv":"a1613406d358b4c1db8439a3e69a4d7072dbf78e06c8a8b72c37425761f874ae","pub":"0395d2c96136983d906c50caabd2f61d1c1b19a227549f7bfeea2ee327c5cea276","addr":"b51131cafeb358b0f90101072a0bd70fe5226726"},{"mnemonic":"toward turtle false distance spider plate aim daughter team jar case option","master":"229e0c7738aff8a44fa62ad310f3cb18f6b94610c83faca246c428c26f47ca18","seed":"405cc161455171571df109c3baa2b3ae25a8ab9b3c7affe9b09b32a755ea443ee590f722f9d2f3c39e9e828a2f276f46a6f9b65b024a11c6d9ae76929210ad23","priv":"095f70fb24f7f97994339cf37a6afc4e95f1a421d9b076cd714453ba2dfd29c4","pub":"037fee3b9ddecb153acb32358781fb541283c3a61ce2f25366b199f970a87057e7","addr":"f3e1bdca0ac89c2f4036f07cad45f65ecc94bd61"},{"mnemonic":"mind mirror athlete assume piece surface raccoon struggle inject horn body engage","master":"75156c7a3676b6a756cf4eba160d44d94ecbc6ae06457ca714f4313367e8493b","seed":"c754f1684d8944deeaec89ae5977458ea9843b4bfa0997a7c1213633c6203a154b65f2109e4e2746735c85ffb7dce803bcc57b38cd617b43345c2b486ce44ebd","priv":"c03717d4cef8ebc0e4bd6d78ab5ff3d5975da9919fab3cef3249d329d488fe28","pub":"02638868a04c039201022036284a8916939b6432f4a469c132748955f7e6dc468d","addr":"d7906686be6e6b9e1dc032c9e89d30ca8768c698"},{"mnemonic":"armed lottery garment beef manage knee subway market enough end clever edge","master":"08432ba7a4152d14119d22b52f8913f2e221237f125f58e4df5e5c87da81a74e","seed":"7660fa9d42eaee32aaba664593f1271cb60e092a5758bf3353c03a448360ccd74ef45b01612aae2637aeb86f8d9380bb8ce6b9eef5e0739c85736cc50b612d51","priv":"4f9e5ef095a07a939d5f3296b211fd938ca90d21f52640da2272ab812947127f","pub":"034c3bdf7e1bea7d629e2b1f82371d1d7d04bbce016317bff603a0cc2682544a93","addr":"8ecb13c1076cb132990cbd0efeb072e58fd3d1bc"},{"mnemonic":"city chest trip critic advance sign push patient choose pride lucky cage","master":"5069d7379310d03e01f740871ddb8043daa108e523ee5c2aaca252d079b9b99e","seed":"5459d94456d6fec414efec5630285ec7e05293d92c8290a07b1070b5a7fecb8f7356beffc82790b50da2fbfb28921bbdc64ac0d94e1d565f6ead799c1c04e7e6","priv":"6d334f7f362d2dfb4e7af20f7fe30887e3c91186954a8252078f215ca22e4b07","pub":"03fdb94e64855c4c973fee4157d3949bb9b840ead95906a672c1d08390e3be4883","addr":"bfa8840559e159b5cf6e7831c4696238202171cc"},{"mnemonic":"fuel derive exit magnet shallow salute clown prevent inmate hurry conduct series","master":"0c721f303dc4ba98877e76b3c36d82a82639ff6c02318dfd4547943b39d7fb36","seed":"877d16863699cca3246681de6e1b9f2c4b59ad600341c0ce16dd8c95c1f5cb1964bdafccff0af5d29eddaf9bb564552499234eee8e493549d0f6d2cea0a71695","priv":"b4f009ace3092938c51c2d7557b52900941c6dc437306883a89a51e29af04900","pub":"024cc003cb7be1724456fd703edfb7e339285883088e97247d83cc64e8283f796f","addr":"b2bfd256adb5be91b637eefc2c20efed75659f8e"},{"mnemonic":"soul junior garlic chunk eyebrow betray heart sunny average coast help champion","master":"7c420ff72c69dbc9006c4969beb830d7fbbac17dfedebbb7d7852430f17490b3","seed":"34ec95dad85e66b55bd9bde227e68b86298e4bb51b3b3514ff774298ade39fd769eea0f2433392a09578da35738cdaa31a0d71cf043204083006cbccb9ada2a5","priv":"719c2fbf2db0df066f36fb31275ab75a3905c52b04335f97f778c540e103a7fe","pub":"022333046c912253a37832140cd42243733ccded5a7a13f20ffd6e59cdf19443f2","addr":"048677f2e035a21eb91d40555f0c9ff53f335660"},{"mnemonic":"private outer service journey dry exact thank ability wheel destroy blade scout","master":"6d87dbea0c85b9ce5e67831bfab7e5118ea85d7e9103140842ed4b7aa46c2b87","seed":"d0fdad93d2b727475db3da1a5cee5a4dd8c9a0794a6a73b5c3d6078541df7e7717aaf0053edf1d4a670dbddb96a6085bee0b7bf0c4428f09bae98a46c93e139c","priv":"aea666b18ff888190a0119fd38604a711a66d235bdfd514378e6a52efe4067da","pub":"0275d06c981e89fc560ea25164baf2c238b6fe33bb65e78952e6912b9cf991a65b","addr":"32aa41676d1ab5e54575d0d13f673c352f0f99b6"},{"mnemonic":"diesel suspect urban fatal total motion other opera taste shock prize lesson","master":"6760aa56bdd6d9a29615c425d934b788ccd70b80066c85caa2091e3861a5508b","seed":"bb3df25ef6c4ac87b93991710c0b927a24c47bfe467cc3d057ae3cc5867bff989d6e8df8b790b52661ad3d310730dc55ba8fdbbda118d3fdf75a21750f2f8089","priv":"399d6d98eb0cef3674ce7d155b426638ea4679fddc624cc582e13b7f2927a8f8","pub":"03e6082570bd65f91edcdac9564f3d71efe75a4bbdedc379774ca9879fc8a57cf6","addr":"d3a69b264f967565d19aa3be68b6a20ed054da40"},{"mnemonic":"tide rain throw pink treat sphere soft season network good left potato","master":"a2f3cb3671d233a245fbbdc8b769089035cf13a9312a78826972dbb99eb4e619","seed":"0fa23be9b8c9a11dd03a5d6c1677ef78526ff2ce3e12de5195d2e1b40f2df6b90515bbb6eacfffc2e9b82ff66426fa1e3a86b51e98a733d054c4b58b6b5e7025","priv":"34fd376b792658501ede9f9f2726a94f8763151e20a3325d05eaa7e6b92b19a6","pub":"02f2f3b3ca1654334091af786f28f9b64dd599f188902cc24f2890edb62f0f7527","addr":"1f06acf38751a45fc0734766e3c794547a31434b"},{"mnemonic":"hold forest select elevator skull warm crater help sing liquid foil burden","master":"20bdfc70225db1ad0d9a1f53a1558efe992ceb7001f181a0ab5a0394851dc81c","seed":"8839e0268e51734574d033b2ac42d3de449819e0e6a916b9f59380d15be767f5a491076bb4e9c2c586cf92d07812f7338400962d28a06c2218a3674bffaf586a","priv":"8c1f88886e7ee663a9df9ad3b31871cb864bcc1ecac7e19bff14344423581796","pub":"022dc59925b511f1420f897805f13b684d9e91731c88672121dc59308ab4fd7c12","addr":"3911febb503ec0cfe4bb41bb6e9fd1924a027aca"},{"mnemonic":"power orange shoulder stove sunset during jungle buffalo funny enough immune skill","master":"51384a8d4d886c1f0a7b4b1938d798c0463e44fb0ef05f6392d5f0c3c0c1813d","seed":"ef0f86555bc2d06fb8b676196c8d046aecc752a61a95d4783f8e90cd0a3117e08c11171214fa63a8e86a8280ef98cf4cf780eb384eb78ece725b94a261770268","priv":"e644ce7c5f3541acf3649d8a44423d277301e519147f50be97dadd4ae1d629ee","pub":"0312f8f9435994bd6156ef158a80b721e73dbca17671aaac7f7d67cc847bda7ed4","addr":"82167c6542716e9c1a072228a6159af1b02f8893"},{"mnemonic":"black evoke reform inmate similar wall machine deliver gift photo axis mean","master":"2cd652f239c8ee231e516843dc9bfed097ad33378563e2cc50e07a48cf0bd28c","seed":"02da5a82f2f4a6ac1a4a962d5450899e949e702f96eee80f364faa7751b50a55b438c6e4f4fac1b6e495b06fc55f63ab9ec1d288df3d62f6644bd59dacbcea1f","priv":"f6566def1b32c210a1369b859cd8815efcf5565a2e1334afb0663115acbb5724","pub":"033055d70eb1aaa92d91e04edae35bdcf2dcaf4bd80cb2f798f2be9bfb6a6fcf3e","addr":"dbed2e50e81e7b093ccadb9cb1ec9ad86837ba09"},{"mnemonic":"sea snow child feature gadget oven this lake post entry essay alpha","master":"0ca6e7a0b4fa4522ed7b8ae0834949bf8a35f7fcfe099c237513d7ba59d82562","seed":"94a9ae63647a2b63121725f961c7e56c7c6b6985a169c43ae41434c3155ccc8244ce10d6376fcc473d7663189d51049b035e5e232834b470a404f24e286e88b0","priv":"9b029add6a255727c4cb80b868975e95086487b3a463cb35870a74414fc6c14c","pub":"028a44cde34153397149442c970964c1647e214fc15dcb345c4025cdc26cdbd3a8","addr":"a23cebeb59b458c97abd67a3e32387bbc56545e3"},{"mnemonic":"couple regret airport shy symptom shrug mom sail insane culture detail shrug","master":"37711c29531e793d6a5e2b4931b3aa0240ccef541c9b8408c29bc5b68eded038","seed":"9c054a9047e66665412432f402f94e0dc5f87d7cbc1a32f6486cd928bc2a9a0aa898ab91fd3aabb962af985da396eae7a0d00fd739650bffaf070c9af44721ad","priv":"b9f1026e086eeeac648193494b398770b7226d46221cfd7281e5519e81fd8fa5","pub":"02de158ec50efb1b8567d63331fd7aa66aaa59ff26a621a59a52ad9341330b028f","addr":"aafa96d9be89b09030494856cf6275b8e9eb387e"},{"mnemonic":"mechanic sadness easy credit eyebrow sample health pyramid bargain actor power glad","master":"68c40248a8f7049062f18ada91f3f2166b37865895d4fdc8000268dfe263ef9f","seed":"d28287812cbbf2cb8509eff491ac456ed199dd2dfc8cd3c93e05b0541c154850f09f686a573994d41f163884708db205b37afb02752a8f0b2b9785c6eff504b3","priv":"250d326d0c232bdf26b6eb8e349ae5b49e30b0507fcce0be1be3bce55b0f7645","pub":"02d5713f20005136dcf9d8653dbfd75bedca3f42b2682ec9918b92394f2b685b13","addr":"409ab6606687cf83eb6c2388d6ebe296b4799967"},{"mnemonic":"mercy spell despair dirt board clerk about symbol supply provide rigid evoke","master":"37a0b9c11386b995b71a8c8a5e150ff76d238779b8148a2137e5d4666fe9fba2","seed":"9e3ec2ab97061086be1e02cae7a0a30493c019247411a7e7271c0c5f7f40bf027ad3230a1f113580365c82549ae23c024ad85a8601a30b6f78276744ec803a35","priv":"0385392be6a34bae1ff02570948ce1217fd11700ac753bbbbd47a1ece41ba38b","pub":"03218315e18c8a5128f74186223d32ece9c3987a0427db95ef51eee9acda922c03","addr":"725139ec60574c941c133ad2e09e793c1cd32cf3"},{"mnemonic":"emotion exile anchor charge silent nose family tube view lottery neither razor","master":"d8e841a6199f937fa9bab3c3905db51899d456f9caa5d85d9d930f9981ba6ddf","seed":"c8610e5fa0b9d9a83610c4458129802434d7045fe44917de29366c6d900f123e5414fda889e21284405c4c64fe745a36966ee86fd6f61d1dce6f809e0e63624f","priv":"b567d59ec087a81214968756017868e483e62326bd7239fddb27586745412349","pub":"03182c009fea42d30f31f24b6a5d251b70e72c1262d22f25418653cee5a226bd15","addr":"9f5d2ece004dd9ddd79b164c4b51361eceaf077b"},{"mnemonic":"orphan attract pair execute fresh interest artefact shaft sail advice vanish moment","master":"b58a705076e0c5aeade31776d78d319529bb76ce748aacb266dc910595dcddf3","seed":"a156c3c4b6241c4e99bb63dc221b13fa77219f2419f7c33a7a7752b5dd89d5be2178b6c2de2225292bdd0bbcf3b90bbccceb93ea65deacc866a5a3da4944ab1d","priv":"857564d0b2bfda18ecf561ea17dccd6d1bec2100e79b6adc8a74997b55f53126","pub":"03eddc58dac77538639745d167c174b907a448072ea4ef9b14563217716fb606fa","addr":"b3a656fa40d9a7f6471cf6dbb00fa0e2687df914"},{"mnemonic":"guilt awesome champion wasp execute purchase better mirror such prevent stay actual","master":"ffd1b0b635383f57d0086c1e6e4925d82a9cb9b310d0757afa8d941a13a1d61f","seed":"c36560913942649932b4aa8027520c46155135b50d66b0c6b33a7f63272b3d531946fe3aa0efd22c6e91d5e19cbed5183ac2bc7a18c219ee3e47dfaf35ef15dc","priv":"d5d35667bd3f54b40858f3cb4c6f09feb889f11d6da386935fe8b42e3a37f58d","pub":"039cffe0fa0a30d9ab9b1ca354ace89b5c9cd21d2653eb5a7a8c5b66c03912bc8e","addr":"1f2543b17460c4f7c2d53369fce6383771c0f7d8"},{"mnemonic":"pyramid soul ahead tongue observe void whale sense keen feed today abuse","master":"272cd80e4846e16f0449c68c8ed4c78071613b57660b85206f716203014c9231","seed":"2f342928932ee8e588bb75ca7cdcd7cc61f32eb317401047cca5b4133e963776ad86474999f9013be1f6cd947cfd9cf4add3be93e686d467223864851ea71751","priv":"d52cf3cfd4e6b6310bf47db08d27ebf0109582f78419d369c4c5da596f22bdb6","pub":"038f855f837abe423fcea3ce81efeccc49da313c71630cb08089956afb73e96e95","addr":"c888d0e5e1840b29f6d85a64cd9704221fd3046c"},{"mnemonic":"speak mother wage grid column movie pluck deal bulb stem okay own","master":"60b4e8cd422ac64986d88f4412e0c694d77d09d4469b06bbc8b4d9146ca5e412","seed":"ecddae7245f9ceb3b2eb324a78421ba99d3b39819bf394be90309cea21d6275ee32a068aef8078fe3514cde61a69e31ebe091669392b5c8a442451b895591ad8","priv":"4695ad7f839e5997df9747bb6d4ceffbad85f6bb26d01c328e6c6e8f6e68800d","pub":"038e3e274ef62db04582bdf01f4c443fdc5b590da7d2c0f5f1d1d55abb0752d440","addr":"359c60c1bfe3a11711423effbacf7d857d39437f"},{"mnemonic":"unveil toast planet basic limit bubble lawsuit grunt lonely favorite inherit write","master":"32bd1431071e17e039819b0f3d9d959c5b88813cf49ca69c90fd547a4fedccea","seed":"d036fc1412c23cd5406860b96814ad9f54359e103834f5d9d1e5f79d52b2e0a8432c4ae705d2fffa9d87d4946dbed2c847a4589542f8051cf6e37689617964c3","priv":"93fac9e5a9e35c2138568864525be7a43492e11f715c097879033aa4019cd723","pub":"03b0e30e8c5bedab8f9ff703df5c9440855b96594e19a367f3c1da13aff1f606ce","addr":"0e70b83293cbdc8b5e3cbec03cf2d0602f221bb8"},{"mnemonic":"cereal forum again rail lawsuit mandate above vacuum hour tiny rain mad","master":"1bfbb49078074dcdc191bb798d3c02462d736f786d7e91461000fd644aff7cf8","seed":"2aef95fae13809c1689d4b5a6598ad4e642ec6373dc6a10b6f348718360e3397eee9a2ea24acd344260d4002b2e7857e71daa1e7111f943ba036d4d94deaa339","priv":"75d0ffb17edca54a389371ddfbeed3a930ff3ca88ef166a67101b9091636d7a8","pub":"03c1ab2904a55bcbd56d1f1b2840a4b09f665576e980cdf2fcd45db21c007fdf82","addr":"cedaa1fd49e697c467d8ce47a2d67ffbfcfe1d56"},{"mnemonic":"infant glad torch shoulder benefit pledge social indicate present deer glare hope","master":"fa580a50eb13d1df4efe98cd3e86a1927e4e9b8262a279f2e782d298641a7378","seed":"a3e088fc36097fcbb0286a2103e2b8f8c1b3e0f6d8521c82c2c93fe06a8c1b97748143b02d9196f095ec1be5044aa0d89b39bb131c4488858e549879cca4c8f4","priv":"61c933db24e871ee66fcce148c2ecc3fc85def76b1e6f8ea784001941deffca3","pub":"021922866e34e3d7e28c1f5778c70e7b8742c2c9151ca5559039949f32ff0854b2","addr":"e550531be6f31c18a90bc6add24c02895e444794"},{"mnemonic":"laptop vapor rotate chief frame trap duck satoshi obvious pen oblige bubble","master":"239c6fca9e52e705ba0d2d9190a08748408d3a53ba0d19bd51fef426b56e1ac1","seed":"15a573343b11562370b53ccc9f11be74e183b1a341ee922cdfeb8c84a4dc914d23ed6a7f58ab451cf57d5f610c8ed9f16e2072a71ab8edd82414fb9d24cacc3c","priv":"ac37a60d2ff77750624fdc0d41531ebc6dfc1786f681dcdb436ec920f91a34b0","pub":"025dd6a2cf772db80dbbe6957ad1606603cd5b065177ec93263ab0194505c420eb","addr":"5693d8a59358cd00f21dd8786248538bdfd0edc6"},{"mnemonic":"walk raven camp kingdom defy nice hero copper velvet lock era south","master":"b4292f1b198481120f507ff13017c2756208cbc9652c555807472d872a58b9bb","seed":"6d2f085ea9e128fb3652d78d9e14e38eaf793ef1aa8b455798556482a5c2f3dd43933c26ab9fc38fc4943c82cb85c8c5b027534f005d45b740b31f63c683b87a","priv":"ad8fc7544b1b79028e05e96c9889004d9c5cdeddbcdaf05bead09b2075dadbba","pub":"0285d2a820245c70d9f3cfc930d6c4e467585f3c831cb7bcd46f58d637bc827729","addr":"4c7c3cb79dffd93e81882b609f7424431e55d4a3"},{"mnemonic":"impulse certain olympic advice entry initial bean glimpse begin flip cotton mechanic","master":"b092aa1b7fa22bacb8915bfbee4018484dfa4313c5779142e71e6d80e334dac1","seed":"9dbec0ace8784d915fe1bd3cc88b7c774fdc4791ace38856dc0500927aa02975feac3d82cb9771bd69d5b2f8c11c663e887b27292e3ecb36ff33ef5b3b3a804f","priv":"19497a3611ce0f1fb43aa5c55325099b6fb18811c99ec1d38c743c3338ddf5a4","pub":"03ca79e260e5a06bd3717cd969610c06580f65aa158e770eb418653a95a52cd0f4","addr":"f83b4129ec37643eee9f5d262cfe80087c5c5841"},{"mnemonic":"trip brass eyebrow plug sibling couple tuition tired warm spoon october finish","master":"ba1d19fb67d08931e7fc46b55c02651d374c7edc6df6a3b89fdf9e28670de4ef","seed":"736522d275c19137d354d8899542497b76b304e33c348e8f446970cd77aea927e2fc1d493b5f8dcdbe48c0a535722ba4223ef52925a57db21065f92779ba66a8","priv":"5d7ece46202706ddb8db591c4e125403f9aadb33c96f259105a0648ca1e2acfa","pub":"03791637ee34fa2e798c0cd98ea21cd17a4c02c429f05a9df5197b852fb643216a","addr":"e46722ace3466a38d3b5f66d5f94786d4576390a"},{"mnemonic":"suspect brick cloud coin tomato guilt inflict type lesson panel right still","master":"56a2d9f123ae22001633fda68b5b6f1fce4959ef19dac2c2a88ca5f774cb7d71","seed":"bc3b42627e5dfb76f1808f75e8cce883afff811821dd615262fa62c98c00cc0e0fd97b213f3b386ac00dc38de399e6e56b9216e34e4deabd15d23d70ff94cfd5","priv":"0d2c63fef727f339b9563c1f8bda5edc3755029ed45010e99bff74bf805f187e","pub":"02742f8b32ff1cf54225fd667425daf286705a0852e554e3294d057f5b41bb737d","addr":"4ac1a9bbd5d9d9597587bb809db80b69485d7e47"},{"mnemonic":"innocent interest smoke fortune smoke nothing clutch dust ladder clutch property glad","master":"ef88eb840ba3b3a072860d726b16c5309b9959381db68debc03d9516a7a7205f","seed":"33a6441e74f21794565c5e219b98416a17316a7b9335f8a0f5a5ae45608b315539c9938740266b663f8410e773dbf361f67550e185c0d42fdd4b406fec4cecea","priv":"5360d32f6dad727cc98c0c1b0dea7bf59f89aad2e5127050294adb9d7b116788","pub":"02bb5f40466fe161d106ccbae569709217ce1da9764078d27d3c8375752d7d1f87","addr":"fbdf59b3297e67600290d6bbffbbd39fb6f460a6"},{"mnemonic":"employ ladder boil blossom level pitch vapor gain permit manage coin supply","master":"c550d7336d80488c81ee8f2a8c3fde04784b8f3079d63add93b1b8800f796024","seed":"a80406c58b6958a30c0bb15f3b6f9efcf7e0c8cd0f01114a72f9c446130801c539028c964321ed9ba511831aeb00dba1be82eb28977319f727de1a9f44b1a7a5","priv":"9233c90da7ccf973268310430efa073e4e070cc5b9dfa29612bcc9541ca3417a","pub":"03c070cf8379e2461ab6158755f45d881ab8fa7de1501bcf0530a871abcef79947","addr":"fcb4e5a3f2c568e0d513d1ad97c7b806a96debce"},{"mnemonic":"winter absorb stamp enroll brush paper spawn slide salad special front update","master":"ee7f947acde43c8fc5761af3ca28fd0e87d0883043ea4401f0d692ea818d5573","seed":"0f1b5f166616c83c129d6b2e0d1cf706d46fb56e60698beb77f9eb105bc0726fa7159a4a492b6de462517d692bf26a310528379ce47b4325879772f46ea0d82b","priv":"31f98cc2cdb0cc6d88d91f21960136650d3e7bca690a569edf2ddd6095026e38","pub":"039ad4a48de652c30e015c424c2ef3083f234e5df78791f112eaaab2f74deb71d8","addr":"68306083576ce37fb1bc653ef33e46ade3af0c7d"},{"mnemonic":"focus usual earn deputy execute climb broom save robust coral piece shell","master":"148c7f123552e1be3f696b2f8b0df4885de067d43f9c1e5c671ae6a3ba4dd361","seed":"a4f311017ce37d0f1199253671b0f615ebb09f92648cd33590c2292d4bbe1eb45d6f1a94e71e1438c5cc25974efb3b8ccd03272ea0218f171b01c7fde17adefe","priv":"587f36966f566888d5684aa983d86c124b4657ae02e7d540939c5265ca50ae59","pub":"03cc82a5871dbe05fc52fa3308bbde84a7744780a4c6344910989437b37b59a0c5","addr":"6fcc01f30a9e9733ae95a049ff8b3ae0ea8c97c0"},{"mnemonic":"twin over wire boy dragon drift erode human shy minor panther library","master":"1488ced839d3116ec99c8d4fef9208224ce28d270e4d3242999e8c3d1bcc1719","seed":"099d13da6ce761e666e6df0199a79e95e83d0c911279aebf8037196af6c7070dd08867dea0da8d9148dde2d14ac55864a7dfd09464282d93037aeda70520d664","priv":"1c2871733b9b2fc6224400612807d75387c37b87b925caae6486b777b0dc1e53","pub":"03496d39cdb3d666703b041d5bbb69482537addb552335c7f26d29e09d5ab8500d","addr":"7b89136f5fa6320f53c25a260b4b75eb5bee5774"},{"mnemonic":"potato lecture exit color target shell more push day catch entry erode","master":"a44668b008915d6eb656347398a007187c18cfe766ea167a89e855a77b9b9c37","seed":"815db5e7fd253567cffc54d938a3fd307968b45e95407617c55201d661f2ed581e92f86a1391154e6421bcf04487da1d3c098382a3587e8c5679704407812fab","priv":"de5ca4846103dca9d947e7867ed764c9094d40ce189cd2366befcb557325616f","pub":"0342ebbb943a1f8100441035ea11cf76c17dde7b7298d160ed56e3dc8fcdc7a8a6","addr":"68f2cf5a8b290409689d5e08f99cf1b882582e06"},{"mnemonic":"grit flavor pass apart swallow quick payment view weasel decline travel hat","master":"3a2d8a4e041357a246be12beaade6b6c36fdab6dfbcae0f8230106a09c5157ab","seed":"a69ea95da4c681f004cd5fa6d357c39e50594b66c73a42a93672c13d6dfea0ff0d741bc1b406851c36680895a8137086f6de132d2aaa47af5d4872fe08818171","priv":"502b2d14765f2f80f6ee0c10b98333e498dc7d33a46424555f8429488d57de1f","pub":"02aea2e315932b900ac7e31d5b6b82e9966e45b098dfec8990e2efbf4457e581b1","addr":"c6f8426ba017b6ac4fd45a95341e760f158f0e41"},{"mnemonic":"machine insane tomorrow island assault follow verify spatial pizza major cannon inquiry","master":"be46461a96c733b1add1465d664d74b8e1a28fc1bf25746b9e9d44ddef81ac4d","seed":"2a5d713bf4b71dcb40d0526767f8466c87f04ff5b2fe38ac17d5a7418f099b25761917cddec77d369471bc22a1f26d2d7f6fcfb00b3dbb28f08279ee0ac85f1a","priv":"097be27be2a0c6960b436acd651792cff207d877695acebd02c088e6f3617b9e","pub":"029cde9790e6e1b55d54aacbfc6d13f09fd6b5b04976d0ba5e01cf25da0a2c3976","addr":"06ffc6a5742544cb3a66bf443ec0d8894e5822d1"},{"mnemonic":"plate grid latin above champion demise idea urban raw exotic day diet","master":"9daa2224bd8c15a22941090eac1262e88dd2faeb708ecc00f404c88723bf617b","seed":"e07adaff2724a1af34ea6f3ef3e583086fa835ca126f731875f97b366322aafaa8d39b72a22dbe70bce68d8539f1ac109e3af03db42317f3807e91c35748438b","priv":"423d528c82af34cddc13f8873534984302e072e0aabc9f29b10c70335bd72a3b","pub":"03241547e0145dfbac8bbd5daca05314e2fddcc22aadaa8b49952e461fccce7d17","addr":"2c1ea451fe2233aa3d2120f2b836d11cba72905e"},{"mnemonic":"august quality apology more ring armed hamster raw gentle inhale angle dune","master":"90478d31095fcbbaa751055f7d9fc70a75a8dd34ff825f1b4547103e3367ff9c","seed":"0b944522c472688010098bad62a38a173e0184f64710bfc370e8ffd7a3e2383d630202f52b7ab9b8d41948f534b2bdd0e2664ba76f2e460fc62e73fd1684ff16","priv":"e8228b2ba4ccd5a22bddb4e0a3eaebe6a156ffef061779d264b905c90797826b","pub":"039fe65040d933902f33749f3d43cb924c6df298a969b05760bc4c8fdfb27df444","addr":"b0370814a3a0390cb3874600ff1dd48481725ce0"},{"mnemonic":"argue april pattern jungle favorite shed silk adult file cover benefit neutral","master":"3d5f13e3264550f14ba0edb8b693e7ccb5e74789359a7cf9b7f819654542acd2","seed":"f5fa70f943ebf5b941574820d4b91a1ce706fc5f9849219b7e2e0f9fb410c4bf81494beeb390383e1371817a39f2cc7a9552452d973ea8a15ab42b881c7cbebe","priv":"d0d2a3c92a4b1914064826c1a9205ce8bcb076109ab2524a2818d2ecaab08420","pub":"02040f9ca1b771a4692ff543df77d2fa8fbdd9dc5817789b1ac491a9e0908638e7","addr":"0fa135a93523a80e03603c609953a2f5c7b799ca"},{"mnemonic":"oppose describe defense consider long lesson better kit capable taste feature reward","master":"07ef0cb309577396089c024c1b48dd278d0575aed88e63ac99a44d531fc919f8","seed":"c6ab42822e1fc062f5bfa6e5d7d4049a28be293748858bb2062f4b9a3c20cd30dd02e7e86dbaca2c77bd2e1d837247cad63f8009f9f9410a0365ef7bbe647727","priv":"3b82e67931a96b68e6752ce67c1f971e23c317f8829e2573672edf1d80c68836","pub":"0248ad30caf9f25bf49bafb519ebb3d381ee9c95a6da6502e1cfc88a4a1aea3b37","addr":"17fe8e8d5f6a4a10a2b7f0323cb6ba3bdba9fb93"},{"mnemonic":"blouse patient surface urban stand clarify old pipe where spatial cargo shell","master":"8ea8f4837a7a4a3bc100595fb6dde65f319e8928e61f7da3eea2309169b9dde0","seed":"a7ae3795447825e6d51da632bbba6f8d9f5e141e593d2a78e05f7e0914ed063d629f1f84d3427e7803fd1e317ca0359654bf918724705f523e2a896077c39603","priv":"6fad450edfab3300ffdd65133f2973fd0be3daaf7864e2f357598b63416a01d0","pub":"0211cb5c4316de9b5c08e8764027f9dfa0cae026cd9ff9773dcf524c06f76c08df","addr":"2a51a4f2ba38e779b20b7a4bfba78e8267b6d6a2"},{"mnemonic":"moral penalty ladder step panther divorce bus adult math various speed rural","master":"9641e82d742f458ff81d48d486e38cbb8919a56b2a317d822674ab9e4887ea6d","seed":"8b4c57108bbc2c753be29e0b19ab43b06c7c81e2dda243535f74c08222b23789d3aee754e23ae936df99c8728b04cde066b6e6e512b54fcc1dac28f0b0763074","priv":"043dd7b6ec9ac7f52f1af6f3ff95cd99371c251680c04b3c847da42242d152ce","pub":"025f7dd3fc53ceb3ff87c2bfeaabdeac1d5f1c9b8a897bf4a28ac33b95562e4f79","addr":"9a61f1c15e55009122d52a1c3917a8459fa29238"},{"mnemonic":"pony liberty split enact quick arch mammal velvet cart wait arrest burden","master":"e5fbd41b38aaa3aa643a66aba1c3e8a01709b15f5e1e30d639db03dc87151065","seed":"b6a41b697611cccb9e117b5ce798d47bb37ce1e07341cfe972905a4b66c4b7f8596cd0e6c21e0cdd221be33de8c0a5854c5f8618df36f28d95dd1dfb0f31ea1f","priv":"7e98676864a3649911657e32afe07f6ca86dcac164f4a25e48e33cb147ca4401","pub":"03d61b29c9f5775c6d8fddd6babb2b8e77b65fddcfc14b8c8f6db262285f2d1832","addr":"36c7ac440660d8a8642d669022d621ec1e877680"},{"mnemonic":"summer envelope tumble six bar crazy forget very canvas sign inquiry copy","master":"4c8765857e92661d69dd8f64031d43df4e1043c786f1ad7593d9d6cd7967b9eb","seed":"662aadea06a5198cb230ab83449dff0514b2addd644ff618647ca788cadae3872e19becd5e8de5719e3397783cda6ab0e1496e8a204d3ea8ad524ea93a1b71a2","priv":"a1d833122e4bbf53a23695915b9f398fc8681f72cb68644ac78f5b0ed0b0839a","pub":"03620a954c07b3e3060414ee499f68a904a8afe2f7f3ada8a9db2e039302a1ac0d","addr":"9758f18ede0279601ed2cbabdc5a87e0858c0f01"},{"mnemonic":"robot lift decade april style rapid thought modify tenant wild pottery cool","master":"d43dea8679ea3ac6440623974b253ec2355e97697557c8d62b5a79eefbac54a7","seed":"bc1a90f5410aa2fe22248c19110d3bba802378c5fdf2f3a2eb379c767b3d222fc2ed5d4638876d51fc9b44816c229673694b3f3e8052257f574ea50fd6d7a73b","priv":"fa29d04ce0480d48e6793e227e142330aca85e4e91ee9488396b1b2af13aa160","pub":"0342e19701eeb5ce20b17397457db9105c092d00db7250968ba38a551fb47d3491","addr":"c8ae52e691ce5b507a152f47970456570aa6635e"},{"mnemonic":"invite pool cross silent empty jazz change smooth appear snack cloud lawsuit","master":"0ab641828b6b935da8bfd58e4910c6c3fe8cff9d18548f86bdcf7d501875aab5","seed":"4aca0bb1ece15e686bb9f08a0796eee1830b9d926b0daec50aa9e280ea8eb522f546c1668cc2e2a8beab636eeeb992569a8a8b50e2082b5cb6bdf3195a2e8376","priv":"621bb83e46364ea7bb3a1942dd857213f49077ebfd735ef33095843e11866388","pub":"036a6b24125e8cbb887c0e9806e5feb6555f3ad4042460f1ed85e8a5738a02cd54","addr":"24f1dc90e9321c1faa33d3b2fe82665b402d4e47"},{"mnemonic":"current exit average case novel nuclear recall unaware decrease maple bind acquire","master":"a0a9d482c7bddfd3a8bedc54779098ccb0c54829e7949b52969a76f4a67f1ee4","seed":"35f2474be8f9068d91047c19ea9f1471aef87eb868804c5c205692944bdd1a3ac62ab71e052047961946d9c371da2039e89cfd77aef881d23774f10b24c3e16e","priv":"75684bde10654605f673ba3f704edbc2329997c9b15128b5640b6c4e3ca366af","pub":"038617759898bdb797d411a87d1e55024fde8a1a65c6bc0391a8deda099f6f7fb8","addr":"5785b3440fbc82cef8b1fb97c8f8e62a590b1842"},{"mnemonic":"tone engine property lion used spring enhance need choose grid deliver sister","master":"a0b23f0ebfd072c71a27b964ac5ac2a58fd31fbb1b22c044631fae01b27a425e","seed":"e47ac6612dade3bab1613b016b271eae20948c7934b08d8ba5ad0d14da1417b27512550287853c6c71efbf023b8026d015b063696d562850b991664ea8bc29fe","priv":"bd8279824526377e70a20ab1ea2731f815ac8975ec7ba5dca90d54859143f409","pub":"02dc15779fe271cc197da7035bb0886d2b44026292c137f6cfa8c98624665b383b","addr":"8271679fe371b6ecd1e989a2fb2d7c8d981006f4"},{"mnemonic":"nut solve indicate dolphin crush bike puzzle outer mask bring dutch city","master":"0aa08b93b1e497f4e54d6caaccc4769e921cbf9cc155a5b8877beafc43884c5e","seed":"c7c692ed2dba467ca28d1249f4d39a5c0405a54131245312d05597ef2aa31af3bc6791850693123f18cb1c350fd79c1705e53ffee10a501b82d0cb237d256579","priv":"8f9835b154157f65bed179b6008a352b7ef7d5ce8e21227a22c461294a7410c4","pub":"02da01e33c91da079a39cf256db26b1254e132b894abb9f07bf01118b5b6edf486","addr":"3ca1fa508b336a46f89231ad841a5a14d026f5c6"},{"mnemonic":"inmate snap bullet curtain used blast fatal one join owner route absurd","master":"e4003c062456105b608885d8928bbf183aeef12a48d6e3510dc7f183514a5195","seed":"0402d1974747f32f00e4cc90795f28d6e07a12cba21f31e22e0eb269ad1dc5fc0ad5d6ed1b5d5268dc50e31fe78b7145546de0cc1fe7afec7f5e3831863e21c3","priv":"8e55c05a82e8fcfafdba94b07dc54940cb247eebd1c689b51170f4ed10628a82","pub":"03637d8eb1c87329d9367ac73d1f65e482bd13b072d791f5fc6c08fdf262afdc8c","addr":"23d0d3d1abcb6ec683851d8c21a1ccf5941f18d4"},{"mnemonic":"useful panda fold short about copy hurdle vibrant kingdom draft suit cat","master":"9c99df0058969798ccdfef6b053f61af2b6422e4c691213f1f0a59f4792156b4","seed":"4fa3755fab5aee41e0771c00362701451ac578a9d7f8b139d9fdc043b33fe3566576a7942b904047978bf6a6360181187d9f20bb3475c495985e39ac7fcb8987","priv":"2b65da5f7070729879787dea803a4f50e2df1ae69c39263525bad0b5c994f86c","pub":"03a457cb29097644eb4a8eb1713fdea43d3992b2b88dfd41fbb417845e2d373ce5","addr":"901ed83b7220c552c69c43d661dd468ed94ac9c0"},{"mnemonic":"intact pluck author dish garden frozen speed grit bar narrow across loop","master":"548d4844add02811ea1b60ea7a6c337883e818ead83782a7b5a652ac038310c1","seed":"6b3b40cfaf38ae1ef9938c621264cd373b7e15d196bf9c69ed6efe3f7a7a13900b3c89eb915fbc99457347832ef1b816da26cbdaf8bc48c2b8a634fdd8be2346","priv":"eacaee29cf8bae543732278774ef2244e4da49dac3d88fe11fd7ff50875ffe8d","pub":"03d4d894053c398cb5dacd431a03c673a4f883781d951254fb398a24de018c6110","addr":"0b0840f26af38181ca7f65b7fdc0a3309c28fc4a"},{"mnemonic":"equip energy remove soft alter mammal valid van ordinary motor follow buyer","master":"6110f719e36e14190eb39d4ae66ab2b35bd5c3fd2969145fa3881650556c5384","seed":"74163bcc1522e148a87a95c78072359a600b364eeb558d052b722e5db26b6b317a36219edab7558cfdbdaa6d62c7b078c691fcdf2acc493139a75cbd26ea3bd6","priv":"fea286b716369fef22c1c5ea7da50ad612868d81c50f5efdcbc2891e21328a7a","pub":"0269bb65b5d86befde40cd916410790f9a959c2f3aa3beb5efea2eb358eb5047d1","addr":"9ea73e16006fd30dcdfe1ecbfd2792d5001ff8a6"},{"mnemonic":"limb boring random already marriage team useless polar impact equip rely sunset","master":"20c34a5ae5b9f78bf032d7841469e27002583c800d4aee849860d58213210c39","seed":"848bed01605f3574c16480514ca0cac72c21412fb6ec38833f97fb744e4a975fd06135c4761aad05d73280bf2e1c8297769e5cb69299bcd99e638e4dd542c52a","priv":"59f09a8926377ef066a13627f032d2e700795976230ff2e58806d046af0450c6","pub":"026e3e1e7ff239b39eb4a77477b32d492f99cf1f611558885afc7363f3173a8a28","addr":"61dffa0563d51aabb1e2e585bd444f99cad8d54b"},{"mnemonic":"vapor reflect friend jazz chronic supply awkward tongue venue finger island brass","master":"4dff50c5a87bb1f9d2c0392ee7eee59977bceda605a40c0a111ebb46587a0ab8","seed":"e6f70f78b981254b4e3061270fa96d262d2fccaf8dafd752db2d0fb54f943ca99f49eac07d279b5875432dd7c0450a7bbb776e8852e5a5a82886c65803ec1698","priv":"50273043958c3d7cab07f41dba28080c507f460ff920c6b5b135d1c64dc85469","pub":"03ef40a81e58c08d1bcde1116e9e748eacc38906cec057f2984fd4bc91081492ac","addr":"a8aba313467ada95795757ab9a6661395adbbd33"},{"mnemonic":"top base town abuse shiver symptom green thing vast eagle steak warfare","master":"7ae7456584c905376b6e6f6732b8890baf4d768e82dbde95110effd229dabf9b","seed":"f88b915dc5753ee33855b3adfd292bc56f04e8aaca117023209877ac8cda5df3218c969f1491bd0eceba11ac433016a05a9aa68d6bf3fa59b51a5cbb224c902e","priv":"ea68890e0209f3444eb78727cd3f13dca20c886e8bcd6d31689dbba04d000a30","pub":"02030607d8a2bd18f8af9b67f99db31585b7a879d6f08588aafbd18dd95d1cdb7f","addr":"fa202ccc3db92eb55d45cc79891bd4be395fe4f4"},{"mnemonic":"picnic seek ivory unusual text become room artefact rigid unhappy wall harbor","master":"05638878665f27362c8165adf4b73fcba3cedc983be2f0897a333378f53377cd","seed":"8af253d6d848e9737c8b7807d37558e5a1f09d3a14eaf5794c83c9d4f2021166aab7faacb967eee25714553003cbbe0c0eed9487d4499bca430e709f0b8d219a","priv":"1357da6886941f1c50a19bc3b32a174acccb21a0415dd5a736e5d679fe505f0c","pub":"0333d6d3cbce04e1ac26ffc7c2d4323110a038dc33ce293e95d2d34d11bc1d4efb","addr":"c5aca5f8318f75bc143edda3eb89821e751ce0e7"},{"mnemonic":"faith box profit long entry that alley stereo wife nurse tiny assume","master":"67457c024bde2135b9493124ed03d0f5f30a66530c958693f02e463982362395","seed":"4e22fc62d0a60e2de3ac33de2db8d4a884905ef84071b190f8d43f57040686eb3476fff7a90d19b1bec66d8a2e62532501ac7914585ee5272c352197ee0f0ead","priv":"ba198f97576c66c34196a36a04172bde332ea3c6777ba1af203b68aeae3e23d1","pub":"026aefd0f79219acbe5377bb3578a38f71174dcc9f77fa4d1dde3f3aff35ad2f10","addr":"44c4ffa77990259e15f2b9dc59223c5807c85f54"},{"mnemonic":"brother bar food vessel shine object tape acid opinion brand indicate local","master":"23338d7c853f4e76208d97bf0c47db2dc317cd4501cf00c037e60461eb373353","seed":"e32c6c54ca4fef48630e4dd7927634ff1d21c60fc488e6f1b87755d3e79f4845a3d9f86ddfcf185136150b52dc2f721b04f2d61913d63461956764487fec24bc","priv":"3d410ce752789e05c5e02ba5e95c2765f77208c90cf32f289306204f82d6eb77","pub":"02a795076f39164eacecc80ce04d63e5336edb32d183c06dd81f50e330b6102c11","addr":"b2c8079676ea7d98e10b24d9a09e3d4519d32d74"},{"mnemonic":"broom together virus run require inside output spray day hour cruel witness","master":"3ec636201f4b0a0fc7226003f1744766875a0f8a76e19d69c6c352d86c672cb1","seed":"51bbd8710577f0a2eedac3e341727d975b0e79e2a0777766d43b0cad8b66e302d1dfeda04a6a5ae0683db18955692aebc554c4bcaffb5f9be9f4db079a550f78","priv":"9063c803e2075922b916efc668be57b734212ca8ffeaca221b587912426af4b7","pub":"02b66afbfc48ab4d97a0965e7c96582d2c4cdcae965f8aef72ec98f59b31d5eb7f","addr":"b18bf07d9f82f070da34d8a4e58fd6cc4125d51e"},{"mnemonic":"crash knee output divide essence fiber benefit pig recycle patient strategy already","master":"eb84eae9a804895edbc89020995755aca54a04a4e7b59adb96b2ad0a8b465a7d","seed":"4aab7e57401b6f2dd6502dec26ef36e36d712ce328b5190d73b9055a118c5ead12dd5f18829affbb488a71f18cec672093d58452bba1ec3775739c1169901e67","priv":"0d0ebcf8cd5c075d9b8a2d2e404d44701fc1a5dabfc5b3cb50cae523f3c4c149","pub":"0296e9cf1cfe73a4114a1afae2f05a6a92da168113764431fa57c25afe32258d8e","addr":"8aadd8961827385dfdda784993f8f135a6678a47"},{"mnemonic":"shock assist horror regular voyage gadget cook pipe hair boost release stamp","master":"74b514c25d4fa22f3ac95aae2e58824da6ea181962c52944256a8b80cf86e980","seed":"0a13bbed1d4d3d6128d1eb0bcc0595a4c72701c7e9b79ee6110a104e10e20656dbbaf2993a7a06381e9ac424c3db6b0e98be6d5c2817433660256becf295c70a","priv":"75da3f78a45cfc4e9318d5dcaaf6595002ed037605ca196282dcfc18c5e6eef2","pub":"037187c0d2d573d9c28cebed9214ac37fe20c55ac56ba565fbbf7dd79c4eeea519","addr":"4b79f08bc7daf43ea00b5ad88b7642c31fdbdb17"},{"mnemonic":"monitor artwork plug dream sniff sketch oblige prefer dentist rice degree trip","master":"e8211a763f0b7f2f0085047ec1687f9c37910d27d8580696ae843872a7cae0d9","seed":"0a48851384b8dd7f8c99bfdaee23b143479e589bcced7ea423f6fc5bee68bd5e5c45834e3f2a7a1fcb928781e37e2b3078d683c15dbcbb5032ca31d3425dadf1","priv":"8fc0e10b570558eac1349ca8ef4f47b2f6d3f148a07b94bb2f1040dcb9bf21d2","pub":"0341374d25e701d963aaef0316ca0b4f4c15283f6b8b6932d954cdb7d7af4d7bd7","addr":"9a4cc3bcd48d6998280db5cfe856f7ed85d6b4df"},{"mnemonic":"bus deputy eye shell isolate judge nominee later gift mouse leave square","master":"cf814d6a08c10f4f771f670120b52cb26b6265a5510c5035d5bab583bb7f314d","seed":"9974e3131ea54805d6e9cc124ffedf80b0ebf935cd0908c4d8d7a3b777220155c056f12a7cf3c0c6e58b7adef792215cd471c080e9f11ab6cd4776ad86df9544","priv":"ef857601132267606922590b016b10faf2405f7ff92e3d8dd73ee6843f0b3707","pub":"0317f408e6be956b15a8e9706287e6bed905a008e8d4705b6c9b6e7f478bbc57e6","addr":"70cbfc88189721a264c3d21bd01f2eeee8a245bc"},{"mnemonic":"toe present claw afford agent render direct december model skirt tape soon","master":"88f5eca5b3519ed612f9f7b15ced098565559b85db98cc57979dde0ed818bde9","seed":"d776e445d7541e997584381b5d2eb066b99644275814961daf748a76a84898c21942f23837851d387f0fb6557a0f693d98e4d23214ed34630bd74fa808b36668","priv":"6252b6cd338753e5cb6745e7ce92bb661fdd373e56796722d1766def72b93ab6","pub":"03dc54c14b80e91502c400d6a97562975ae0f967ee0a7cc5618ac0330855ebc688","addr":"afdf4a2de468ee8b2d47de70d52ad9a3239b3f42"},{"mnemonic":"save rich wage off orchard unfold call frown idea jungle boat oxygen","master":"dfff9a17815e298cd92e9a2c5d4ccce14d3df12af9b9c69c4aac7bd297639ec3","seed":"7d25dec6c87f92e685124b901b0ad423ca3554c31db8583d205ec4beb3f42c4a14777ff4fccf830f5641ff4c376c772a8a1273060d58c22b95a51f9daa812a2b","priv":"5e962f6e9e6e9ed76b0f3e3174ec9639996027fb2bec3fb47faed79e66c4fd6a","pub":"020b08249515846a566c2c9616894ddd6c2239c58077ccb2f2e7ec5a8a140ef293","addr":"dbcecdea56d7e5da2a6c96c1f36242e87416f221"},{"mnemonic":"claw ketchup mistake lesson drill crunch unaware captain perfect spell endless manage","master":"bc0c9ff880973352267788cd2e1882dbdf5613a8460414df0e570a099321bcbe","seed":"4b9cc68aaff0b0ad24c531e990f9a9b7d7076dda27cc2f21e8e75bce8f65f2daf1ce6228130bd2c8900fc677313ed4cce1c47eecf24fea0c119f70ad6d3d79c2","priv":"e36db8076b37e0d3785c550e47ccc91462388c8249d160df13391ff06f40a30c","pub":"03895e970001fb0b3566d8abcb1a3df46725daf591e6cf981c1f06a81eb202692d","addr":"6548f7cd7b619dcc8685e59456ecddb223c0bc45"},{"mnemonic":"canvas black between chunk wolf resist again joke club moral fix spawn","master":"374f2b9727601f87f72b70014fc10a38c5fea6cedb36246103e0fde2d356f7ab","seed":"217881b165a67d70c9ed44d81a1100cc829f00a0b3782d8ccd8429806b883eea17f900ed32927a7c8fb8df34d75d5264cb5704208d3dc336444c199b9cd4bd1d","priv":"7e6c83d4d58e7a55e9882e6160238c6fffebeaa89e86dc9785fb1626fd22e8e8","pub":"02795b9337e8dbaebd288d1f0d833d51a4969b0ff995ace05c329fb6d20ad82425","addr":"7618cb9305c15c8ba122949bc298b3d6daa43ef1"},{"mnemonic":"dismiss rubber stadium badge enable exercise collect globe another survey own hope","master":"9da347a5c2a00a44e9bd39e50d80c106a9f885f8c84f5c4d90a0a75dfa5d5508","seed":"7038ff726fcba91488e5fec28d436e7a2e7c462b06747769f79b785aac64164eba1ea5c125e6196b9430139d9e21af8cfe10b51a09577ed510453487cc1f39f2","priv":"86b04f6848114854a1b207b44d9475c216e63a9b051c44bdb7be3eea9d24988d","pub":"02c6e822bfe6255d841eae33f62987f9cbeca84eb8dd1dd02b2daf9c7de7f36371","addr":"bd2a4f087a519a3469cbdaed704221385a07acab"},{"mnemonic":"dignity tired drift feature file salmon vivid wife faith title direct toy","master":"ee03e61a429a846453557f202766fcdd8a3b408c00f3430f7b3a1c9bd88a7d11","seed":"baaeb3a06b419a7a9c49a99e712c11e87a7a4bb34b26700b1d57e95177dc9b6b2d590878111e14f6050e73e5c72239a1562062d1b8e4c8ce9ac158aac282c2ad","priv":"d1dc95b42024dd0c10e8b5f0aed5e5f7c9ad0d56636da91bfa910d6af2124969","pub":"02e1f4ba20c8383bf512073e335400e1a1b1a103cce9450864b9087203dbc0e027","addr":"3de51323a7d40ab752f2b0cda1c17d51cc477369"},{"mnemonic":"legal sword liquid clarify utility depend romance cement trash whisper endless parent","master":"7c61e0c0e85873e8bdf532ec5906b8be283a002114b8dd4b8d0154054b6f40b2","seed":"21ca62d84191c141f6b9890627d6d216d5373ee0819e7c618e4027e70395c2a4ea5702aeee5b844a99eee4fedb85bce72f7d5f57c3d670308e1fa484108c4862","priv":"d6ad713c9dc2cff3e55243729c56485fa34ce8a75c4e011f40762ee000dfdcf4","pub":"026c7a44022f2892f2b2b091bc1488e547b8b52c82c2a780dd6603f40261930d3b","addr":"c6c4dcf4763d9908a46ddde925afd86bbffd4719"},{"mnemonic":"tragic inform salon lamp tree deliver sugar robot torch collect choose nurse","master":"77e88aef57f8be3507ce43c1e47dfb86ce0fded4a6d9a5ed6a2c6711a0a83216","seed":"6670f6815a2865591e6f9ff5c1cb775eed9fd45d53d1ff3f65937425c6bb79403862a398b28c7aca032fdfb14f96b238174cf6353776321631bfe338029ac148","priv":"7907a31525b26f89eace8cc0b988a08f8feff4914dd8f692e24199c4134c6fa9","pub":"031af666b3e8d5da1684fe5d585b8638fe46cff1b1fa01bfde3b2b8e2ef2aa3a58","addr":"792001d0cd191121043ef1434855b85b583ecb09"},{"mnemonic":"common oxygen toward security mixture swim elite issue suit welcome ripple online","master":"f4b85ed364ae42dd7453f56df2731c194a203cc06a8bbf71a2498424d7687631","seed":"9f2217e5ef1a8691aa51e914411a5ef5bf70727cfc7d0a932e1a9f7d298a657db8f2f6eeabe881e8f4f4580a2bf1834ae888cf7b3bd32820448007769b310724","priv":"2f98bb40d987f7e50966b15d2bfc89befc72bb6934aaaa2293dbd9bb33923268","pub":"03b89c51d6a32cdc56e334997a0bbd57deb010778d62024f5012ced0ae184e2464","addr":"2ecc6f88d71e3b1344a7fdbbbbe4fa60b5e539eb"},{"mnemonic":"kite warrior idea engine trouble swing route main like burden divide drive","master":"8317ec95801550a748f5215d6e83cb12424635d5b2f6635a78a4a0311cacc56c","seed":"f406f2ef34c3a4bb64622dfc4496a0b6183f1b7c1f58bd28d3ad863ccaffe171bd6164044ff5e940650a6bef6c290279b41d80336cbd9592c1a3b326314d44f9","priv":"4fc699bea9f32362f74b1cb6e445b1a8f3df81dbf1d5333dabcc84305c355e9a","pub":"02f8b8958f9edce19f8c5a50371dd079ec4b4ad6f6a9746451d4024ccd266829c2","addr":"8fc3062dd0b1063eecaccb75e14faf5b06cbb939"},{"mnemonic":"toast health connect merry resemble slim address pioneer crop orphan keep dune","master":"07ff519f3c3fd08b9de16a26197914867d4e42b67222c9ce863ac6b176bb5909","seed":"5e80b7b4b8b388522fc283784f368f5f7875ff7b412af6c3e526ec1426ad4164e0f4921494ff28a258787beade935d472cbad9f48386c2d7e16f8ca76fce769a","priv":"1158d4b986fa7e05db824694ce3379b63f473161c965a39ca997a8e3f3e7664e","pub":"02a3a7b75a8532df2afd58bd2dd434603c21a0aa4081f8ef9798db401372e32bbd","addr":"24c8f405da27ad41be7b0c62db63f80226fd6b58"},{"mnemonic":"cube shaft clever hard fuel review enhance short nose again banana profit","master":"30f3fe7efee7a0c7eea064bdb63f509182f0dba45780dcbebc5f3374d1b878f1","seed":"93774eb188a6ef898e534aaf67c2ec9aba02f716eabc0d193bd5a035ed8e0eebb2e82fd3ae30bcc24c44d697d46296e5d307060420350a4294f3cb639a48e6e3","priv":"857bcd096012a98022b2d30cb926757f0afa9465058c103b70fc931554f2d360","pub":"02ccbe787178d64d347a4f146facea95d2d01cf353ba04cf7cf7325fba6fad3824","addr":"d3dc220b0c09ac018fffe2cfffb220410af0c0b1"},{"mnemonic":"weather surface use rotate entire foil female carbon once kit seek athlete","master":"68614cd2df975347ef5c7efce4e416821a1f1916ac54ba994f6d69f8f2860576","seed":"478f798d52999208d3c8c0feffa78c6d56406d59800a701c996b8c8a9b193494aef1881e2d1f8aee0a5973b722fc3bb3ba007187a377a64b13a81d0560cb090c","priv":"6671cf2b354b61f6410500e26cbc94afe78392d3feecefbecd6e60c6b1a33a31","pub":"032afb4d170e89e8c89c544ebb404678bc6470d26bf68dfaa1c034edaa85a9bb5d","addr":"2bf3d54106897da2427b1c4c85de761e4546564e"},{"mnemonic":"car rubber ocean miracle vault brave goat eager dolphin various infant receive","master":"fa86484b17c9b62008647587f406f4daa107c6b95e708487778865c76a31e330","seed":"ff824d733d160e50a156021b256e4663f9ebebea1530358d70c205da5e7703d64ca4f3d941043787a68fdade5143d993376b1ddc9fd6037a13520e8cfedb790f","priv":"bad6b6ee0a3aa898466552b2e5df05bccd7d0861e3368f206d8cbfd2ec8e47ad","pub":"02ae2706cc6a96f31da9cd46d544ab142a26ebc6259e5e807065fccc251b26c603","addr":"a6ddada02b29a165a86a8bf4a01e783640e5638f"},{"mnemonic":"segment nothing burden boss obvious find kiss join science dinner clip wrong","master":"64a4c932d3cf62f9bcfe86c3b709ead38ada505e944322b93e14022c3ed26e18","seed":"71966dfe2434f4dcb2cd1bec9090ebd20bbeac2ed54dd8d081a548ce7eb57f1b17cee242581cc893292ff9ae4e5526bf9e11034688299753a6d0bab024ae9126","priv":"44ddd6571ce3582ae17ca9c74ed41811a760c7059dfa7ee88f9ef76960e30328","pub":"0288341429320e6e7cc35df266cf3929e93e843e911f8ae0ebb2634132de1a6f49","addr":"4f32c063b84f9895d4411ece5ba0c9d2e94631ed"},{"mnemonic":"cake volume physical initial phrase false pear poverty bonus steak rebel ketchup","master":"8200ce644e28680726ffeaa7d949e23feef136634b58d504e34cf8b2bbaea439","seed":"8f6577cfd936a64de1c2be553f66b8e5991e2cf30c42181c0f7eb527105c19221268e3268aa243f740733748dea3c0ac16320305c401aef7cd0986f3dc6ed978","priv":"ae37947a92ab4e9ab9b4e24b5f26f710725ecf848f0412b583b8701dce4b7730","pub":"02ba33804bdd8733fb5ae1ce1758ca55c8bd9e15245d646e8f737da2d61758ebf2","addr":"1f3833c0eefb3d46c693b0476470d97abf02a792"},{"mnemonic":"outer meadow velvet fetch claim forget token fee gadget alert post pelican","master":"a991420cafd20f348c847780fcc2128888771f4771cc6ea137099616c617b1e7","seed":"35cd93e8d9c4651799471d4cdf2a2fbf083088b93f1c1bce6ba4394ab6239d05c0bfbf8d7f8976be68042e1c8267dfa7ab3008c967f8d1ae0793190c77077fa0","priv":"e4fb166f29590fb4a5c5484729f038a62aba50fef189f1e3769fa290e1800790","pub":"02e123798016f5eb1f79f633588051def8b59c27fd3973a7f2012db1a8fa508ad1","addr":"45a62d3353b39439d002c307c8789ac70adb69ba"},{"mnemonic":"flip expect rule wrap cousin fade example ugly crowd monitor cattle cable","master":"d5c2521cf1c8f3dbbf955477a993552cf7f6f0ce452bb789806daa0a4dcf192a","seed":"b08a8f7dde39c9680c07ec31ffe80377ea915de328fd38b81525e4f694ef0ceb630e7ccc19bd28a03b7061b194f2b7758f802945a7e556d526f25bf2b4d5fb90","priv":"21a41b9d3ca21569e3b8638188633a7be8e9b54397964a65bfeabc3425d5e4bb","pub":"03cacee92e7116a6012c2b3002fe67d00dd062e937393895703e010d5ada98b4cd","addr":"b3a4f2cdb4cdcb64f1434f3f1e4c20bb8b952116"},{"mnemonic":"alone absent senior wisdom sheriff siege harvest coast van skull want quick","master":"74109213fcb3350c4ebe081116bc7570d00bf49cc7cbb90cf3b09f5d532a3d97","seed":"7d111179778ce63cc39879ae303814acc25afca8eff930d3ddfdc640d7b3d8c1140429a75c6db52db96564aba0bf0c8d9e4cf78fcfd703c1d219c09a70d8569b","priv":"96c3356e90906a9b3c523a3ba61d66ec63d9bad5ccd23edf923e3c5e4c995774","pub":"021736b932aa1eb90716bd8bcf3cffaae73392a37ec114b34628367f8ecf1b35b7","addr":"e8951735e9840492e0589a885968f12b044067de"},{"mnemonic":"fall any bamboo energy ripple flag rich arctic argue decline auto pottery","master":"4b3fa55e01aec7bc6d41a890d8aae2d69e617bab49f8529beb38aaf835d15a69","seed":"aea9842051221d0eced61932fd18a5f3e1ed8479159c40d16e886699a0f923807b91df0763a5d9869fe9a159ae0453f8d651302a186bea4ffc120c2902012d3e","priv":"ca5c56fd1b4e7e7bf623032e17a186e20b22fdd49a4d29d9bed5edff206bf26f","pub":"03a8fd0ffee636d66a64cdcc6032214efd1c069491085053808d03c1ae83b9fe96","addr":"ced9d32eea230544e0f8095b39b0a4e18b59937f"},{"mnemonic":"over exhibit wait carpet pencil record post duck gossip vocal all wife","master":"6fbad4c20428a892a365ee50dc66f8eca7773dbc5ecc34f85619fbf1a73822b7","seed":"f998a57ed4eab4d8425d4a71bb1fa451d7a79c8dcad33e18f90d6a4506f93b2adffbf3eb887adda7669c0108e444548a3566306264a76dd4b0955af27cb9dfda","priv":"bdfaebff9d0fc673539d8be5e59907647d0050a9241dcc4aa24c5c26eda0fa60","pub":"02d32a22a05926844a6b0f2f677520bda4c54e6b2c9269ac91127b626159a9dde9","addr":"60862548d4e283f62ff8aeabec3f25891808a439"},{"mnemonic":"spell illness engine habit bike able chimney spoil know nice tunnel weekend","master":"ac366b29da09441f12742ab837cab2a4636e1b50f11680c4e1adb7d337dfd8da","seed":"59e69d46ac9f2a9edd9b1909b1e5ad4b9fd2b401d48e95eb43a0f4f2bec0e6c60bd2a263e58bec77dac6f6ba45db1345cf9d74593c6e0b5ebe3fdc7c5f24014b","priv":"05d077b8eb1163a1fe2e5eb3729ffc7c1327435d4ac48db86c6db5238d5af45a","pub":"0364973fff68be7b91de7858fb35869decac0273ccadd7ccb45b057ad7d7e9baa7","addr":"c59c857a493b2b81957f4769dd9b7b5a934acfc4"},{"mnemonic":"thunder fabric basket stumble file sudden effort congress process essay excuse practice","master":"6c3de9715b71139a3a352a1d0b272aa0152402db4b8429c32654755430623ec5","seed":"eb8d579bad88d416336e6ed882bd8a57474cc5ba30d4a20e426c29a78bcb27255f6a6cb50b6430fcf905111f9b9fe4e3d4920d563887dbba69ec74856ce4b79e","priv":"a38f2fdb79ac8a1d64f613dfb3cad99c9f06554cb05f39b6f60c52eb7ad888d4","pub":"03d548248b4afab15ed5e91699d6e13fc4401d6779ce97b3bbc833c690302d0049","addr":"fd60d97532ce397f4ae9accfa99ac5ed9f5a77d7"},{"mnemonic":"twenty fan benefit benefit life orange crystal matter index drip mobile matter","master":"08a9533038e137f0149a965d12c1c90d7f6846107dd626027164146406c86fc1","seed":"d3f6d9f156c814e0f77fb7e9aba06ac2c9c3ee171b2d0759e2d91fb5d383f862aee8b7dff8c62cf61286d8f7f374ce3aeae7ab36d551f802523dbeb80673e0f3","priv":"08bd659717169756d9d66e79aa2b51d2b539f5c453ac8abadcfce3d29df49e7a","pub":"02e3885a7d4343012cc76314876fe67729e434202a28525bf69ce27a9167a46385","addr":"f3181c18f63bd74c4ddb37a4c32d0985e0af010f"},{"mnemonic":"scissors foil oven finish exercise typical catch dentist lens dolphin flag warfare","master":"9db47325d363c87e509aa52701131ad236317ea04515f4e24ba4f87cf99b2327","seed":"0246e8cd14b6b8f01d35aac9c09f8e526bf9f05393c5e1e77ddec53477275dbef74add79ebeeca7d081e58272f4a1bf1fa8621894a8165dbc681b967d84ed10a","priv":"6e7e4b51346f8d1997d81f63dbb7fc7bf4f022bb3b5ccda9e5d84c4a5c97849c","pub":"029edfb5c989c002795c283f445ef4d673101736c25617500f8fe655e043ab55ed","addr":"2a98038648503b442fd77f4d05a338da2062cc69"},{"mnemonic":"monitor vehicle bench chaos stable cereal acquire shock image purchase sadness hundred","master":"bf5d7680d5ad260a89229451e6ebcf3c45988a83df6740fff9b557eb3afec827","seed":"5bec19e9219360a8de56fa85d593f5330ddb158205d25d00d8a2307f6b420f11916311e104dcadacb638f5434e98efc8551d768586a0d8d9baf2ceb0759ffa98","priv":"470256a6d68f8de27b0aba26684cea4c075f384bcdf8a68bf5418dee37f08dbf","pub":"03a1193ff722ba3b4bf7d257aca5c184fc776540fb139dd9a404d3743d31030971","addr":"5b4796167bc701e5182f16e2119d7e9d491881fb"},{"mnemonic":"never dentist blame parent sell income parent bullet eternal random seven urge","master":"665961de4995f001085ce2f1058422bfe5ba0132cfc5725f0c5c9d827020663c","seed":"79a95f522e50cb551c7fa70d54c0aafa5b794512be4e91de2fe1a2e9c17d76bd55087621a606107f3fb19486f15dffec5947cf16405304914f511dc43844ce97","priv":"88db51c0d63c95730fad0c616e4d4fde5a631dc3d315fc74db688ea1a7ceb5b5","pub":"020ebca88011035818999fdf69ccbf691d93cbb6bda65c68c0f2ca10757d23abe2","addr":"9de8cf2beaffcd389ea6dcd264444aae075a1590"},{"mnemonic":"noble shallow label region age proof remind panda useful session poverty open","master":"a8e1a3cf36520d5ae852890951b03cef3902f9ca168cf53c4ec6289dd802ad8f","seed":"0cf4cdddf1605c5c895c1b81fd523ee83239d42feb4a130105c2d5d1fa371e00cf34030cf02ef51aa53596253e264da2c3ec220b97885202dd73a7b5824b982d","priv":"5ddfdf68cf41919145c9c8624c245ce9d6d8c380f5d0153b6155e92b253b1b22","pub":"037943f2b34206bfcfc1fe236c77f6e844d98cef04671431a12883e23846e8e7a7","addr":"559839fa53e5b7408f3dbd00ae5e80f56042417e"},{"mnemonic":"hope inherit quantum text sadness dizzy glimpse cheap expand legend kiss once","master":"c307e0a3f22db3e59a7b28b931c1ba0daa0a8e8d743660c48b6babb4b9563702","seed":"6fa72118b297f2bcefab29f19ad4b701791f72cad287681e2af3e92595ec6b9f7a15b08771917d1754053d1e74aa1a254fc3d6e27deb78b7b55f35a5154964e0","priv":"1a6b9948bf4b717756a11e43847be38ae87b0f42d718dcfbded3bca1a8852aa8","pub":"02dc42929ebaebe447d089cc702bd8e29457a2619047a1d7c80cc4f2639a82246d","addr":"bdd0fc12beaef99e0ee5b07c9c2f41bd90163bf6"},{"mnemonic":"smile odor upgrade deer mistake bomb friend ability then segment orient nerve","master":"17c87ed5d20e5089408ac7fa68024124053d46bfe32fc04ba06801c45b6e19e7","seed":"f620d852a56ab0eb7d55d271034b767eded17ed740ada7f8330fe6d9affd8d88e44489de06d6d3f7b84b294a847334ea051ca63f0be4742667ccffc79031b5d7","priv":"8f90608bd45f866e9fad2a6a316fed6bb6342815ed79c967c3eb1be727ab8aee","pub":"03b6b746569b0ce4b97c3035634a2b30a519ec23a78402137c7ec395d35c4eedeb","addr":"179277829c7cabca8286a52ce3cb591ab22fc72d"},{"mnemonic":"black ghost quit birth dial helmet custom brain diamond rally local season","master":"8a6f8c836e3e83ba6ed94a9de24e1133d4b04fc436827d810c23ee1ec9406fa4","seed":"6488a47cd4123eddce9bd31a0982eb0ce8208ed5e331081dc18256dc8b5a1718807bfa267ae6a75bf1601b99c784542c3d981a9350f7f268d2666af3bb8e3680","priv":"1e7100a43845319b4bad268d111eb3746f09c9a005e023c45fd1da984d37e49f","pub":"035ed8c0324e4956ef2fd2b5141260cb6dbc0943708b0f83c0bca0e7297a27daa4","addr":"d2d9e9b6ea946a61082fe98d9b0a808f5f0879e7"},{"mnemonic":"advice uncle change position drastic leopard praise rack match toward paper faculty","master":"9583a2771931234cdf27fc8a96d06766d4c76b4bd25247596639dd21da4c95f2","seed":"8fa5760f5f2d36734e05cedd78260e9ec7f837bf5b7edeeaa8f4f3ecab9a1f82ca557fa8d75d7d779e47a29eb7c974264d98d12fe7af6a22a87a70bf0031cecf","priv":"3a69d90701054f78204f1d3c959f128dbfaecf4ff0cf6c29fe5ada13c96186eb","pub":"038241211180ec347d2459f2c22c01b50fcafd8ec1ebb51b4ba648fe291bd71104","addr":"f9c6730eeb7a00027b3deb720d6c541bc6b0aa89"},{"mnemonic":"carry enter invite orphan file grain pact glance ahead grace action mistake","master":"b6b8bb3d43f27c84f1e3fb1ea462c9a88d8544b18b22d9b9c13379954a3546bb","seed":"a0078d2fa9187ecae2b8ad3d4121e2567695c1cf26bcd441536ce95a6e04b4feb41c1ceacb86ae9ea26db4eeeefaac7e0477eab711b22d5390be3eb3daaf97b3","priv":"7503c22dd0cad622d4337dbd7e0bea66a2e8b52427cbda01a9c5959ebe8b5a73","pub":"032c577bb5610ae703c54444865932db4edef3b8c84f88c71a25731a85515eb69b","addr":"f268151a05642b378f8738ec00b2e486e60e284e"},{"mnemonic":"taxi betray parent equip margin snack spell agent talk possible portion lunar","master":"5bba6a340254e9803fb2889beb84d4bc63454beaba3f10cb992d5823b23472cd","seed":"a8b970f56b960fb9888f03013542e90b547f7d60aa91218105808e595a561ed37c13f259692d3dea5d324d0c4142b30e39cdc2e60697ddb5f52a5459469fb31d","priv":"ae63f7802417743bb8bca410ec64380a407373900e0af51e6acd65ec9d54a0f4","pub":"027410f719925fc55875ccb78092d5e6c31b8543e115ff39bdfb9a26f97fca8859","addr":"da9b8ea1879e13bb49e7b9d179e5b56cf6de6537"},{"mnemonic":"sheriff marble regret shrug shoot tornado coast that obscure sense duck noise","master":"e97a0a9cfbcc28b909f7a5a617af10289965c6901fb06af76a6fada22e41876c","seed":"7a231c5b3b91408a19de9571bcd820f17451562063ad2daa85a1164a952aeaf8d6a3c703909a76aa1e1a2818f8fc36d8dee3c87184b59d6340201402384fb7d3","priv":"d3fbcac181c592367cc527d8f09b54e1a31d3b2c3fb5c1cf4f2ea897c483f5a7","pub":"02b3e3765ad7c3c020c6a166b0113b87279e66a53859ccbb9d214181e2be30ca01","addr":"517212232acd318b376fcface8544506a8f76c18"},{"mnemonic":"connect drum once first trip dust trigger duty situate burger toilet half","master":"073fb31a2785afedaea95e67ac7a3219f2f910aa01b054022a5185c5ac99c35d","seed":"fe3d1ba2740ca127dfc5bc22ab6fdbcc930b957185a0b16b1919e4fd5e637c053b3d356b12152cda6d07f7088f16195319075d0b3533e5082b45f1bbdb7d5a74","priv":"6a19f33e357328d40aeaab5323764bf9e12df8b476100baee9d398a0fdbe3970","pub":"03f639ddf3dae4ec84bdbda49149d2fc3461b2309d043c89eea46bd99762b54a0d","addr":"c8a8a454a5aad713670e936b63c519c843874b3f"},{"mnemonic":"shock later journey twelve any ripple soup climb globe impact poem auto","master":"382a7bfaaf7df9ac5cf8ad1f574bcfdb98e185847a92cc36d272b74a14228259","seed":"aa3bbf8521133a0fba514e54147daa2c6fe294b1af8bee3a6fe46ecd480983d72635520db97bc3631d9bdd55787b07e45d81b052522fb7330f4e0f6aa24fca8c","priv":"dabfdd6c702d104e4c17dfea719ed870c783dfbcc66e8987bccee888658bff76","pub":"02efcce52d6c7ae70900d892e1b24ed5af6012c38c15864f2d15067457a2c55f2d","addr":"fb3af390f0137dcf7d98e2630021061d0fbc9e06"},{"mnemonic":"news book language depend fine fabric idle curious depend plate fold sustain","master":"4c28a9f9d854290f4655fde6a91500dacb684417d8dcaa69435e1ab4b8f04e3c","seed":"2839463d79148eacc1d367f9ed0a2ab8ad939643f439c276bb47f0fbdb4cfe8795001ea2e5c24a6a6da9d35cc6759c37e50ce49f34498ea61a74dd11b14a6421","priv":"d6ec69e742e0146c9811de01cfcb07b3de56594fd4e374722ccf81dd143e9a12","pub":"020f5c54b785c5ca65547b2ba32138a47b8b5b462b304e0cd3ef981b407ee73b87","addr":"2850f467f64992626b23e03d366f34f4e6760807"},{"mnemonic":"equal energy inquiry frequent aim wide exotic tail vintage toy marble spice","master":"0fae6d570fbeb343eaad5bcd272d8554fe27a9cde389685263ca1020e65d4a1c","seed":"62aa467a7dd73249fcad8432d188e64a1d0f1591c66912f906eed133ca0c1e99eb068dbcc8ec37947cc846b1ad4f439821324c61bbb385fd91b2e440d6a86e41","priv":"1a254e7f18b0836975e187a72d0cf1d1b69225067167f44dad6aaed6065e60ea","pub":"02ce2f7840d3f69580538517852dfcb2932285caaab4d11adb98ccf335430fa50c","addr":"53117f2a5d41d6e727db2975c9dabb1d28708d19"},{"mnemonic":"recipe prize resource define enact basic glimpse chalk box prison approve fossil","master":"ee8a619974bcf5cfa95af842bb003ce4f5236abac96eacd51ec8f797bed520a8","seed":"b2d4c119da7c72c24542998b036b2e1c501b0fb990154d1b5abba4c5ab9233c4caf1a427948faa62aa862002f43d115f2e4d715b8c9ea3eb662b2514ea06390e","priv":"0d896d53aeb3f2fbe634ed280225bdbfd10116e18651b3c801a3cbebb0f75ed8","pub":"0320fd7d4c9c548c28d08e587f45836902f14c7380cfc9f8119e0b6e36089369d6","addr":"949025151f752888794030aa47854ff5ee407e09"},{"mnemonic":"hunt carbon lady smile luxury old empower pretty memory gentle public pottery","master":"e9542dc3733e40f7c1e5f540e241dde57a09f76d28e889f69dba48d63f0b6445","seed":"ee0dcfd61e0fe95e1e0428f29c78076f302cc5a55db61c13f9e6d84811bb0d57ba3dc109d4d98fc30c1d2e5b25bab1c646623fbb00e5b3719e4bfc58005fcea9","priv":"e846c35be2eb1e3781e8078d8433a9816d8f8701131e69873290689940617de9","pub":"03aed0cae3a1054d184c820d9dcd5118630febfc450d4972b4963e56de2b1005ca","addr":"af41527e26ef2ed7e1692f2897fc48bbf792c8e6"},{"mnemonic":"captain disagree filter crane chef cousin one cherry able scout tip magic","master":"bf4a3d4839793f7d502e24a4ef4e99bb39fb2aaebc53149eb004ffaca0256af7","seed":"3fbd2b4e5c614a29cfe82ff906e94be976849cfffc6831d67fc47bf2dea68ca06fea30de70ea546adebad96d3fa106950545350e0925425f22a0ba1a0abfa3d7","priv":"046eff73ff79adecbc208e64dd7bfdca16c4593a1780261377ee48e44ea06d57","pub":"0374f44a020872df00e0101f61fb61e76038f6fa8a7d50a89757db14b2c95b76f1","addr":"130a585f378df286341fa93925eb5d630adda295"},{"mnemonic":"inform measure recipe evoke make recall volcano girl obtain flash soap prison","master":"3bcbc5c191d8f5fd59988894fb749ec333a07e909b3c22108500fe08cf7edb53","seed":"cedd1141a4c9a1e349435e247349994c909811dee5770ba3642768518cdebbe7d7e5ab0776af835bcee0913fa1bb4b72205e9d38b637196a624f031238bd2bf6","priv":"9c070a30d5ad6301d73ece1e6e71790327c6922521f93d6e8b7c69391a12d37c","pub":"036ebf4e4d5349613dd3c7375703a1025896ec4377a9635e9ddea2a2dc1e7bef22","addr":"74a413291b799fc2866fc7c7ed2d2becee9f15be"},{"mnemonic":"carpet poem piece silent boost trim famous coin fish rule leader oil","master":"ab7b210126590431eb1c09ead09bef99b689a429cd86be65681debd5deeb1ef4","seed":"133b317aa1f56e79697425b4c94aa52d5b7a95c3fa5ab6d437bb1b310bae6baafdc91ebd812c76b721fb45835f3ef0f61730320a8ca6e7cc18291b84af5ed68c","priv":"1863a0b1d15847102e3198549a59921488a67002e38af1cce7ab2c0e055eb498","pub":"03dfd8ee8642ccb78642d0e373ce9b15ce9384d12b36086d2c64601ae8d18325d5","addr":"b70aef2f2dd6e42f909a5840a6cc7e08fffff26a"},{"mnemonic":"liar hold orphan include gravity nothing erosion offer average now ability purity","master":"71b19fdcc0d8e082eea3d92a5e6d36512273095251da9177b7cbd0bc2e5843d9","seed":"e58ade95c1063890ab5296e5d8a07e20ac80a159afeb88c74dcc6bfa8fcff6c85a2f19af8404d3e457492c560e4f04becb6446e290ec1a376564be64ce1c7ec4","priv":"2bdde1157be2917e98549af370aedc6a98fc5d6df99db71650ef29407512912f","pub":"020a188651de8022da9d74bd298d324c54c88e35268eca0907a5f6366f9ceb3287","addr":"9c4c3c19a81d424ffd69bd29802ff155f52e219a"},{"mnemonic":"crisp security increase topple put engine wheel apology north tent front minimum","master":"77288b3b65bd31029a3791d357521172af895f1085c1996668a1a689f4473a93","seed":"af74884da27f1ce251a75244ac945052c4df5fbb59e3b12eaea5e28c8fc26b8ec95bdccbdf5481eba4b74680e642e5e7ab2b0f6a4d0eb41db3c08c01162520ca","priv":"4d1df90eb70f94aede9dc63cd951a30730364379bf9a0f339d59d5970095eb65","pub":"023f2f6cf79a65e2d25fbff8c422ff519603c2e400c5d3b6523a6db06b969c071e","addr":"42bc49b12a7eaf46695fb1ed32db0d32e8e661b9"},{"mnemonic":"switch shy kid child occur salt cage local top blade cheese width","master":"5755daab29ff030dc4b255171f77523530a659fdd70bb5fddb69d150d4e7e1f3","seed":"dab58ef3ea14f3041588a5411f22cd426ead10057616df799cf53907536819056a21faced7e56aacd120181734640821c082daa86fa8ea4b39ddc40b5bc02aad","priv":"e5c1ebc0e3428c9ca42dfe809495dcf7ce2abf2b149664031b5f5a9d5d2f8b4c","pub":"03fc64577364f254c6f919e1a9262740987217fa2c66ea490ee6d3dca1787114f5","addr":"1b83078e35972e3ce3b1bb062b3924665a6e5c5d"},{"mnemonic":"rival notable exhaust climb disorder enemy desk owner again twelve mystery devote","master":"5daf52423aaf7b7ac4d8ff4bad65d81f7e3b15021222d3d9ec788a2d35d074aa","seed":"709afe1cde759d12cdf4fc3a68793b35490cf0261397754a62dd5d40fe528424e8deef620f89337dbab01bf57cf241a6664bb3696bd76c886c57a405170a7b74","priv":"b171a7ea63d6e1b8aeffbb63ce5179edc656e17eaf85609ab0d2680e35a3d64b","pub":"02cffc5dff2f9896d995c9f9b6d11c1cab3e0d40a25dfb9da5aa010b703c80be0d","addr":"cc673e6d2578bda7d7054d2d53b841c26e15dec4"},{"mnemonic":"defy prison walk thrive enforce match turtle venture margin quote must cute","master":"9d747975a6889f2bab69fecae39db2a10df1545ae418596d97152de0e7cce077","seed":"183b5f3d963036b0e22eca9717769422bc515977c0a7fab66d716318de12d41a01f5ce101bb47ce44501f0908f8c1255f8c3078fd2c2084aac32624c20647806","priv":"a871082f9cd061e39987c76e516a7086f82eedc06a20081161e13dcada541f61","pub":"02726bfeeefc2d5ef521c3800ebc7700e11aba3cec88f8be5c9cf3275f4ab254ab","addr":"6d793f4478d2e4980a140b724cc8012b44097446"},{"mnemonic":"lyrics goose draw review manage recall snow lucky mirror swear fish rhythm","master":"b69e9a8960d5cf2b8f457e6a037654bcc72ec1d26e4753ad34512a877cc329af","seed":"47054d3ca54f6038ae500dd6a7f8b5fa3265e87b384c16a4e68560f56dc9f7945d599d6a71b2020618c9f7bab46bc6817062751f19b46c2e05eab7831fda1cb8","priv":"5c0efe877506f2f46bf345c71c8dc31239f9e23a543193d5ac894faf0aea9ddb","pub":"022b90c4806ce022e81c706555ba3cf9597861a3d7e28b9aef6bdf36211eba916f","addr":"a3ebb9a579f22150fd9b7cf62a5f52369fce28f1"},{"mnemonic":"coach silk assist potato gesture hire bullet piece document outdoor husband panda","master":"541e3f3e4e4e9803da42f2264efdce5b9338d410b16b0e7b66611e5dec5bf896","seed":"4368a638c45b7ba4d2f1953eac650631f1a1e3c23c72b545dafe466fcda597a0b97dc3302072e50a298989f94ea255290d3963ada9e42e064ae300173531f273","priv":"b9462f51e3c20b3d805b54adc6b27c669ba07d5a5c97edb0a8cc6199d772097f","pub":"02dc7826d790d013e76765b03447d2dc92a945268e42611c51080b7ae207906bcd","addr":"e59101c16f77cdba771eaac3ecf416232f6dd1cd"},{"mnemonic":"wet problem raven barrel explain long call civil pact swear luxury expire","master":"1e2704a2365215a83dda9aefb1093e095c0c06623f060c2741e8bcb8480c4165","seed":"fd81b59cb8a4abf789c2fd55e2d9366051f8f64f54a3e08d117d344b633f2ffd63c1a6bce7a4bcbb01261b6e41f6330ac5d0b151c36649ad59c0cca7e4b3a820","priv":"bf9f0440cd63148ea0771d0f892efd3cc0638330c428a50436fd048aeedd7ee3","pub":"03d807ec07f4f6eb00f9e3ec69dadafb3201cdca3e878367ce4245af65b8e4490a","addr":"e43aabb2d20275ff60d591dae8d83b938a0138c7"},{"mnemonic":"unique mobile gospel cost genius symbol online rack round canyon front again","master":"ff441298736365bf07856cae35a9dfc2612a9d015592d5326980225c4d4e4e21","seed":"e05899b5a5a94c860cca584b6065284e961625486b1ce1c80340721fe4f89fac7afb7b665464de68b5c5813e48896210a90d44eaf013ec4fa90ace43e3153d3e","priv":"45513cc23e8ad7f7b5932988637cd6aa85f19a481cdd20c220f0407afc69c688","pub":"036080589a5268143509bba4c4f26ae8a3ad7b12ef7295c9ef416cff53b66b39a7","addr":"68456ee838f224959e5c29649f41eed02b56c3a3"},{"mnemonic":"street bleak prison artefact pupil armed blouse pipe eye brother man aim","master":"6e0891146585834da8d83d0e221c88d53770f3c56f68429565d011ac697238aa","seed":"8af79a74ad501d308be613981a1a25342791288f14f05b7cf3b81131ba2146ea63e01ccfd150c4d2bfc42d64adc899158383d82f3bed0eb772851fdab4f901c7","priv":"86c09e2544c86b883e8de233ee297fa704c39bba463e5a8742c4fefc9ebc109c","pub":"03d8cd38cd2311a0360c84cecc58787fa3916c6c2adb5b2baf12a880549a572f7a","addr":"68c1770edaf76cabcf93c6d94f4510162fd36924"},{"mnemonic":"love wear kidney math magnet share mango also dial fabric near destroy","master":"e500e6d3a103eb11414e5ebc9e27eb96456c48e9567155c6250aeb83920df860","seed":"704e740c6f437a9e8b7e8d7e2321ce81d9132c9a6df7a45fdda99cc66a09c9d73350305aceabc0fcbb589bf44911917be71e9f399c401f86246d0aebd4b467f3","priv":"07c906988f937dc841918a7c3092f5df0cc0a6ce4487631774cf3f703e9c2713","pub":"02d131982bdf285fe3a37370ae0175438094cfe3d6fda273bf24320008fbdeb5cd","addr":"df31d832d2d23502cd0198c5947e8297e6f73eff"},{"mnemonic":"nominee connect useless dutch double vehicle rocket exist mango floor educate absurd","master":"0a66acfa6ac891a588255bef6fb1a845f2756ff0a7dee8d2ff33a19a7b22f18f","seed":"4c4e362fbf0dee5928b21652552815edf27a4ba5a11a09dfd83f3b53a44cdcb6acff4c39b16d2cb9ea3250af3743baddbf6ce90ce1e492fc6bb53f79d646a4ea","priv":"e81668360f562929af7e40c5970bc685ef5aaa7d390c1bbe005b028460c79ff9","pub":"020a16c5a1098493bf1f7242de71bed03779c4eab8f35a1c6859035111514284d7","addr":"c8a841f39aced64bbdebf2f8f834ee02ca33a8a1"},{"mnemonic":"sweet leopard loyal problem pupil perfect power flock thumb wage person secret","master":"6fb555e482a1987c2c0f129ffc040fab9c4eeaa3c23a3370db7b4a5ebfd2cdd1","seed":"b20837f8580aebb15a7a4b035639bc04e27bf33e1f600069ba1378a5dfdeff3e95545e6828f339dfc30eaa449c78b046c21fd99b24d819c735e050f6992f898e","priv":"9d06cb0fa2cd01675e038897a14e6b7719ae84ca6002ed6620a557877ec373ee","pub":"03f49f50e673851d74da1fe24aaaeb75c2cedd25116c003fb4a810025192c3186c","addr":"7f61e30a20df85042cfcda5163867bea46b98702"},{"mnemonic":"slender tilt tell faint dumb seminar cycle tongue bundle case swamp author","master":"444b57e7f846dadf73a0bf77fe918e8716454416501c84a48bd78dacfa87b885","seed":"4345b114d1f3a78c5582ec5469430a8cde3a1a866e64b3c3606b84f62ff48bbff48826cee928374a01aac080b79269f89751a11aa086fc1fcfe74cf05674ee04","priv":"7c6d51ee5199457807c66f22e8d9b7a703a4e61a84cc791efc3cdf5f7038d28a","pub":"028b09c16923224208b6ea2ed777a2e4aa2bca5674eb8f0021e9bfc4e9d3fa0a69","addr":"2486b9fb36e8849e09b147749e445fb515591197"},{"mnemonic":"alone oak satoshi diary artefact virus muffin quarter identify car whisper topic","master":"b4c37472c7fec6dc3f3452d4aaa7c306cb65ff940052b0aed224c12104296648","seed":"4dca6ca310d5028c4cff946edda516d55c7de81309109e6e3586927a8fc2c4095215ce471774df2795f04fa01cc2cc528c44a5968320ede4016d68c24e4bbacd","priv":"fde405fb9a8f0e98feed3f4e996b3fb90193800c571a89a2c681c0fb4917afc0","pub":"034bbb553a8525daf361bf0c831c756a56ec476c0c9a52b0c74dd9eef35177a776","addr":"c890e1e83daa169e0295ff2844edc5ca2a7ff346"},{"mnemonic":"noodle hour inquiry know sort review oxygen observe exotic script mimic march","master":"3be52af1a8430ba7c4610dd4bb1ad67d978d40ff7530d712cb5728bc961edd3c","seed":"e803e685c85a1a0a4a382d1358f5fecdb8821564545d8573f3708a01f0f0bc1da54544ca2338cb988e7d6239d18c32bedd38e1cb9bdf1bbb6dc8cbb323055510","priv":"defabd99910867339a4af3a425caaffad76ccd47a43b05a13ad86f3d23887b03","pub":"02609b9ff36c966dff6399576fec7efa83cf0fdb66bade72334ce2ba69161768b7","addr":"abef04d453ccc6d443cd60d6f964d008eb5f08e4"},{"mnemonic":"crumble loan economy dragon vague library slush ticket flip mixed accuse switch","master":"f085484747a4bf869f38da6e6f56b9ed2be60b137536a2333f2c6818d76fcc68","seed":"b0ed9b4d75a17a53b33a73223fb158d79999548d13919599ae7eb71cfe2fcfc06cedc8f94cdcdfb05ea043069c426d2b78e2f67260644109c42a6d9b3f7d5134","priv":"a64c537c561fc49e504e870eb3608e69afdb2cee4c6f177c63fd1ce170a67192","pub":"034f7f99f2699604d3f9869dacf1e6ddb387bce4e0d13fce3f4aa85713c7976048","addr":"4b51a7f925c0e1b428b1ec75dafcb0e4d9852620"},{"mnemonic":"rifle swing confirm response name void scan shoulder lake oxygen uncle south","master":"3560f172b5c2ad665da648cf0809604522eeff5fbb2b1e0ec50e7197bf711dac","seed":"85386f49048f371171ac3ed2bb4f358b7e22ae406a7f2c9b3f494f2f7eade96f2b6f96fe48bff1754894b8b2586013393f0b9f0365c6996cd251e668ee90071b","priv":"c79860b8ae43fa4dfc570b2d20549b457ebc6e18d38865ec9cb1ba571409bf12","pub":"0253d92439ae131722981eb16924b26fe01421e4222152cfd0505744278f963dec","addr":"ace153f8d13e8cee51a2c08fba9f445f50e818c2"},{"mnemonic":"air floor random smile mechanic exile run auction avoid truck expect old","master":"a7cf0d4043dccdf5cdc835419f5bf2665c8c10e7affeaa2d8cb42e3787bcec00","seed":"e4d315f6daa11eeaea17d513f8d6df6ff2dc13dbd2e09158af03f847ee6cdcac2d6b88906ae62e84355d9a0c0956ed465b3f8081837d45eb01cf785223404306","priv":"5f1f737625360db311accae8b8ceca9d4f2aecf15d6e4b91db4c407bf75345bd","pub":"02f467c86cba2d8d6fa258d16e9b4543006b81c61bd357a2b1d79b9010fa30437a","addr":"458f265c275940d726dd9714413a56efb7f8c4e9"},{"mnemonic":"assist right street define hurry section tide museum faculty glance power aunt","master":"49eeea0b9687360576a3f93cb31eaf0edd3521d2cfcfaa37434d6d51a2f3b5f6","seed":"9371c5276808cbae376bf529372c88e6c5c6178a9b469ef25a7558ad68fd6200a8fcfb2c117b7d99e9c7db907bdb8c69632e7ec058f2b8a4ea16518fed9dab82","priv":"936dff8ec25f22522bec8ddf52535a4320327697a581e9304e62240e5d2f4922","pub":"029c518dc7e8261f2a64104ac846ca90439959f4467e69dddc7c902dfd41fc2177","addr":"5a6600220c96af511e6c89dd9c8c80f1a1b0a893"},{"mnemonic":"glare earth tuition dish elevator mom remind arctic enlist excuse vacuum little","master":"a251df0c9b6925fa78489dc803a34839d90aa10dd35216360fef92173e0bea80","seed":"4a543a76deb55a8df2a58d0fdca3ef32e3f3ca74be97789cf004d1b69608763f8d311c6cccfa76bb6c7b04ff8d7ce20ee064d78ce4e2c05d894053e8a5309349","priv":"0aba88dc12cda2d2f267dbd19ebf0eb390483c7384895b6b7669ba821b73953e","pub":"033ca852e0b43e2ed4c7258c43bcc5be47e621bbe6e0bd570176940aa9b371adce","addr":"983a92fccb0350a8371cb5d5effae7125615316b"},{"mnemonic":"tornado group bring crack need pigeon scene quarter affair purse three mule","master":"b4d54df22150e28595aa5e1f6717ec764ffd8d2cc6338e264dbbb46e9155dbc3","seed":"85c281d21f25c14304aeb5402e717b52bcc0e5dbeaf2d155e11913717c545baf79d4d965670d7645bf093ff79f4793d136d794616905c2e24a8c72ba1af44ba8","priv":"c45a9afa0dcbfabbec916a9fba6bbd9cabc1a65b4ae3358e29943dee9d19ef9f","pub":"0272882ee11e688d04b89252ca1000456fa743b5931ae03e1d29934f79980baa41","addr":"860b69d255bf12d5f725e286203f91bdbdd29bfc"},{"mnemonic":"toddler bamboo tornado season total battle urban mule oval steel field case","master":"af9ea8f11f6fa83dbbd4ef32dedeb88070b3fa9fd98d27e1d9b43e66da7d3df7","seed":"4b95b55884e008f340660a6c9ed4f2b23f45a5e45535fb263e880ad8842e845a62e66720b75d94fad7f47fb494bd32ee70b7a339de5b07bb13c7f0533e8cec57","priv":"643eb65f5c87407a18be41f6c660d4d1ae610c9305833c570d785006b92ae354","pub":"03d1c423839d02f40abf0632a36f9739c6ba59622ea56e1085d2ed54504762b43b","addr":"05625426a47e8c11f27fc55a53121bf748c2d05b"},{"mnemonic":"meat endorse bike truth avoid measure injury polar rely water rocket zero","master":"23b56abfa50026840bf19105ea9a02569d1881e2cc447a582b08a6bf6304a33b","seed":"d8de461e4f04d4657de6b5adf8730bdbb85fd175326671886017c09d8081ddb7dac0b8262fb01f2dde477b3e2bd97653a700d373fa29ec7db2161dcbe418627d","priv":"f409c92079cbcbd9f96b2bf0d84f86d495bd8e6bb4859fff2d62c29558a551c1","pub":"0247908ec215a561a41e2da6ce05e0ad08158bffbef9fdf7bae729592e4d17b45f","addr":"e4cb61da62a6176483f967aad232c0fe89a9f16b"},{"mnemonic":"few transfer upon helmet property draw strategy talent awful goose index lesson","master":"c0e538e1e0b819660c63ff668869a81595107458fdad44459f6ec22b251d46e0","seed":"fad56235bc5f3a7dfa666c85e5782871e7c202bc4363da62fe3771d71b36a9a1502d550d668db69264daedefd7375862b891d4193cf958b6d8af9b39a9fb0e3f","priv":"51c8264448b81467c2c86c003765322f7c763e0854903230a4ff3557fb7afc31","pub":"03bd00d092d311add8fbf191abccf181bb5fbf83e26d6e29fb6f4d70055ad5e7fd","addr":"270429d79b582d835fff0b15b0eb21ba1c98b2fb"},{"mnemonic":"can warm add shell obscure ability mushroom discover destroy useless split blush","master":"611e2b107ee76d6f7b415776c7b0c6f03859366c342a56618850c6e3cdcf46c5","seed":"c9f4b2663f8abc8c8872842c41fe06b5911b412fdaa875ba59366d7a18734aa795092d220793867ed43afd1d79882ffefde417ca68c9ed61a9f52437d7e45a53","priv":"af975acc3008d742a37bd6917f4a5c6e9a5e0fcacdf1e74ec489e675905dd9c5","pub":"021152804b2ac5099446aa5e8cf1fff850cab08e225922e3865ae5b280a230ddf0","addr":"d4baf915a1108fabeaee47ba0b03cb241a12e1bb"},{"mnemonic":"critic length shine mimic gorilla rebuild bike security price differ spice average","master":"418d3fa386032d0a22a3b4553ec662d52ca416af47d0963e288a1bd08ad50d20","seed":"c44a2f7e56ffc9850454a03c40be79555c340b8bb2a7559a664a8e295fb34fe1a38074101b431038c207baa219181046805a67977022d61bff2270c1e27b80b9","priv":"117d57d4f3dd6db8a718e025f4fe5009949139f2a41aebd682ab49f96ed152dc","pub":"034af1a0205014cf22dcf328aa9308e255355dfff65a7185aeb180061aeece5084","addr":"f7af8cdd0592983c065c322efc64bf7c25769e2a"},{"mnemonic":"vast resist ticket hedgehog around fatigue rocket rack carry run protect icon","master":"c434c6e478fbf7edaf97e2c90c38369de3033a98696b1ffc793aa349849c629a","seed":"720f1afc198446db8a107105c7398d3bba7675fe0d01de12f933e2eef7d12effea0e9d93099e0256b9e494607bf45d855fefd68543d9beb4b92f3d7779a8616e","priv":"497b2409c651a41ed36e58e977611292bd665e273847d4d413291c386d0d65c4","pub":"03ba0869f55efde74895a6905dd149bfe140fb2ee4e3eb19c959195d93adaed2f7","addr":"2242ceef764c76680a768594f804e218154ae3e0"},{"mnemonic":"neither bunker use enrich liquid borrow time feed mixed clock submit scorpion","master":"a9c4646a10078a9ca6b218b7da25745a76cd7dd9e38d803d8e840863c9b97449","seed":"22cc85d4e408d0a751b854f16e00fd16b018fc26f95aa7d82323084ebd7d7bf3fc2370c1a5e38f88584e8a17977f17987d75e447f704603c2d71b3ccf806afd0","priv":"9801ad0243910e04b7322f493540801628da575ab5eb18a5e0b20b0ffa498e5f","pub":"02c3f726202db7040a250647799f5791d4013b38da6053e44f502d0c8a064124f7","addr":"fb0ef77563764b393003c137da2dd1ee21d92904"},{"mnemonic":"letter violin disagree arch crumble amount car inherit wasp vintage disease orchard","master":"a24fad07da3e4a04fecb2674abf8b4260ae5dd71f003622bbc4a00292dec3cf2","seed":"890b94a33cb176c697b9ca49281c053f88a8e8bb6f52af5f0fab57ce621145ea59624fd9f17bc4d7ff820bd2998cd1d4a2dcf8f89738c150aabe7af5f87a6b1a","priv":"499b6d6e741483ddccb35f917752e51970c5999900b48e18b2d1edb85927b7e6","pub":"03354167051ad5a01e056f7bb655de9af430fb0b3756e1cbbe6dd0cca65d43ff18","addr":"efbe8995bfb51a94b21826bb93937616c5807d94"},{"mnemonic":"elephant shoe quality dutch pepper math between lemon wood below strong grace","master":"7890fde1f36829461985465e7a7ba26ef80bc9908e5cd849517a999f04b02ef9","seed":"077fbcc3c57bca394c393e9852c3b837ab555cfcc5dd0097c058136bf088fea569d18fe0d447a8bbe53b5f22961de7c5cd0000274930db60ef18f049aaba4741","priv":"0af39cbaff322b7b7298b2605fc762bcfa69ff84a50dbb121502ed1e8db963ca","pub":"0221dd6d3d3c597b982093f5ddc4b8403b3d16d0e084aef37db3526f050c9b66d7","addr":"81ee7b181a5d1902b6aaf42ad0225edfbf669498"},{"mnemonic":"powder marine skate good skull correct catalog parade car length fold clown","master":"dca44cfd6a67d213ff365e5dd6bfab6fe63ffbc999c9d38e48b9c8d32d32f914","seed":"91dda0ed96be1b82432b76bb7dac1e80ed0a1c5413096d4a22437081834cc29f6355dc3e79d7ee00cb6bbe50a83fdd3b652259937beccdf11b844ff023269e76","priv":"25ef3009323160687cc6651338320311894b8260596834e6cd05c1b921c7254d","pub":"024b805e8c768c8914ad8c55d8e1898490b9c71fa68ef43d07f3db496f03db11e7","addr":"57c28bc9cb2f4fea177c34e581c95832256090eb"},{"mnemonic":"client wagon legal favorite donor tag describe object camp network tornado immense","master":"4b916d7a10502f4e2ecf295d826a3248fe9bc45a13f1332a46586833b2f1dc05","seed":"e2726352ef940a7cfccbe95172c1fb07c8c25ddfd7ebf5ed532f27abfd33e81041e816e34aff02530525596654111ab3186fd71bf65dd3dddcbc6efa7944c347","priv":"131de6e55bf3b614153557b35c839f0c869cb10d62b8c34c15fa2cf7c32bf97e","pub":"026a3afcb9ce79972ef910d6272613580b199f90a00035ecca637b09397f0624bc","addr":"b2ac8314ecf16da855c5d7b9ae3aa12854ae4a05"},{"mnemonic":"someone tip green vague sudden element beach people route lawn vehicle female","master":"2f7b9ecb854a851e308e944e6a8b39811a286e718b4ebb9a36e8c8570cfa7890","seed":"7653cad23c600649423fd68b0c7d002feb0327551521059362b3914a63f6ca6adcb1409f7f7f1b01f5c489237b25d0dd9b0aa121a60b1af33cccf739d05e32b8","priv":"4b3d50735f027be5ce5a85a739227b4e86590765e34b3608338497fe318cdfc8","pub":"03b47e6036447632c8ee3d2d1e3b177b51ea73bddd30893818c81059cfd3ec6c5e","addr":"10d976ebd58061a7c6ebe2ccbfc85adc617db2ee"},{"mnemonic":"version borrow decade family away zebra one course paper promote man gravity","master":"ca2995d4590ccdfa716b0f27a3e5e93d084df7039116b06ce5b4c5f2bdb18ef1","seed":"97a3f0fd0c7150526375d5cd1ea192dc0f04ed096e5c4895e0a15a6d491b206b59d52800c2c31ac6b512664788ac79663135f450b5198f358dcfdf1e9cc26e12","priv":"cbf04fb7c5c97ab9980cf82625a612919a85e72c0524cd49c0a237c25940b563","pub":"031f04b34f157a07b6bf50fd54ff972b8441a72d6a5d4fe1e54a1867d07fb61cac","addr":"57488105d27e808a39fdd571c895dd06264d3357"},{"mnemonic":"truck zebra tobacco hair monkey pool label produce leader hope misery cost","master":"b42e61efff413779403a9d5ddfad5230412788de3c0c7da4b020c73a72a77569","seed":"1b9c99349d6388e5f7dcbb8d5b87951a614ae7f803b69b30783035ed016cbcab3c42714246d05039bc6121dba51fbb722c13d2f6ca0cda79a0d816bf7e568cb0","priv":"52dad4ba927ba056a1f0a07515f044c3c9dc712c2019879029ee0b37c7f51b64","pub":"020e6af559d2e1115d8ab76e908e3ae778451dfca6250b996c42d4f3044f0f1a27","addr":"1a3e87568d2f20d4480c153cdd82af21382fdf9b"},{"mnemonic":"dizzy capable mutual cage uncover frozen exhibit awake teach grocery juice reveal","master":"54d15b84b003dd74581cc49909d3bd7ad07e00e745f4113aba6facfdb305aa2e","seed":"c4ae35b24c55af14bf590df97843ce1c9bbb324b845f9d2a08f0ead0d0292f6092e261711aae504feeae862bedd7558a092271455d89a5d1629be8ca43710e84","priv":"d5d476790ed6e46ce12e1573a9fedddada0413d5750d1d18e408c125e43c7923","pub":"02f3b58f6cf3533f3731e5ccc6cf094815d52467e39151d517b9f6a425f8743601","addr":"249ffe5709370cbe54520c162a4a7c8db2b28bba"},{"mnemonic":"menu damage flee oven blame vanish olympic scale pretty valid toy write","master":"91c79127f19318ce4594f4f1045f0f2efc8ecb6a3ee9177ea2cbfcc890a781b8","seed":"fc4b72ba3587fc4b35637186959e3f02460262bbb330c3b18e561faf4cb2ea29ae9f92f011d9d78231746dfae33f57d75ed85f96680a6a3f309a3f81cf59831a","priv":"cc7b3e962031f93079b4d6a9152a85bf927ddd2fdb9f84465220e2cc3ccf9ab7","pub":"03eb09eb7f21c9e411e3660fb49907bc9a23e04bbe75151ec732e066e4e0487118","addr":"20bbafa15fe38bfda08c18ed7a65c52daad01614"},{"mnemonic":"remember hamster power document detail pave inspire tongue rookie monkey board tourist","master":"dd1970c96e30be347b4ec8fe789b4cfc29ee073162d4a2e5dbe5c78c80944af2","seed":"561682af8f69fc045f09d43db4f71a3c7706615ac142078d6aaea287bff00b0bc3213537dd50b783d7f5293b4c2d2a1f6f9bfcd5fdf17f19cb10ecc05f854b1e","priv":"79c341d4178a7a8e1fd364d8a847d97b06ee94d9906a269499fafa63730d04bf","pub":"020540cda9e4957f9480aaedcb38379f2ba60648ae487b741c629a45a5b34870a3","addr":"cef7f07d4ae1da5fe3cdbb37d95bed5bbe53e838"},{"mnemonic":"endorse rescue traffic vapor chef movie symbol scene slide eagle youth tide","master":"8e54dbce9b2fba91209dcbbf6bd272d524762ba3ef2ed05297b01f440e6ed597","seed":"2a0ff0a70d82f948b866090a4e77ddc360a2f52b6abded17f13dd66e79e845bccd2c55ada4d4ed3dfb33d5d10700628bee551ea775c7f3342f6d7a0c3005194f","priv":"c58ed547be839e99eefae49479b3b6345fd7c6ddf390104a544b79f5f677016c","pub":"02d795bd4c26b14dd2aa3c04633f5e0ef787533b3ada72e7c83bffdfd4cbdbbc5e","addr":"ee25d8e4187f6a6214662cc4872b7f7cf7204c45"},{"mnemonic":"humble glove resemble slide rib focus naive false snow north strong attitude","master":"e8b826c5d90453d1af3082a0d5f6a625207bef96bf7e168ddc4091d7f865d51e","seed":"b9bc139c6e97339489cab328b3a362546cc19d0cc060e5c5b969206024aff86f1579d230b4b8b3983b33cba32a58d6dbab5f078704f0efc65d6476062c1d41bf","priv":"4085b496b9a18f4ee5a1d79974be1b1729f51d3c63ce347420d08833d2c793a2","pub":"0251ff80d2e90a37efec614d9fe65b6192179941b772a9468440a2380845996846","addr":"4fc115087277fd7dfcea23e089f5a3a6d7e3bcbd"},{"mnemonic":"fiscal truly seat deal crash train labor trigger kangaroo angry today minimum","master":"1770627ca13a66d0fcfdb474a3eef708abbf9d23d211970395308dd6758bf8e7","seed":"a19680de56046e31637ce714778881f1ec6bc08abe9357804062cb881838c2f8387b52f714377b89b6faa07c4e5b6294324081b7dc521190cd43f75f91029c22","priv":"131dc8ce3551842aebd863eb61e07e6d2de40d548dcd28ab0ed6380e469b5d92","pub":"039ac0eeaf7600231c75fc72dac0b2f58418e1f187aefb3491934120b4fc779d18","addr":"fce14c8cded6d2711301a780a58297c68761dd52"},{"mnemonic":"good dust code sell element tilt host valley climb genre asthma bench","master":"106ae0e9582e9db67ff88c1098d3ef651efeef30d44ff60de30bc0c447217ff6","seed":"1b307d8ffce13f7944bfeee6d6b97de257cd31608ef9059bcbe2cef8bdfded91722fcbf325788d48a5072b9f915670d345211006102e5535f7e2a1dd86bfdfd2","priv":"a78bb63f0cf56b81e228b801cfab1706afb073bc2deb8ce1c8c56f2ab564f1a7","pub":"03fb2144ca5e9dc753c2aa46f94806b35f201d942286571a44bbbb879d2e9e3adf","addr":"5d68a2c8fd5486ba93dc18cfb6a04698250a424e"},{"mnemonic":"buzz prevent cover list flock meat that slab crumble melt prison treat","master":"d620abf2e72b47f061594137194e41c33bd6789799d67b712179c5c9e0dccf4f","seed":"331fe2ce10eb19e2ea13c0ff7abac9b49d43de8d937963e8498da172a46e0c4dcf3e9d276d1e4c7dff5926609936f253e59c814bd4c061429cf1408c45d6e5a4","priv":"8e3b30ec2427f34c463f83a500842d4fb73575e261022720276b3fdeeb20f075","pub":"039ed714c28facded3af8fbd8497b17818cee93d26732aa7258ea61c6f8cf542d6","addr":"74b44edf7f993c72dfa53fbcbcc836c99578769f"},{"mnemonic":"domain tone insane visa much reason tip truck travel head finish grow","master":"3b00a9417e07cbca1d0b80b108cce99089c726e49c267b2e5a2a1d3965c7c99d","seed":"3e2c842cb5d267a2ca3fda4c20d674d048873ca2cfe89e02558a0b585475796979e4bef6e835b17593c53a75f5a4b37dacad0977a6b6fd6589d26502db47a048","priv":"cba9d951fdead64920a36afac46d82241c6084b46681902ad37eed1928135db3","pub":"0321db6f62dd27416d94cc22ebd3abe7ccb66d5e5f57641f79de3d9a1c49f8d0e7","addr":"17d65bc69345ab94e3817738981ea5f9289b81a8"},{"mnemonic":"bone earth country lemon great ridge glue neutral vibrant age doctor income","master":"ddaa76dc4405bdd779045a0b113133f51af43c14ac12281260ea2281a21d4704","seed":"c7edb1f4572aaf510b4b79f18cb68a7464d20babe170b3bcebfa7902f2df2a47d404baf1489922bbe2edb46a2a8ab798a99cb5dfc162b315e4e0a83ddcc5614f","priv":"cae3b56916c64b7303c038294cb1a9c15719e3cb8ac0cb2476e5688b6bbdbf50","pub":"03c9565910b4120ab6a62c275ca0127b717116e773f57eb93d1852ba3d0f2b431c","addr":"81b61de28566c226e0153b1e3afd53697c6591e4"},{"mnemonic":"rotate agree figure style cereal best corn box corn actress toy deposit","master":"ddb3592dc43e595f968e906c72be97c03beb78325f00969311f167e7748bfaec","seed":"cebd7cfb74b2ac03a29e6f4d3dba84d6b47730b478d0ec92f90c9a0ca575d17c581e1f3959b4e0ef5d5f51d43a0fa186ea54420cccc8c2fec8a25f36af549e6f","priv":"b3a7e3147640f66d7be8028a23dceeade18f23bead07774fa5d176014627dbec","pub":"020e2c9e9484acdf5f8a574e9fe912cbf6bf9198579107a48b976da5e4dca2ca0f","addr":"eba352793c5a7ed663a5eb33ef9c44ceb0388677"},{"mnemonic":"kit age click judge decade enable trash noble first grit crop decline","master":"bb39f1d6570a42b31a6b1093d6c1d3d469df3d565ceb2064863e50c540cfd986","seed":"9c8471f0ada1f4e4c4b863811b36036e72818432b8e441ef8234ea29446d2978195da3d63aea71aa5d1a7c4e71e131a90e2db598bc4ca2bad1dfccebeacf963e","priv":"83a532c37858e36cbbb325481e7be10beb2166ddb16b7ea19328e8dd712ac178","pub":"0215f7cac31b44b05f1fac2742ed8a0d6353fbecd06a3abe7946e2dad1feb089c2","addr":"a10254f23fb959df76231ea3061cdde854aee99c"},{"mnemonic":"jeans broom faith border sign decline choose black depend camp nest song","master":"01dc6326bc635da075e100217be8553c30be5c3ee66bd4cb8dc0768777b5826e","seed":"5e7d44489c45338978dcb69035addb83625389d15a5a2284ac888682e7499e8b07aca6ccba965201512ecf7da5a5ef6e22d561583e15f4507eb79ca60e525da4","priv":"07e07f2a2d9eaae6ec9ea7f676124dd14e2f29e43095cc8574b67fe5a8de1fc1","pub":"0295a431168b265c62a8885186b7719298c5791a0d73cb5b6e55cdd7200b5dda38","addr":"9328f2fcffe4db6cc6c8c2a5b0e7f78cac1854d5"},{"mnemonic":"narrow federal feature ignore damp sun brave cram blood crash glory cargo","master":"7e5ad0d0325b2bfc0ac8a2d32b13d758b308fad36c5aa4c497ee3fad4c999fa0","seed":"e680df5400ad6c1f8b097a39a4ce9d9c3c48ea4c21b71795fa499ed641137b50b58f78603bcb2bddae78ff5f96079d48fadd175050ff95784092bc93557d0c13","priv":"eb443a6e96330c1d3c2213e9e345b4cd0e4b2562d6bf13bdf9366f0974d0a98a","pub":"02843de6f3e02767908c2692c091df22867fa783f858a39aa7f6dc786ad5b5d2d0","addr":"5a53f850027b3f303ade321198c74d108e24f699"},{"mnemonic":"fringe fault blind lock wreck one kite ozone system come spring amazing","master":"dc2916fd303a02d0d7ce5d5e0ca55b8c504063c3b54d006f0926a89c52e413c9","seed":"ce52cb29528f78b85c003f5bee65b2d3145ba93963fc4ebc023183618cede1c0add4fbeda85df76e8887004fa526769752808977726bfcc838fe9fcbf4019df0","priv":"5b6302f3548c8a8ca594bf67bbfd44ca98ca84b2df134b0d1edf4b28ccac4340","pub":"03846f7ead64dacb85b25d5279681074dfb9a8c363fc48acc6565c6e142380ae3b","addr":"b32324b0f48ace5119e6d6616b9e613438d92184"},{"mnemonic":"rapid donkey deliver soccer between antique pipe youth science angle erupt leave","master":"3ba5a3b9f7badb433f4235e89359801dbc87b6948e74a61e8555b11dd2f6b491","seed":"eae34a8427228c93f754a3a5ead6241684af42b34047f98b12cb7339f3b7390ca9ebd4373a89ef512e75126de78cb72501d2deb575d356d6ba9d64a8d50951a7","priv":"61a6843aba8ade001ff479a2b768008ff5ef996a5a8576956328815755008c06","pub":"020bb75350f98f845d5ae99ad8720b025d7176c00b6a92a9ea7ac14818a7ae6a73","addr":"2cfb35c09a2a5a458519e036d21555571b88fde1"},{"mnemonic":"juice riot brand example type sign crucial warm bread describe rain slab","master":"9de3651516a0c991dac2dcfa0f95265a6100b6ca605a0d577bc9221151306b18","seed":"5ad029a5964c27c295502b40fba611bafb9b9e626cc8f8df5a98394060d16e53ce41ea46421a615c5a3b5b61c20138466dad1a0b9541d57e8ccf7813ef6d9327","priv":"a54d64cedd5e3b3cfddb182a513a13bfa1cd64627db1fcf5c91f398330010741","pub":"03840dfc1f9d210a632dd38f45fec096c9dad11de2a8523adcc79f4f520faab8a4","addr":"1151a84a341b5b24b687abd2083e7fd150ae937c"},{"mnemonic":"air ill huge miss empty force indoor inside young ball wear blind","master":"76dd3f042a76e88b7d63422086fe0b5242a80775c92ba4dc31b31333c6cf367a","seed":"0df5fefa4beba8bcbdc1e6d4b906c91ca66c14261b543280b31be5e1a37b7a91baf9f34e17143a3e3451d3da18534996a4edcfadeec0971b5b7db225d6056fc5","priv":"90ad41d7cdd253fb10da90c1eb6f9c75120553db484c6e1e2d61aa4ca679d5a3","pub":"0229419c442507c123f161277de5a9beb43fd91556f6cbbf194e26bcf4bcbbd4a3","addr":"68ca6d2e8330de386a3dff8acc4f9be6aed6facd"},{"mnemonic":"electric grape tomato average idea shrug slim certain caught know rather poem","master":"4770c9846aaef6f78e326f3aa72fe236564251b0187e3d8cf2dc95187fe348ce","seed":"d054638cfeac9ab3a2150a49d6854c9fad983e7fc91ccba17d6bc210c976b20336c33fb5f8eaa6e54bd6480487491a1f8150d074b29ece6164c2c99c5427d7c1","priv":"0bbedbc6807a1c2b81f7c1f8b9a8380e27d19a0905eb505630156639d0ea4097","pub":"02be715af6a8583fcbc51f4cfed7e78d93313d7fdd047b198abcdb6d0d2271bca8","addr":"0535e0d51a9f99ed22fbb713b2812e4f2fbc680f"},{"mnemonic":"boat tourist proof point giant horse error trash abandon transfer poet legal","master":"5c366956c526671c4e6f9011872b24d76adcd95de54187d81e3c7c2edc749023","seed":"7455f7f31ee2c7729f7a05b4223bb2b335a0ba5b8ca1ee3f632e04e752294a1f0081e94cbb6763391132562a8f8323b0b05cf00961a2d9a4993ef5ff69d52e2d","priv":"ea1f442448650bf1445c5aa13107210280293e9cbe1b1e432327339db7b68624","pub":"03a80a35d7d599be28524a427dc9b3fb593bd12c7cbef3982bc67523ae6c202455","addr":"c12318aa7559ef40d3b56856a2cfcf89d5f5def8"},{"mnemonic":"number oval section onion aspect surprise romance paddle oval reveal business pudding","master":"2b2fb49728bef8d8301af63af35716b2375071a75b1e2e8d4162afe068e6a7b4","seed":"384e57c3ddb0691d55be1d667dac88873719ba4260fb3d26c263d75d8f5cd12b444255daba423821916bd188df5007ad31c6388b0730de258f543c23fcf74923","priv":"26c77883d1bd7a257d55ff87b562a41408544fb727dd98a7aac093b4a70f75a2","pub":"020ee3bed4cfcfcd28ff8d41c96a1b7851ea3ec4f81fee00ef8ed05def21d37e51","addr":"e8447d8d97950c9a15d3d181a3cb00b0541941b4"},{"mnemonic":"shell lunar fragile unveil dinosaur napkin mountain fresh annual jealous check jump","master":"0bc353301fc1edfb08d3ac53efcfcd96699ffae3174bdc83876df3f9a5fb1a90","seed":"4c8a46510fff2ac0d666176cf77fdde3f2dcfee550260e43bef7f9e6127ad807ed335fccbeb49426aefa8c0f1268e5f602124c2487653160f575cad5ad68a571","priv":"2e783a6c7e1e74645f99752d342aa3b6de689af33c5a80e3abf28f7e1ac0c6e4","pub":"03fead7454b48e2bb68c8fbeb1c807dd4a7d05c6c4c9153d4c516b05967ec56853","addr":"0ff9f27bd866673fb10bf741a221cc8cb4a4f95c"},{"mnemonic":"sniff rule decorate expand siege boat people choose resource topple produce coconut","master":"03c9712b2dc0ed358c17478acf1b3b9c8ea9106c01f0e52056856ed212d4b9d2","seed":"a689100267375fcea1ea18ca798c803fbb6e4b9d82f9f4fc96b3a0873f41b7553589c605b021b4dd4a2db9d3dc5b239053ea5a48ed227fd6db264299fc8d0e96","priv":"8eb04249c00506425b0e414b131ee80dbd8db4f5a873be04a0b1d293203544dc","pub":"031e448ffa6e72016fbcdaa4c2790c8e57145ff051de1d99b69cac4df1f8ccfd0e","addr":"edff4f402b7525e5707a9ebb5b13b2bd03d12ee8"},{"mnemonic":"crumble coach clock opinion net churn cinnamon seminar slot upgrade always nose","master":"8af370254a2887d6d8d00364fc824b6565ef750d3b19fca98078281b040f9244","seed":"1c6241635fcbabb70bdd30d827f602169ddd82e36333aa50a7f7f2de4bbc9a581d6f7718cc94c0d63779f38363a8c45042b76b89610f9b3c2e785de234ba5818","priv":"23dc380f4557ecb1cb779d128309012c409c544c906865b06244e49be877db3d","pub":"03261b2261da80af3a33ca8252aeb21edc608b337761a6aa8160721dc202e65b29","addr":"fe0cb66348437ea5dbf8ca79de9db63f0ff51528"},{"mnemonic":"mind fat sort buddy gap glimpse hunt ready library invite mammal repair","master":"01979edaa3aacf38e619e05cd78ac50eb2729d6ca2d8ca5b476677d30a4414f1","seed":"7fe831aaaacfd5895fd3746b45c0cff02d52923fc3ef55842fdabd02de07bb6bbd07dab7f1db1318f97fdb6141e5ab0142d7d06ae92c020d2be760e08f99661c","priv":"10d3729902b4a8c26b88c84ddfd6201048250294f18a2ff0ab4248a5b4085992","pub":"026cc54074748e623153f3bd4b735d0c7df21cd21fc59cac3ba43292cf0ec3230e","addr":"0b7932471403f4769cfaafe834488587349525e0"},{"mnemonic":"area switch resource vibrant prepare write genius danger extra alcohol section company","master":"dc841ed2cf4ceadffcc8f8f6fbc50dc3385e2b438ba5f985f33dc5c68190c69b","seed":"cc2ee2baa8b309ef7e76fbc14a343a2435d6ce0f7da46d1f9a84782c77e84fd7cc40c503db71f75380cd7e2236c9dd0579b528d84b7deb89b0d4a4926c66a360","priv":"b2fb735d798aec932964121a2a00cfee6184f03bc0d7885a84507ffb1a8f97c7","pub":"024cd279a8812efb672200639f718ef89d9996a6bcd6ae9d50c1548da744bdee7a","addr":"4c56a50381b8edb7e02124e205e170979879ac05"},{"mnemonic":"twenty shift viable behind victory napkin cry gasp own dance primary glow","master":"4519e4b46f8279cefb8b261568638b514f8591a60617fd9ef4c0f03c193b345b","seed":"393b214e7d24adf4912b8b6dab2c779c2896816b1f001d80a702a7dd2c44b5a1efbc85e2554e2586eac150a1a2bf1fe12e08735dbab0ca65a746259bf953846a","priv":"a187f775899244b9a57da9a173614ef2992ce1bd2ad6333eea6e796f04ca446e","pub":"02735247ce372948d922ef85da71f424580a46fcb453cc889411722f8984f301e1","addr":"c055c01a09dfa7b360a99d784d05e715dfb1eb37"},{"mnemonic":"jump end chest decline act capital text puppy empty input possible goose","master":"5e8250d4fb78cdfa191efa589fccb98d2a635d091df8352a0aab57fa13be007d","seed":"fe6e62ac192f7f101fca767a1a24421acda2c23d1c232ccc19221eaae7697d9eb0cdf7350272d93ca37d7e10b3deb739ff0b05ee723a4acc754bb6994d2a5b78","priv":"f400703afc057875c9dd11e046fa53c0edee27c78e2905425a74139f3329c1be","pub":"02c98ed539a5905393750276488e60d851163ea5dbccd25e6fbeccf119b22f88e3","addr":"81473d441525a6374665b98ff30f75b43157b29f"},{"mnemonic":"spend course nephew spot nothing girl wink flight wine hotel harsh better","master":"6d62643bea35847c1ec3b6a7273c42a24832d28092402c2dab4df1004df249cb","seed":"5cca26006b3c22da1622ffd07f0478988c9c97c5f128f78b89fe6b89314ad8c37627f02eb630f376574a38c243a3069c5a34dc59a709d5264f42cb1f80740adb","priv":"dce7ae54553f89302b0aa63a500cee7472a4a33967aa8a1ee18e16aa0e78d2af","pub":"036052be2df30dd8ad7bbc35055a4e60bf520fe962d9c7158d1c5e2b45c4c4f841","addr":"1ac0320f22683aa7d67416e24bf59098933a7e4d"},{"mnemonic":"coast grass horn front broccoli artefact also history screen bleak thunder example","master":"c49a459ec914359418504d3d471fde7fb1a82257347a4bd95997df53da47b2ee","seed":"2f528e97791aad4a82a7af1a68007871a2b4917fa238d69137fb93f64ef1f7af2dc036079ec220b8be11365d62ca11be66e83ba0d829671a55a319c441f6c8c9","priv":"06fea4c71f85b7b161ec6edf5ea0b90cb95a410fda9fee0a603fa350f289ef43","pub":"022756af9a6df41e36de4300027a8a6a6a8f6bc7c2b31252153f3d915299a8129e","addr":"6203a9699c5d1b6bb64d1dae86cc741896792266"},{"mnemonic":"shield liberty wash park absurd inherit suit resist garlic cycle ecology mass","master":"a35a147cfb59e738ea4eaf9e6bcf1102c7d4c15e3e59458aaac528a0635d5316","seed":"fdf1adaddf7f8bec833c3054d079be7a240f98fbf08d051892a02c4b1e1392ffabf84422606d7ef333f99773bb8d51f01175c568a94f5317cf8b225991d7a528","priv":"581e1227a6f32dd51a3bf36e7c4f1504b00a528312f3025f3f7fbecb37b88b7c","pub":"03c0e2eb1d83e266c1c25cabbc6a9d46b0d955f70ee83b78ef0348e44fd6e8162e","addr":"18573866de437d48c044002b20fc5b886cd1dff0"},{"mnemonic":"spider cake process model elder electric mosquito rather choice insect crunch pizza","master":"1c95e3db98b4194020be93e3d4791b9aaa2c7eb1c83b02d7f3bdb07183f4c3fa","seed":"d25f0954443b2c18507a0c71923aaa31857d03187b08a649156ab634c20f29a444ae505cc80515e30feb69c05cd4e133f38b18659ae6189ea27b442705b9089b","priv":"5b9cff23b6a19a67864ec0973e3004da548b5b97400f9fdf2dde3db2469b776c","pub":"03829d931e59a87c6ffb4f8d512374ae7981ccf2c08a30acd787b77c628b727d8f","addr":"aa95e7e0c4fc203ea639873f05503a2d5e98b70e"},{"mnemonic":"include yellow off random knife video person monitor height virtual oven derive","master":"92cc90784cb9a58deb578aafd5b6bddf5195bac720c1b27ad575bddb1fe19487","seed":"7e090c19e128ee76d95f7334361fe7eef356bec53a06902c6c5bde0cfbbc7a7adc540eab3fbaf7d1e4c6ef38f4c29054767c115e6160e6825868a91297e2d5d9","priv":"076608b84151c535a295ccafdd1301e8eb82f779fb4aacad5bc2a1f0a699364e","pub":"03581ea3f2b7ec38ad8ad9717b22cf43192a637eb4d4db0b051f2085ccb43d9e5e","addr":"a68d0470048127c2234f1ce4a70f9f04c72c4dc6"},{"mnemonic":"chuckle hybrid seed portion dress move settle pool erupt segment annual demand","master":"fbad7924603e902337c9f58086a9334562d6f3866c798dece4c1761af9914d3c","seed":"ed3ee02d4b90299b11fbdf6fc7698613aca89749352bb2ecdbd5cf0e0436e0ef702a615ad041bd97bddd4e892582ed9037028002e2bd5c58ae7730c47a44e20f","priv":"77c0167a4fbcf6dc7105af046e2978eddf6366e945d8456c28e13c8f3ae4de57","pub":"039a672d56a39e6aa1bf2d51aa0c3525692117ef33a92ff903dc9611f86550b96b","addr":"d4fcea5b95282e1286e412122701e9bf49bab344"},{"mnemonic":"portion upper maid dash where control nuclear post run manual mushroom bleak","master":"66c9b9ac9c75057c18fa94eeb0f75cc73b90c08eaa3aecb1a83577062be3f6fb","seed":"06d6d3e53986a879befffbf87dcfd6b7570321a071e22092e1c88de34bd44d7ec72c76323fa0a7ca040a7ed90ccd686d13ea027ebb06f8c66154a838de229f2e","priv":"f5141661ead9339621deb48ffa15c4569cb2da05467de78a2eb631a327f5a68c","pub":"029a18777158d04ba09a941ac8ae89366a50dc8253319b71647fc1c6e93dab01c2","addr":"f1fa2abc32e5e9aaa843cb07c37dcd549b76485e"},{"mnemonic":"fatal lend tortoise urge topic sweet spend antenna stock nothing doll face","master":"2d03a7cd457dc67949321ed16a2893792e5210cd4bc0f5ac86af83897094507f","seed":"f48146154da92dab72fc0fbe1f6c7524178301502d72ae7c404b67f8b7e102306bc03f339424b011eb22d15977a0f12ad0b25e7adef5661d65b06dd0b5184dcf","priv":"d5908635bebc92518047b79599b90b1048fc2bf2d3eb36a2bfa5a894927675e2","pub":"02309e322a1c103c44ed7195044842250cd757b061430c55bf1fc8f7f10d660bb6","addr":"946728094cdfcc601a6a496ef5dcafd3de9a6488"},{"mnemonic":"blame margin glass dinner worth right require unknown wine settle make aware","master":"7297101c31d8168aee1fcb025bf1ebcd747ca6d5ba19d2bd28514fe3b0e0be18","seed":"e97413449360a70d3d202dc63ca0670a98aafecbec1de44d8c11f1ae90099bca926813685a429d4cefb6f0e29e207732f29e962aef7b6ae82ea3cf2d7617acd0","priv":"b144f77a520ba1ecd94b1fed5f362cc1fdd7ba9bdc355e9d520c2f39c0a20f7a","pub":"021c6773d45e549503e3bd6983655510a46a873e793c6cdc989356f657f3e5bf20","addr":"f259947fedfbb0ac039a44936e901f3622b9323b"},{"mnemonic":"gate make bird oak brave hole elevator tuna gauge type school disease","master":"1c1407749a31dca67aff767e4b78eca5351ab6792dca8aaa3b31a766147207bc","seed":"e079a04be32619bb57910662e11a006f27b02743e4440136ba02d7915502d0fe1590667a555fa76313452747a1384596950affa367c4a3e6f5b179e750018a7a","priv":"4319abffdaef48761ea2bcac50eaf80551baa1404b27b48fa379172f2fe8e1f4","pub":"0229358636cc2b80f63c7256eeb51b9e0bd3e1df0cb5e69ce87f15d71e16fa4a8a","addr":"d0134881f0c1f11cf9938920472f3d37e9365565"},{"mnemonic":"crumble danger tell frozen define mixture sadness strategy village mass junior kiwi","master":"0dc426f3c99fc31a73cd91f5c261fad7b70e2a7738e6312325686c95dd9df2b2","seed":"773955324075bed8d11f971096456a8557f8cf76750e48fa4423bf5e604943b5ad17788fda1afb47f03cbe208c79c8b6c38105538d6028b1ff4359e7f5a122e7","priv":"86f1207640ee12c8175e9b34cdc6fbdf2c200be9e03697fa82f8cf43dd8a6cc6","pub":"022ff8d5a67f1235242e9e143736bb950d391bfebc29173cdee50fd6826ca895f5","addr":"49fb80faca4a0537aab1d0b7ce5674d4490ff8b7"},{"mnemonic":"reflect mass fall habit mountain winner logic box cook between drift donor","master":"350db5a525a544ff7d82978817ce35f33ebb6c148b9ff6a9bdbd357a16373e97","seed":"4511bc8cd2b64472dbd108250e8d0efd825e763790bdbd44f4ab700c5038ab129e417ee574716e1b895cd660c72f9bc4f1a6a2846e7b09c635db2a51c22356c1","priv":"f2e5782037ff1ae1678ca2baebce674b973aec58caf7aa1aff830b372a6d6436","pub":"035d54ecb4a48285dc13346fe46cadd907e443c03e91339363b81c3d1988b09a38","addr":"6e8114f26eb00d95ea09ddc7d4d5cc104bd3ec41"},{"mnemonic":"enrich corn rose chest can figure canoe used pattern margin usage increase","master":"d38a5d82ce728c441f707cbced8d7b08d896ef9f37d0b563476d5500ca0008ef","seed":"ea926f98f2efb3af7bcc514969bdae01680e237424554b732cb37257e0b9f0ca1303af09dad82b0c967ce189ac8173901937ff42d0163310e5fcadfac1710c56","priv":"880b645884e27fd9205d82ad44c18fbfef02f205455ef818fd3beec79ab08e5c","pub":"0229eb380ec659c8964ca2d19196eb59804855b0d4226fbfc48f2373466380e1ad","addr":"ba2ea36646e0806378faea7ae0d1a691d91b54e4"},{"mnemonic":"coffee labor involve dragon upgrade route south guitar uncover enable soup sustain","master":"0dd39ec2f51c819042ad3fed701d1f982f599383049b38ca36da842bf5d3663e","seed":"f81aca2d700fedcc07990f1b9ecbaf194c0df5dbfd240437c06728bebf0022aac77b8b44f7863b13613b4bc5752f0f19e2a21617e5e0578e53f9198c2ae853cc","priv":"12c7b8c875fa9d0117b53e2e539584c9c524fe1519414a13062edb33eb712408","pub":"029b8bea854aa1d99e6564e5f4c9627a95d1fbda000a59ad3049baba92a474a5ee","addr":"eea20101f17d14b6bef65b393a49b9c558f5b87f"},{"mnemonic":"dash clutch smoke chapter lobster quote fat negative desert labor rent basket","master":"a6dae26374b6e165be90ae4f1759fff4dc4da104493a21c4e062d42a50ce1b48","seed":"2c4d251fa5b3a634ddafccb16393730cbdf1a1f20b44ddfa0a25ba2e5b6a48e8338e5e5a8a0b65bafe30ae629126789264c98a4b02ba96da5eb3b15fe5a296a0","priv":"5f7246020bfb4ab5146674df950ccadb3b014cb8956e4bcc3b575f710b4cc4f5","pub":"03f2712cae90744dfdec3a37990221e86063620b7298778ef4cbac6f438764acaa","addr":"7d8dbcba23c0e04ae21d250c585f511ebb825ff1"},{"mnemonic":"toddler juice raise depth club rebel weird portion void minimum game typical","master":"d56bc0aa70e0e583c13ea0edd4df5dd6f3b02a9a0434b0614f5fd9c2ec029b58","seed":"373286db33542c525710b01bb881158a7a1c723512596414370f1547edc08a11738d855569109b2249f927839c53361c8e0c8c468a62421c998b97fee5dab6e6","priv":"3db2ff05ae17ae227e78096b9803281f9332857f555dec941153805377f38520","pub":"031a9ef5c0a80f32c99f8c3af49b8fc51b3902ed13832ffcbd0f9527e057c0d56f","addr":"e5b70525b5b3c325b9a2a044ef05452ea0dd6821"},{"mnemonic":"legal lizard easily dream push business village network bread solve predict surprise","master":"4495fed7ff0239ac3a3ce75f1ec1e81fd3c8f7ac2c3a2a9d94f0f82a31042796","seed":"a709e3741759029624f534c66e8d8e56bb03fd8df960fa4776daee1c61810b96c495bbc3dcff634ebf140dcec9f7da9151e09856ee16ba5106cd7c1088032ebb","priv":"5e3e0925e33311aacc94b1d29f359f449d443cbe618e0a689d0c40cab692af21","pub":"03e2b6a2f99cf742f7c1fd356a6948df231a75fafb3cc471f9ca4ad00ddfad8c2f","addr":"c0980871c3f7b15830fa514167c90999279d496f"},{"mnemonic":"draw boat debris humble cactus method duck ask author soul busy assist","master":"8bbae4af997d4735d14c988cba637bc041b4b0907c5c53ecccc1456b43ea79b3","seed":"f05a91da4ef94c81e0bdd30ed6d9cd09cbff7013c693d6e8261bf2eb3cec9568fd3934551344ca8c768bdfdc44fd1b30a082bffa2c1611654320948883785e05","priv":"659c3413372935b99cc972629253f37305d258459c1a92b7fa81883ceb6dbb54","pub":"025a5af583aa8bf4459c72c9665cac772cad9fd49518b9080f635a4de283542588","addr":"36d01ca7b9f3c37ccd529033c15b1c089b877d8d"},{"mnemonic":"between equal crush suggest spoon material poverty diagram forget click company call","master":"3f2d83ceff7b98467d9cb2523820f55d22abd1700651f4b71ad6856c029ada7f","seed":"34e2764bed365dc73de440475c23b18cd69750977a4197a2efe374ef552a9c56eadd6ccad970c422730cd51e5ab4e051e4c86ef4db2284256186fdfa0ba92434","priv":"62febeb0325ae75eb0c71c4a3ae889a4a274f4ccc361cf0829743d5add3b084f","pub":"026e528216c24173250fb71c73019ac45e6171dd4f9d8fd97b0933fa964b966ac8","addr":"22aeb188b3a21507a27b35d860b583d9d844cb91"},{"mnemonic":"cram palace round input disorder armed wool cram over abuse order grow","master":"5c040bed4bfa8520ccdeaae710403b3ee7b77e069536bd87babd93c09177f9c8","seed":"df3911a2a01087b8826327ae368abf4dfac62258a1a7a91cd4ac64067d926b3ab89deda5a0e5539d8c0071d14815e2aebbb913e2e506c6574ad973f950049d91","priv":"87a97c3f977b1ce0b9dea5f2ca8671ab6830f9dd4b3da8195e603b7549f529cf","pub":"029722cdb8ceb0be8456ce4dcb24a4fafb1028ebb4d35b4af757bf22e8539de367","addr":"eff0f2517523745b0b404f688dc048fee89815de"},{"mnemonic":"donate view volume faculty anxiety degree brother cheap film eternal hurry debris","master":"762647d305701dbcce0a5bb079077eb514ad72981fc8489c6cdbd71991d24179","seed":"566c1fbaf6ce9a0c7352e903069b332aafb438ff086eaeccd1207b6fb8a9f0a0a4279307fa987a905ece60a04a52a59b3db45ec15892ba76b2308cf9db8e36ac","priv":"c0092fbde92e9ad29a52c825b8187f40fc5e4ca7a586f4b5b4a8805f0554a0b7","pub":"0340718652a6d3d2b791e79fa91e96f60eef740d10e3db8c8b206457f31b1a0aee","addr":"315ac67c85646a6ff00192c6752301f11e19e409"},{"mnemonic":"pattern much pilot choose prosper spot shaft camera unknown target wing movie","master":"1d04a744f4e0ca2b180f5f20ed34bfc800d0c874d232b5eee1018142fa612b15","seed":"2e1bed0a31e13e8f13a85a35ec1531a93ef433c96338f3e6533dd13d5bdae15bacdbeb954f9613fd4dfb6a941357fbcb5908520096502ab4f6edbf0c93e6f559","priv":"ec42f7fcebafba29c6d692ba732e8060d7050d7c57ef67c0c9d8ea152494a804","pub":"0295575d1d162b7599175bbb5b213ec3e79d6b632f5e50b6ba84e6a2ca15d70939","addr":"ddaffeebad79dfb4df2e2e35d9b6928900d38179"},{"mnemonic":"cruel tooth rescue step entry shock uncle crash possible inform inmate such","master":"f02e38437185794196a7822f0e4badce8644354fcb5d03e337ecee7ca0241df6","seed":"6dc6d27c01e91879638ef2281c904f2b3b0df18b0231c16f1518b63b39ce53c59335cb858b692f50decbe6fce2617434c927cc09d428a98820563438cda13c50","priv":"339120a922594b577d1f64af46c9dddbe0239a1ebe0187569c4302c035df4996","pub":"023e91521223a9a95c1df315c36ae543e606f426e1dc0b4938b374af5fa4967fff","addr":"c5711e1ffa2cca8f18b9be910c4c31330b8d60d6"},{"mnemonic":"evil height seek edge session require obscure begin skin outer foster able","master":"71495c08143478276d1107b9a496ca0befb1663524e46ae824b65e979b14b22a","seed":"2d209c72dd757b948bae9ac1d69014bda27b76dc890be357f542d994ee79329ea51114a1f721d17751152a1bbdd5c5e836771902ec6113c716fa016e30309a31","priv":"862d6335c9d39a65655c3fb644d71f9e4a902f085741ea4df75cd36afb94b0f5","pub":"03004f2c4133b0ffd92bdb3fef5eedd75bf04b6e7e18c0dea3204989476ad3762c","addr":"5d422b55f2091fa9e350655b2e550d209489318c"},{"mnemonic":"gravity sustain speed quit clock cage cupboard radar injury unlock sheriff alone","master":"44e4470967f781784b98f1e33d8fdd16568d1d43b1de044541a8e0821715060e","seed":"6c58333728b07bcf95ec884cb2ccdae5ec12dd67c3442044f7680a87c47da325429bb280727efbd848ee7f8c5fcdd433da0e9de39b21acb66938427ef6ac47df","priv":"37a9522e106495f859db94f5b6efd4e98d49e352b4e82cb3fd6ccf03bbec4b90","pub":"024b03123748ed0b4fdd8f6a351d1ab6a7167396fdd583aafc15233f5e79e3134e","addr":"62994a9de9dc8b9c9269287b63d847e90f519d59"},{"mnemonic":"fetch uncover sibling unfair brass explain sorry wheat talk web news exotic","master":"1ef8d0946b982a3233328040bb94e8e8cd0d5fc24b345f55535a8e7a92c22b67","seed":"f5b3db4d9c5686aff4eef0b0eee3cf88c4ffecde0e9b1c6772d9071fa433d5ccc9173f2f9e95114b27a37a1d91869227f8cb46b3ba26323e237bdc7a2365761e","priv":"cbb0527d80293daa1ccbf26c5e8f117123a63c0adf772bb80700e2334690ae61","pub":"0271bce67767a922d141970501f7341e7ef0f5d877df908c0c06e66000b94810da","addr":"368f8cd8319772499a4f2f109d440c2e1ea55038"},{"mnemonic":"follow actor noise creek afraid normal exchange universe swap draft cake forward","master":"7a443b3ca6069d981559e8cb1db37aded7d3e25d06f2f5ad35867c2086ae4cbd","seed":"3189fb459fb30288ea67a8cb2a46eecd8854db40b7f5b828254997301dae372d05b3eef58b0c670b510abe11ef7fa506b74a4280be94ebc55dc891776599fa3f","priv":"17ea39b63689ae32dbddaa2bae52e8fbd79d725a6a2ec0b56c432a90a1036bbf","pub":"02c3460e957acd5e228400055e9e1b22fc5fba87b16212382ec78b6131d05060b3","addr":"4e981e57f9e23760cadf381d28eb56d225f8b785"},{"mnemonic":"pulp fire pulp salmon finish question aim unusual casino super label soul","master":"3041f6724fc8fd54913ceac5487cf0b2a1c95e1d2cc65272f99d1d0918d73c20","seed":"424b5c69d42e95405b4d78c60f8c4541fdfe0600214623631154e144cd2ffcb3d6996fdf8838a07947a6b08d9792e6e883820399429d2427eaf4ca3cf2311e89","priv":"19026cc4be5629f8580b7cc5f01e36cea0cdb35a933d9871324b53eb9e4d62cb","pub":"0355a17ad503b793fd459e58e7cd85e13724e155ad487d9bbca7e49f939a89d514","addr":"e26908acb2f197f61f0036aef79f9c2b8e67cbd7"},{"mnemonic":"draft clap afraid census image debate pizza display sweet square today floor","master":"146c029ef74c9c9d00538cb03e70ffded59641ff8cd695e44abcbd71dca0aea0","seed":"a000df2590dc0b74a6b1bdc868079ff3172fcb9f758f7f61e9963aa49bb9ef1715985f3b88b0d1b22fbe5d30b2fa0dc489c19ab2fa42c5e62734585b6b35f212","priv":"4e39817ee6a106cd3b58666b9bd419c246caacd755c302c5440f7ff8b59a3e20","pub":"03532d53d02bdc71b0ffab4f5dd3222bdd8b49117ea8c10eed11882a21d604c72f","addr":"4ca53567a3b12f8bdc8cd66b1338c3760cd9def6"},{"mnemonic":"virtual search upset mushroom bundle vicious soul fine decade reflect basic nurse","master":"1e7e15314e1cac1584fc5d6fc5609db315a3a63c1baa96afa57475c7e05b77c7","seed":"183399406bee3c1b8c11ec94a8528e0c26a7c22926f286e320461809f84976cf31900b436022acf4635066c55bb793659254c75d4f18d692a07e20026d409986","priv":"8a07be43ff390d981394dfb29638f2464bded05d5daeb3bb54a93ee949f2da36","pub":"0336378e1b67b1588c6d5e279fc3fe58115cc24dee0cabb5f728acecc8ac6be8cc","addr":"e12910be135809fb5a6314212975564422d98445"},{"mnemonic":"venture wrong wheat oyster buzz cluster abandon rescue alter frequent way scheme","master":"15d4683cb037b61ab1fc64adbff7bea44f515683352cdc3b7e8c6d97700d66c1","seed":"0ea9eba247cce6f936ca4958c64cd6f8f19c3f68914018ad61ef9042a4fcea4058f32017ecd0f672cc8ace9af4d06b59bf2064983fb4615edf912f73343a734c","priv":"47006c978ed707415ac9da1eba861546e6a6150170db9699b585648dda4c863c","pub":"02dc09d31bdae4560008e82db56cd81fe95b6a6dbb87020117a98ea071753659d6","addr":"4a5c5ff9661ef26136b09a8e6af9d6aae0188e2b"},{"mnemonic":"consider sorry keep source session simple solar acoustic crater model hurdle champion","master":"2c3331a974819d6f38071aa2c790c42ad7e97111f5092b00f972859867cfbc5a","seed":"e4f33149ee0eda7a52f5f64d1c8ea945058b2f3b2cd0a0d8a85fdfaa2aa0b559bec8bdcbdb5703dcf2ac54ba7066f4d6c95b03140680b1f1d30a6305e4cd0b7f","priv":"3030acea65637e530cc39df608f467b4df6a47aba4e241c7579a608d8d53f12f","pub":"0340b77aae056f3e3e7e7bcd670c05a3c8975efed4e7efa0c0932a48031a242778","addr":"5dce4e49e053ec6443fdc36f11f1f9f233644cb4"},{"mnemonic":"salmon allow rebel eyebrow siren remind mango round task ritual exist course","master":"7393e3b637917023a724ff52b1f651f39da8a0d860bf20cb810eb635ca348eff","seed":"657dd9b458793c826944ce50c00f6cb97877543ed7dd6b113cafaa7971704a8ca5896fdb5118aa09c52cfd6b28bced9446a86258cf432339549e31b3abe0e279","priv":"46c0e6f6d527a46ca2b44d0d6892dc6c816bc0f1240b10ab2ec9f33050e35666","pub":"02cc668b114070164065c79990db45a64e4bcc5052ab0ca65a68f0dd3c107e6937","addr":"0da2a43e892435f79c2af7d62cc823adfce0355d"},{"mnemonic":"camera casino cigar harvest prepare satoshi close ill suffer chest parent urban","master":"1f6eeefc59b6600a739364a6606ac2c3a151b4234f1edb6efb97da193865402a","seed":"44388f05937f5cb3b47893b75aaac78ae919e4aba29f0a6934ef15d6c7d1df6e5afe36743320856181b5f0a8bc02e731ca83fec8dd501c9c845a1f0325d74a20","priv":"e6492972ca82c2cd62006bafe541c0ad5c6bbb01257600e8168702de496f3e37","pub":"0219ea8444509e7894ca706edc46a522244acdd643bb09d3856db3d9fb1c9821f2","addr":"593e42b50fa2f4491c831039dc1b4489333531c8"},{"mnemonic":"staff myth increase tornado student scare awesome fever promote vault write head","master":"5ce65c1772d4ee171fc0e843ee7b6124868d25c2cee48eddc73e92b805ea2239","seed":"88c5df5805a91765a045019ad39767a4aae836e8c0f53542c661934c3791f94b9d35cb9b1fdc865deaa6f749e583176ef9f114774fb0b59c0637d1e66dd6694c","priv":"066f7c65cb33bac2ef5229764c316ed587710752d456881dab54bae2b1ae55f5","pub":"0263f5acf96f7e6c02dcf040fa765db8fef8ff317400344cc92fa3f5d58f19755a","addr":"fc00f9a09aa3316fb67dba9e08c66d8569f055e9"},{"mnemonic":"during smooth snow please surprise winter measure weapon bench possible write night","master":"0af6eee6b3acb361f5743fec61f7377ca5db5e90a303484e7f877ade8da1e0ab","seed":"104ab4eb787b2da19876c47e1372bef860de1535ed30deec9887075d8f2c56213647f0e8d6b472b23f5ab6dcdc1f97cc32ed2842a0745589c196883967f2fbc4","priv":"0eab899fad8229fc681fb7c86d8102d4074c68e6503c644790125bee07669d76","pub":"02d13bfe147b234f2a81e3e2ae0e630f6be4bd56fe44dbf59b2336c689024b771a","addr":"86a7e52857c14411ec4bbb6c850822b7bfc8b7bb"},{"mnemonic":"equip clarify march rhythm supply attract dress sell clean galaxy index river","master":"aaa85635e77e16d5393f4ff5c73b5556b36ddea446f41c5cc3fd4cf6da2f324b","seed":"519f319e5c87b49923ef60a172b731c50da1da2eca2dc130ec732beaed5dcf161c2c4c98ec20b539259862456a7ab2c5f63d7789da98dbcf01ed23a3be7c00a7","priv":"b42830645c0a8c5fb59994bb7588e8fa80b6a3b95ec223d459a6652a9f3bd641","pub":"030b9ba15ca8ae95d10eeabb8b203b6253c0d08489c02dbe255221c42b16ecd043","addr":"5ac5bec20480d7b9007c9bd184d064ab6b1c9c75"},{"mnemonic":"session hint oppose damage illness metal combine bomb cargo unaware gun artwork","master":"d6322887157ca3852f75204cb3eb60ff3eec39450913387b03ac973f5ff09ab5","seed":"09900b51d5c10504fe63272bebdec8c2fde49190039916839b106af4b7340595cd5ce7a6be9866df28d0a40618b23d09a6f04bb963b05ff1b7e272bd0f0beced","priv":"3f012cc4faabdba2abbb64b9313d0a574b8b31c1d22f403f1d344d87ba3246c6","pub":"03b4a66483e09364f2fe2d905fe5d0d897ca32752df20ddbed0206e383bbd68810","addr":"0bc20be767a401a01d697c5afbf331fd7b3f4acb"},{"mnemonic":"gate credit cage whale razor come opera net speed dinosaur fold witness","master":"8e48eb7d42fbc6c30601ab45da446ae6c0ac2e9b709ac428fe1f98b5c8adcd28","seed":"be8b77e358eefcb5610dae1b36380d25983f1aa458c208e75a9117b507fed28975787d4531cf87edf366c29798a4a6d8b44d6dbd090da8eefbf6d97477b64ae7","priv":"24ef322d8877b9f5f352f8063498527685de6b7d056ca7776dfb1ee34c0696fa","pub":"03389070a550617f89cf46c1df8269a154bd4811ea7d519445ac1e7e3e3f9ecbf9","addr":"45d1a0a5f79d849577106135f7065782e972ade8"},{"mnemonic":"belt girl tribe accident machine library verb link host wire hurt elbow","master":"d604893e69b68ec73d7abee4d15303863ae766b867400eb6cc0c771e8eaa4a16","seed":"ed3677dc17838f9720d5c574a6c70e80c185a5df1faebf07c63bd64a3cbb43818f7337469d48142df4e6d0254fa73e8a8105c6306568bd8e3a1fffd2c9d85885","priv":"cc6d78f6b72176d96a3425cab46866499fc57a8de3a49d5b30030378982911b2","pub":"02926ca73be56e04b363daa330ad51514595250d48d8983ddf29f74749c1a81797","addr":"00cc426c8061740249ff1219b322f104f548449c"},{"mnemonic":"kitten monster sugar game word lion census purpose defy rich either distance","master":"d697b6319c74c77415f784aaa6b341a84ec08eaac0a3bbe094d5cef9be94f673","seed":"f6bcaac87b81723ee589e635ff4e5a5606cd28113eab6846f1e7d5bcad758c1af1c8c77c111ba1cb502f33418f1436220a0a080ee81c5dfd012be5dfb0bec360","priv":"cdc283846e3c5be0b327e48a83fc72d85521bf51321697f281333b6eb7fa83cf","pub":"03711ad3d292efc08729a820344bdd1efb9cd87b083d0ffd65b49f998d1808e520","addr":"71f678f7808db66273dcaf51fe4875fb4c47c80f"},{"mnemonic":"fury tackle glory welcome gauge rely spice profit east science nominee expose","master":"b04bb080a9192b41dd7ee5f9bbfca1396970ba10c54faa1b7a511950b2ac85f0","seed":"5c6ecf5aec8669d62d5db9e39a5c94167bdb21e9380f8efbfc967420a71e0be1d72553a2b84bac9b8fedcbfaca522b82b7b80b531615b9658379c236cc4bc5bc","priv":"05fd2f8cd2ea1cd0ddfe2acd25e498ebd81b902d51935ad3a094a2f2c9c62ca0","pub":"02c4730d47f1976f2a6412681ae6cceb97b899c4fc514b67b9070bf236e906bdde","addr":"bf3e06c5713080e1eb287d2eadf49de120aae6a6"},{"mnemonic":"young chaos must mom ginger hard symptom ethics father rain join time","master":"d9e68439465f5375de6e132498239c9d0f67f7caf16cede036da3fd1c3905522","seed":"4101de8d7cb1dc3176ac0781e94594a37b894ebccdb9d934bac104d7b22bf68d863fae68df1734ab10302025e53357b33ceec095e59505a1461aa751ca77e5b6","priv":"e8512f2fdfbf6bc1e125323de28f9f35931ab760bfbb2a736f750e3bf116bba1","pub":"032f51ba96193a6e24dffa85d748ed2b86e3677112b22da1d6dd5e2d98f987f0c5","addr":"7adb4deb8d4ee9aeca2dcc4dfcd5d1dffd3a2cf6"},{"mnemonic":"dash ridge ten when erode certain game rural canal race surface envelope","master":"fa20b9bbbaf883069a6a282b30870bbb02c8aeed3c611dd3c931bc217326c210","seed":"276e9b97f203454480976e1d86d4abca6072d05e4bd5b1eb972fba03cd6698afb7212e5fd77ff84bb8e68d45c641063550bc8ca208c00604f609a5770fd69b15","priv":"1d2ddfd078682c4d3950ec841b8555fb37981313d0ef69a7bff16c110171f71e","pub":"03f0d1613f82a900455d6834f6a02e037e3d6d7fbe08b1f3a278b2a5958bd13490","addr":"b190466866cfab3ed499547c88af1372f84ab61a"},{"mnemonic":"spend echo addict brave reason tell valve emotion gaze seminar entire game","master":"3d139abc58b8022d8fb2f0c622531874064a80fb4ad795b024226420f30f8ff5","seed":"d9d04d4207827877636a1a077468d2396dcba6ecd3398cdda7d4c15c1365518a5131fa12caef14a2b23702957b282903dfd96df19419e4ecdccf7c38487a0c9d","priv":"cd5f726ece1eb6653950ae42c9fecb053274b692ce6a58a5f630716fc9cc172b","pub":"03e79f46caaa31bca56700d91cb366428839fb09d027d13001ae723461e8575bb9","addr":"35c04d25b3205e9cdb5283b94f328792466ecbd8"},{"mnemonic":"moon argue laugh point unhappy long bridge water naive suffer curve duty","master":"72c22a1d7ffb152045afab5ab7831efd0910c0a4796b20fe9b741e2a06a0562b","seed":"c77d143d6a040b08fdd3a085c9fa097508137cd801e480752dfc55f776179dddf01199050893ca833af63f6595fd60b4d14944e31cdea626ee30777b681ebb66","priv":"af0e3a2476271d7a31943b44dbe9affb5c04690c2f9e1a559674f028a8cdb9ee","pub":"038beb9938f2f7bd600f8b0b48d85ddb9a09054534ccab4e5a3cfc36523dfbdf74","addr":"a7799a4603c1cad8209f6de4cff709ffb5ad240d"},{"mnemonic":"ceiling mother twice mask pelican glue such giggle session absent sauce copy","master":"1ab59e2748679caf59d4646f51b8cd7cf27c9e62160bce71a2da081d57e90a53","seed":"f46d771930a5a1f69674aa4459b0120ffc52f961d7f05a4f0629e580e3027e9112b81c582a74f92a63a0235d275be17a3ea24e8f3d86d2f460142cc3c075f352","priv":"2dbe6c2f1f3389a29271ed7ddb5d5b6aeb44cd3d762b9c5949f981f130c096d6","pub":"03da1b7e3745edb58ea53dda791d7dabd4945343d471f41b706ef2159f4895b234","addr":"14a8aeb393e7a99b53cc3661717b6a550f4ca30e"},{"mnemonic":"siege welcome clarify bread decline educate off snap canal north glance flash","master":"fd57e9d99aae7bddc7bf2218267db21683280d1c1fcbf1d0713d35c872dab359","seed":"d1771068274d476b8e3953ae1dbbac392157fe72dc01d9c1cb66936f26b07fe9de52c257f1f8a89ad5677a786a32b231bd4415a7fd6dc18ebc70d53c16d91f9d","priv":"8d0c094475b505e3c32bba7ad6817460ac20c5e75e4d5d0899d96fb2dbd8f43d","pub":"02bb4a1051ab8df516ba2b5bf42a99dc1a153127312a81f93b16121d2c60dbba1d","addr":"43b7281f4f0495f6ffcc129e1fe90cf772cdbb00"},{"mnemonic":"total wood brief sail top stomach phone silk soon flag beauty equip","master":"2d3e2c155708e47a76ee013fd8bd3d62b17b467fda08869fa5b474cd622c7e87","seed":"98cb2c832f8a2e59601b5dd85c1321251fa576f5e8b9ac250d18e45dfea7a492c80918d864f32d1fe0f3dc24fa1b8eec3cda8bfc526d4826e94a7ac352edc705","priv":"5de85e11fa81b39f6cbd36182259fa33ecbdcf309e2256a1ce91500a1c28fe91","pub":"02dc14302285378aa1783d6395e45b37aeec4456845bb90dd2436a15c601abf050","addr":"bfac65e04a1d9f0905e0d0cf87ba1531bb49bbf2"},{"mnemonic":"junior side human tomato army twin tired mammal sing evoke tape fall","master":"0a491a1d250b31b44ecf38584c65a733e785d65082d693847ebff6f7b749aadd","seed":"65c7faabd749b66f9f16b234142acf734fdeb1fe7c9170355471c008a3224c40c5c2b77aaf516f91fcf17e73f2905f021354561e56ccf08a9eedbe51ce8e8fc2","priv":"40dc50171a806155da73f7c5cab57f7db270e225c33eaf0665c0067e1d2f7743","pub":"037325819201f9eea88ab9e6856d2e60f02c41d3a07c09fb7161c42e05b9db824a","addr":"9acab1c1329b243a5959cf716dc5f29ff1a9bf33"},{"mnemonic":"fitness wire sun minimum novel scare response ten profit breeze equal wealth","master":"0292d1ccab93ad054ee3ff95f3fde715cbfb9b896894b56193003861f4403763","seed":"ab34f068d14286ef45af4f3339ac19d8704d84a3f4af2c00092f431f919252487759c7aa09511271336b3a40f446087e7a63d1cd5603244124fb746160ffe872","priv":"39ef24672e90e29f268369bdab5aaf09786efd7360b535bb4846035b12d1aa27","pub":"03db46d9a6c338affda7db18355bf17ddeb8519a59e193bfaeab4fa522b4124288","addr":"c3cad6c638d4f7d0a75dbbf9fb2d170f79f1cbf5"},{"mnemonic":"quit present half acoustic uphold buyer measure matrix uniform black play vacant","master":"6f8c86f53dab7d379e621daa00a25f6123d43ef2452ee6b7c20e43dff1379409","seed":"bee800b88e86d04b9e755c63669dd4d324c0640e1c121427cd08d1bff6897fe622320644844fd06bc16fd9bd7b981e473cca7cadebf7f50ebe3f917c0721b988","priv":"6070835567461840e0b216338b4a08313cbc3d8e805cd694f379fa0112975523","pub":"0296271e75096d7bfb7393b449318613c522774e7b2d4e0eed6161e80a9376bb91","addr":"3885ad9e25c274d8e461f4b685ec921aeea25b80"},{"mnemonic":"endless blade swallow bird faculty group rookie betray crucial amused gesture pupil","master":"f62cc9bd1a5d26309ff51867edac4548f63e30630afce94a59d94d77f6df34ee","seed":"f4100b5b36d63b0a87ffc828277c8eb2f0055d2ef500b402572d30cc23418960b831c84566153155d33eeb8ce65ac191882810a1281e87c7748bfb592103582d","priv":"14125462458c4e981d9dd963e67965ee70eaf50af376daefbd7f89a3d0cafffe","pub":"03b64c625b503104cb0f9e8de837c741c4952140348cc5d7d1ff379e35ae37df6c","addr":"64d529a1cc4a11c305c8ccbe24217f52be17a69e"},{"mnemonic":"evil lend heart deposit index prosper mammal vendor expose sun arrow school","master":"d3402de3b79b24291822c2737da8e7d760267adcbcff5af52fa7c33ecf199acf","seed":"5062aebf0c68ec4ae51b8f9bebe4cdca4a07989ed9a96888205a84d749ca90f8d9f2c992862f7fdb4bfc3fb2c590431c5fec415abd9a2d4ad04f7504b90a9081","priv":"ff7fa17496fad3c29afa98d427186cd43fa9aee71e2a81d2640fec87ebca2ffa","pub":"037eb47194d9fb1e61a65e399d06bc7044d02097a0e5939581fa9b15346eea38ea","addr":"8e9b1eef983e035d41aa63ec276454a075c52db7"},{"mnemonic":"various cruel sunny human sponsor seminar stumble romance hire cabin blast rich","master":"25f93ffcc752c263058f195fa4b2f80c46aaa057b399de9241c0fa8cc2d3ec8d","seed":"89ee6d4b8a328ec819556eb043c769007e332ec4ae0309c6b6f82ed70b725e9ac8d64cf1309ce0ebb0053ba515f6e42d1273ac4d0d1b9008b9375844a9e1ed24","priv":"4aa30facb3367721c7e39c3052e7221f0a926a00d00898699c483cbeff39e407","pub":"0312c6e2800eb33da7459a510d02e0fc5c91778c115c535eb429c2c5797675e2a4","addr":"9178f5d44bc450a7a1fc5746d17440670fa0eda8"},{"mnemonic":"kitten rabbit warrior replace dolphin banana aerobic arena elbow leisure slogan panel","master":"28b0f611c4fa230cb47936546853fb9f0e13bd6a4417b5bdfba9c85eb80313a5","seed":"88a78a4f882820e729d42557ec5db0984aad2aa40f535ea33416b0b89d25511fe4b6e37cefd23acf1ab65eed77b0c6ed2e453a2c7e8d509311cd802eb267200f","priv":"3af577c50bf57b6f44686af34c65b683c305496d1799c7c0d9febf9dacecade8","pub":"025901819b5c97d505616f3d1b5be0923564d5aa627885851bbef7b4efbac4f95f","addr":"9898d22edfe40425e714b877a5edf2d9ab5d7172"},{"mnemonic":"shy abstract heavy silly excite response figure math travel use cram dress","master":"558875deb7ade8202aa21350c8a98aa64d383c4b8dc6315a5bc149823398c8f4","seed":"256d310717830704992b0767827ce796310b3f561f5faa152b97c6bd9ca1bd10505049005da5026e64377dfc9b9a23b8f71b2dd8e4ae0644055a04b650a721b0","priv":"80c1b4808495fc23f7fba2bf9ff39a4b084371807c61ffa6f6b60cc863bc8fa8","pub":"02268631554db3ae0b7ac58b2437556d91aee4c2ff2eaac5e4a3fd6ca6d96eb960","addr":"e1b0517748e58df2cde812d45c251492008ae499"},{"mnemonic":"tag aisle unit arrow neck knee border plug order decrease corn hint","master":"67412592e636701931c0b0723451ee325db3b1b7d63938c83ab9b4aa5630be4a","seed":"590e676b0362db643cdac3687e67274fc7f67a2f3a6f274da3e8629893b1f474fc608eb2928fa2be01b9760807055ba11a7ca4b52a28b2f66e05bef7f09845f2","priv":"1cd36df351f7dd9b4746bee1d59c42f12b21ce84b9979e39b3b810ba95d13e56","pub":"0217468adf9b7f74d88b312883787e6baadeacf6436986573371bf19c359ce047c","addr":"a719fcec68779b1f0f92460e511739e3bc704be5"},{"mnemonic":"urge order bomb glance dream diamond cute quit napkin swarm oil taxi","master":"e7c99156c46a51a308bb59a9be9cec9d45a55a8f10908f2294b4a35734c24cdf","seed":"a31e29edd9da883053ab020e2058d482cf2a63b39a7d99f47a5972820820d5558f24bd4d86470f1b8f6d1707c059e2353c65ee69e0e2924376f84f36e77571e0","priv":"e204a5c8377829edb3a8866e028294d6fa34c6dcd76d10cbd857afe41f9f6852","pub":"03de7949f7a90aa8f21731e2979b684c6424537283dd15881f31541f14a0837042","addr":"fa9f6d11bf1fe75282dc336ac24f790086794ca7"},{"mnemonic":"drink combine way human stamp code chaos honey decline reopen candy stumble","master":"902a5423ff40734c67ef9ef008e63a232d1c0e30a8b8b75d911a5e5c31be5725","seed":"c5ee4ef92fab9bdfab9e859bd603a9b293509ae3b99427a3db2b3eccbeca2b2d717ff5d5ce010db0cafcf261e6addc949bc3c0187a121e303a0246125ffc249a","priv":"59e235dd2d86967f6690fe2171eee062c5e786ea6a0060069fab9dcdea5bdeb7","pub":"039c4adb01d0bffdd50a34a458ee58e19ed81d3f22f740af2414594e42447c9de8","addr":"3ae7c41fe8a65e527a850a44a5124597f5e43f6a"},{"mnemonic":"will confirm boy glare draft hospital grit marriage hen radio coach cram","master":"cd54fa9f850f2e90ead19946218c1c03ba1491d1273f6e2e59816e50ad80137c","seed":"1ac5cdf381522c28ff90b993d3a3612e0f91c08b89b11c83315ed78b7d89e7a342621344ed75a7bb1d996487da8b60ffaa75ba3ef504814636471fa017f76b06","priv":"c63babfa6c2e301910bb8cb846259aa0062e25ac8523dee9449354e9f44ab49f","pub":"0272029d11d7a1998e79230a4e82aceadfbe29925639f6ca6dffd237b7c12a6867","addr":"eba6a2907bdcd422c68a04093fc5127ef2945cc8"},{"mnemonic":"sister mouse nose morning remain bike wreck reject flee depend foam oil","master":"480c68e256ac710a18ff386a76b2a3ca50ab4214a23d2e162fd473f40e48ef88","seed":"267c7df08090f9d95d26c130af19c37adeffeb28644cb449a39fdc2038a5a87341fc9fb78a91c9d19b8a4843146e79e57cae43b9d1d65042cdbdc8f97c22f02b","priv":"d6d76df9474b038eb47c93ce8bdee2163ed5906475bfe0d40b31bc19a501a2a8","pub":"02a70a232ec5b59daa30873a4c11a65848d6d90b5775e488b87d8829a368fcd2e5","addr":"dfdf9f283fb3e21240437a994ccf124089782718"},{"mnemonic":"mule parent ritual earn swallow visit jelly give sun family scatter lend","master":"946aee32749e7c2527a9d7066df275f6a58b4d979778f565e87db434a4d82ec0","seed":"919d5d8ecbf7c9ee555aec51c4079aa8a97ba7c6207be27a119b307ecf5433e0e44856f21808b1a7c65ccd7efff25eaccb445cdd3d45c682aaea9d8358fd398b","priv":"1ff4a74557f15dc78cbe8c3fe3b760c23c19c2ffa12e6fcb0c452fac97a8c1c7","pub":"02b880cd243da4622fd4084c0779a34c117cac73c193de6691cfb9783c23a13751","addr":"5157180c3b43d1127614fcee3c772b45f438a73c"},{"mnemonic":"modify puppy army pull trust icon suit submit fade game near machine","master":"5b3dd4912f293341f8e62b55d25a7f01debaafa1a8ae6d7d9e34afce8d534c7b","seed":"e73259b5532099bfdcf2196ba80baa86886343ed2a5a7dc081128e5d94232b52d3914a8fb9ee17fcbbdd0d2199b2febc3ee1fb430729a376f8106439d45718e5","priv":"5a502a6484aa0eb1f7d963d950574d1cc348f3f64b1064f0d6ae8526293b9f89","pub":"0279d6b5231ca7729c450b055d51f350ef370544b83d10e80501ff5063961ec425","addr":"54a6fb03ba980c6efeb0e4e6eefa8d5c06f68dcb"},{"mnemonic":"beauty fetch title weird machine section remove better kind unfold candy risk","master":"b9c854671b0922cd1c27f876e2bb2748e74d7e5c56f71b7bb24e0f121c312c51","seed":"223ad6102e7f9e49ae732fd584519ebb6c139fd5cba630b78d2e5872be280c5c68eb6ed3b5b09fedfde8cbf6dcc1624f3380ae464f1d30c2abcd8d8ff5157e32","priv":"9c0c7cb874257ee95038077d5fb1be111685c5a54c7eae74da353fc2d476766f","pub":"02be94467d1120e497f16254d1840c431ef8254eb6a0b1f8b6e63b9f482ae37981","addr":"1c3965d6dce5a86ed7e176420079ebd2f475871d"},{"mnemonic":"broccoli ring road spell bubble slush cable column boil wisdom glide again","master":"dfe7a6221acf8d8f8b29530792efa9ac33b94e352f64ed3244062651596b0b1b","seed":"518f8503f16e8e5810486d1ea5b70951fe6f17427cec5e7f68584d7c7f101d6670ca755f81501146f3969f1869faf5efc6aa639ce47cf1d337367ff2d5336358","priv":"b7c6e7af8ffb55f9282d13c51736270a9b488191d8e9a4999a2735d5dc27ae5b","pub":"02ad6e0ed23179b9a12019db3afda6555fb3e088f2cb91eaf53db823bb284e7681","addr":"cc65b77303a5d3d42de2ef404a05ffd8b0fb73aa"},{"mnemonic":"settle jar tag talent bridge onion jazz vote certain job high lounge","master":"fd3df0c73c84b19831fb4fef9b6e8dc4eec01c845c38276f369ae73805cd5bbc","seed":"6944f80e097b237b7eb501d2d6d735c644c7d9fe0de4a1d12665b27a1567d3d619d41a9a469622c57f2e7998af4f8784dc1bf30b715b6c867d61902103ffefff","priv":"93d91fee61fa1f6704da23dbd1ee4b5513399d1d7ad52c3a632d5e3ad5884895","pub":"0331248b1a2b3ac8919c5654220fd21a10d2f700b2bca6a16d94ab25cbf60631e6","addr":"8219e185c9dc66aa8ecef927a93e884494251762"},{"mnemonic":"say unhappy visit follow rocket bind capable lunar age erupt depart leisure","master":"bb776f6f57d90a587b76509d6788c1afc54b7a35a06ace60d7d627605e462d9f","seed":"e20ebb6b86a37149a20e0f07a637de61af6d37f76d9bd84c210c8c06f92d23e167acd0098be525e943e2c4e7378903f8b4572190ba1c6b37ed40fc023b355e93","priv":"0bb90cdd4f552b15991e6e9c1546d78b4445af65e60d6cc850b7d4f64a6406d5","pub":"0342b5a2ce673cbf8610f049dba20a0c7d92091b7df857951aca402e56acda8a8b","addr":"1af59207b0004314be04dd208cc2154e06476ed4"},{"mnemonic":"next broccoli cluster someone just you crouch monitor crack tribe slim cloth","master":"87d2484fa935339252c8b0db3b4604f42e12a48ea00d22abccfc8a4ae9afd60d","seed":"abe12329f69d107732e3a3eb4ca9bd693b1ad465a042530031d0cf79e4d32a42185677250418809d0cf7fe7e47e0deeb76c321a8b82060666d36f8a79d68d2b1","priv":"9fe6b21141e8035d253dd8fb9e6009ef14f1680f58629dc880b50fec649bc00e","pub":"03af8824d512a243566015275cc2a8af24fae7acc538fc292806c2c95688797e9b","addr":"02f4e6e52415b7e25431c0af1f43f7dce05b08b7"},{"mnemonic":"scorpion artist craft enough whale maze copy ring search sugar rhythm few","master":"8700b2c3bc7b441f6600850cdfa90caa3fa8e4aa6c3091d9850c42644187c053","seed":"cecd5fef8caf60fdbab007cdcfa920867c0057d0c65b55ee569577427914e0e3227ab8cea26f50c1596fcf79a88a521721257f43dd84ef1d81e2ae4a8b73ebae","priv":"8dbc85572bf9b0f91c5e4f1516f3056c6a3608fd78e6b37e7dad0a0a5e4f6c2b","pub":"02947910def2d55c81ae2fc03727c62440713b0cfbaa854f3c7e9cc5b8f245a2fa","addr":"a77f593385c2e978d99f0a6a3d06e427f01f1c7a"},{"mnemonic":"improve help region hamster then raven eyebrow account sleep cliff copy pull","master":"e479782ba4b1b4f605fe2e892c6449a91a03aa8438668e22df211275a5644c92","seed":"bd788f3b47b98d37521fb5d51e35d42489fb83e21dc4f0fcf55dde6c2e1b561b63ef22f51cff2c190ef8b18cfab7af33df8e83d14d066c6b114404ba809869c5","priv":"a2deecc348654217762f8e5a422b3ab8aeb07738a75c49de9a1aea6ec767f4a6","pub":"025ee0f9bd4bfb85e42f918e91294fd9023831385e73ed06aabbbb7234d1707def","addr":"b80dcc0683ebdefb2a30398b0ba1478de6742050"},{"mnemonic":"bronze fix prison velvet sponsor woman vessel crunch forward sunset similar wedding","master":"608887c856e38875ce02b2bb7e6899698cd395db9ca1e19ebdaa0dea5dbdc1c9","seed":"66a0fc313ac72cc89a85bd4144b69061ca1e65f7d1968824f0cffe10b10380278428af5b6a114d6ce2a88e3626dfae38133acb02096d0b6ba7b9761a8c4a0eac","priv":"47de7838c74b2b1ceb138fdf96d455deaf8fc2550246a479ff98aa706b1d0211","pub":"02202887af1c72f72abe2754b6022a163b2abe5ee9f288126dfd1756067b03b5d7","addr":"8756dc9521ce9ad5e22d2612657e552ced185071"},{"mnemonic":"fame answer typical zoo key rail state chest snap stove urge collect","master":"377482e11aac4f724c3a1f94c8abef488f1807e3ad1a92821d7dc3f6377a2c3d","seed":"ffb372372dce3d525e923ba290828f0b5d12f65b241d5e3c36d431c1e1b3ef737f666abffc9d7e60aac3645a8f385262f2295b05c42a4c2f8bcbc3aba9edf5a7","priv":"bad40853765d64cdc729c94aa5e114fae54ee014517dc5231be8321bf7d93266","pub":"025d64a940c5b4dabfe233b552e43239b69dba164eac66b48a36f4e06915539575","addr":"f67fd1e04384628a47a01b88c399b30df8e5b226"},{"mnemonic":"expand machine nice damage roast slam example resemble tonight enforce salon benefit","master":"2e9614bf212cb179d91a224f1cc36fd4dc0a5be13eb5ef3ec614cd3f5db5be18","seed":"97c59f53a69f280fcf28110dd05e7510fad1d00e26d30847bd1dda99324ea2efa8550e5504f2f2648fef7f9c03ec58b2666b94269b3b5bbef1577f17af22ad1a","priv":"bf9962586c0636a20519a0eac17870ed0fd09862d4ebb563b3f445a179873551","pub":"027eb40d841c1028b75f21d593300ef57c3defdc258d17511ab086988240619261","addr":"d107cca0ed49d72efdde4b9369855d188f37a65c"},{"mnemonic":"debris scatter erosion dad quantum almost zone off bless tuition garden phone","master":"706940b567f1ab966a5f2db1d3e5eb832cb827a89c5bf2d17e9f3628ac6f88ba","seed":"b5caeb5e19c5c3e1e7a1074c3e4f366431d57f5ee5208aad341020fd33b2be38c2a228201949b6812513b28523cd82594a2db67177bbee6472bc5528a0fc01eb","priv":"671bab5dd3060bc813898cbc63828aacf50819c35981793fa9dcbe26c3427dc4","pub":"0283689f70b17659b51e2a5f345ae95e3a23fcc69941a5a842e992167dd958ab7f","addr":"aabde1e66f358e648444fa2a10be7404f1d6094d"},{"mnemonic":"expand fence want silk inhale web seed slide pitch fever online puppy","master":"2f3f69643bf40d05ff4be223ad7f05f0942166b629b6bddfe022df650b52a235","seed":"025608f609aa5f6662cea4323e4a4fdb4115f68d8cfd903886fbd561bf9bea74ec1e0c5d871ba46a1821efc769b2447c6b8d8f242fa0dfec8546c814f97cd120","priv":"26b51c99c8bbd84af26776dfb9a244114a66929f24fb782f195267fa7b35bf89","pub":"028d38aafd513f554facaf66eca4907f01ca8c48807898b6e142b609e93c3521cd","addr":"f5d92901099f9516401d963a0693f4d173cc2138"},{"mnemonic":"pudding mean volcano leader grain general because hockey mask solve frozen canoe","master":"a7a2aa088f904b0c44d1a307a17be86554cd9862f47b08f58205a7f73f93a011","seed":"d4e9852e81f9162b8fd6d1ce152e96a52b70d59289cbb8382cdb7bcbea5e5c5b6649aa6a2d138343092886474816c8e9c9f8c198d77986d2d6f7e1476f1499a1","priv":"31535d53290a02faa05f04894d6381b6edddcb7a374b19f8940d4581f9582cbd","pub":"03f89337767bf64bdbbca6a53184c126fca28f7613f2668a77119f62124f52a0b4","addr":"bd54d3175097fc470fefd66c7e5e63e7aa28cb70"},{"mnemonic":"make protect hungry coach tail female capable swamp alley one nerve nothing","master":"f171811d3c1b278279379244f480bdc165f5b645521749b2bf7b5bccb91e64a6","seed":"f8ebb80407da43b794542cca52f76b053175290dbc00751dfcb4539101bcf34369f76f686642c46728aef4b93f91f5ed2896b2a102aa3cd45e54591fcd0dd919","priv":"ea4ce4340c0eb740a33fec8198c22ec0064d72dcd74f85405f6d7efd1b1d0538","pub":"03e06202e127c7996f8367bcd0b28f779207cf222ec3d5d4190abae78fee5ed57f","addr":"54ef6f20caf4216e10a99ed446c842e3e9d90ed8"},{"mnemonic":"royal behave retreat force stable law cabbage home episode valid similar amused","master":"b2d8324833e37ae4f1a9a70dc33d070223b6313fe60e31a0c240b03f644ab78d","seed":"2448c418181d981fa42c83da24dab9d73b6a89dc0f86f624992ec9a982ab04e84989ff541364f4a289969d458364eabb08d51249c55ea16c29c6b65b5b95d7c7","priv":"473b6c4e1192b52fda7e64be4c34ee0197604c0e4c918d2a61e98f35fbd3f9e0","pub":"023bdc3332835493ed0258dad839d90c8503cd7a2a7097893170c6498dfaa2d534","addr":"d77a39d95f6204755a78c3b996c7bd84d1dc6a42"},{"mnemonic":"major dentist hurt task dinner exhibit soccer disease bullet knife hair nest","master":"9202dd767a3b88e0162803d54fb1e251ae14be8337829efc06770dc83aefa0b6","seed":"4c2d56edca18105e69c59b683d76034ad69006170a595c5648c84237ef0568862d5f95873334769be9937b83c5c96881569f232dec873e3947bdeca6831b1952","priv":"4db6777136a67a8279bfca36d0531a93bdc9e6eac4496fc20acbf78268e35d69","pub":"02d35a568677e4be8cfa051c190e54af69f8124daf5f39a288bd7a0baf1b1b4b13","addr":"6b8223d76a499b98d5bed2b146768569eaa7ab64"},{"mnemonic":"ketchup urban occur rain cheese bean need august autumn clarify kite chuckle","master":"8aa0b8b32ccae13b15ea9c808fe3b1185026c52a9f3b39546b355aab66d7f9a3","seed":"c910c33e6e009667a3d64ef0d10ce9738ff80aef32326d27b8f82bee0abf523e2940fc9ac6dcc27d10ed602fb60a99409688142fc18a9fab36fdadb6d76f1693","priv":"4541e2bafa8a4b3fcd1c9b49f646b3950292e0e18c2f1accda6d53197aca0d02","pub":"0336ad51e9c8d24af44291449aa86d4cb798181b2bdc9a2a6ae6a7c857a5d72c4e","addr":"9a37a2e3c1b6763a580a3b2aea95cf237bddbc68"},{"mnemonic":"shift anger harbor behave icon boring zebra sketch kid human nature learn","master":"139db45e5f8cbe86f23952b1558df3924dc55126119abcab216158285a645f61","seed":"1cea92117d8c90c554ae3ff517be704caa5c0d16369f68eb061154d59fb42ab9a6ea7ddcc62325df2c63ba0349e73a50c291edc1ceb0184012b71f2f5892a4c2","priv":"638fc2fa201498e1d76356acb3f4c5b42984c2c4b8619b0138426183daffb725","pub":"02272782c09fd51800d483c408ade4509c5cb83573293b873663a8492c1bf6711a","addr":"020ca2c2be203a95c0f7eade606d9c27bb572835"},{"mnemonic":"chat grain wisdom yellow rough swap notice range collect maple actor genre","master":"57363529ed9e9ae59ed408390581f344a7b974d130b23fc1da952983604e2cc1","seed":"d4b51a786cceb10f907941092f90be911c3ae2eca9924dade05aec85218baadc6b8137e86f4723b7500189529bc1da0b4cc95d1a8553cada6beceb71b12acaae","priv":"6245ecb65a10ed313dfc02843ac8e848a17aa37f6c3aa64007ff0b54b591e37f","pub":"032c33f1bc81371f8e599fa64736879a9fab286469e271d2fcff6f97b1b4829e46","addr":"4e076a5900d2016f08628257ae798a102c007e94"},{"mnemonic":"feed good spring pulse avocado smile surface conduct copper chaos dizzy describe","master":"003488e5bb876fb831b5ced5126e5c85ff6f98203dce52820acb139e31859ad0","seed":"e71271c88e445005f5bab28a4ed6c9d46f41adc6b646870c4097252e6f01d51ff9720d2960c61b9839cf29b559232b086ee5694252bd1fd73d601a27d78f8787","priv":"7702987362194e4b70c66b9d0d330a383e2710cdf863e5bb472c31815b6d9fef","pub":"02b790b42543e16b9c30a23baa39da3ed1d48402e51920187eaaa6796767ebe49b","addr":"778d3554fd4323ae321b6fdd0d907d28a4f0a886"},{"mnemonic":"brick wool tired another milk slight owner year electric later because response","master":"473c6a0dade946ed832babc01cac18b33ed7ea2303a362dfe6671202448a1f2c","seed":"ef22617d9f1ed62a89eb986d9addcb33c98d3da5e205c4cdca8c9b99f6267e0122d86be0b5f60c46d8c9f4c569c3ebade2376b04901bf8bfee5de83f6f818a21","priv":"7df1f72c7a5cf60268e760c29246e6e43f8168ab56b9c83d23df9923a3e51380","pub":"03de70b3833b9be36c88018dc6296feed7ae17d995af5b6942a67bd39689129498","addr":"27f48112f2be720f42706681bf2e97de964a009b"},{"mnemonic":"poem rifle october destroy castle scrub yellow brown soon this share radio","master":"bd39615405d3b2c25d023095975e07405228878f004b48be0a32fba278394020","seed":"578f2a69d418ed6bbe4a7639c6094396821dff23d1c26ef1a5452e91164e142fdcea44d63ec2eaa8d491f7b3757147f371ddb624fe10d6f7bae502e062671100","priv":"7cb45a918ecb28afef642f002cb9627381e1986ad90cbbe54aebb118724f1417","pub":"02ad197d4780b28d57ca50799d59fcc6956b2bdb24c8e2c2a221d5cf65007d2536","addr":"09c81b6b7dc3d57d239ca18573720e063144916a"},{"mnemonic":"hedgehog october thunder frown game aware reflect art favorite elite urge pluck","master":"0f2082a1d92a2d2ebdd605f33eb470568c7d82d0edf73e2be8a766d060dd61ad","seed":"9ecc3fc4516a37cafa09405c306bf19f53b085088a1d1cb0c54bacab3f21d4edf4adcabfa616137753a427c2269d3b3334a952cc5f4531980034433e4bbeeb9b","priv":"d3e3e9ee84d32091f08d7fed384fe3ec0465ec460f90a2749c69883dde03ec65","pub":"03b5af12849876b7c9c0e64833ea79c5b58f4450e4d67a99a90b3c9ab4ec3c8155","addr":"c5a46d31f9e363e348dc4ce803d44a676ce811de"},{"mnemonic":"goddess wear mail poverty exist pole advice blouse famous inform wrist pelican","master":"8c09d67d7e8691a66d2271093d7f74f5eb37729df23bf98525874b6d600158b5","seed":"093b6596b4986195e484e2d8977c8bdc20529c58527d9181c4d4e993495bba922fad305d8d4f13d9b5ba20c5e375dde147fda5aea8accf634d522e488d163c88","priv":"b028bdd6652a16380c61134fcbb095d372e63a117421fbedc46754266edaf916","pub":"03bb1f45e672d983a8856631fa8193422820747e3f8706e55d761d94bf091d7d6b","addr":"528f7468425b08f67e90058778cfb1efc46182ee"},{"mnemonic":"increase debate symbol swap raccoon crucial noble benefit kingdom prosper proud medal","master":"eb8bfa1409b9b28fb7c826f884d7eebaa6203e7bccecbe133e55df59db2ab8f7","seed":"5521921a26a36b06e62a681e2accb9a1577b6342085e9c9498f5693ce6b79fae98b9addd2da01df263445b5e45d2b4db45621517f96b86cd43b0ed00f7797fe6","priv":"e1927e2b0769daec6f1e7af012f1a14d82d52b89bc83a2fb9d007be1a51be4bc","pub":"02d41fc73e6624af22813b072d72a1d31fd628a66ae61e5d191c374be419c4a586","addr":"cc942c7413a8ea0db73c6cd3e2bd4c5e46ceb395"},{"mnemonic":"upset dutch damage thing maple ramp marine leave audit ugly walnut cricket","master":"012beaf52cd1e042c96753770315d25444e18cc63446a4207d57c2287d6ae028","seed":"dccb359dc9c2c2000e0fc23e100ad2ffcaaa0ea9bc1cf036b14c9c1f1542a4f9747097994ec5dc4071ea6863c01b2a5bfd6f747faea05dae4c3fa03eb2716b14","priv":"391710f6f67f54bb50abc86e349b889d0163a4c91dd1727dd3a6ae0912defc72","pub":"02bdbcdee705f81a4764a8e62de4bf6cd26f748be843fa36acad975980c5ab1b58","addr":"888ac8af30c1372d6c243363f6a8d97d3874eb31"},{"mnemonic":"truck stairs excite range van electric alarm sing provide mesh jazz cloth","master":"ef39accf9d3261de50dc985194a30b1cea9a861e2e48bcb47b8ba4542f855259","seed":"088e1bc0f701ada0c35c77f0d17ac9cdc3fee9747410407a1748b2c7e72bb37f2a9382e1108bcbaac1fa2db5aba2bf34574f47fe46450aaffa7712e5fefdd40b","priv":"e2e2d2973b52c1da6098e31018dd238b02ecc1d22236e631ff9d3009572ab1e7","pub":"03bd54aaf28542c6d155ebd24c032dde7341005e69a5ef67c3de5138b546d9f462","addr":"246b883c299597436993fcc8b22d9154db9d8f1b"},{"mnemonic":"admit penalty clarify isolate decrease draw virtual rhythm trim brief vocal box","master":"4df1d8bb85983df8abb7af56086dd76becdde81861462889c5a0809a470125cd","seed":"4340047ec19d4f318596cbe510ec11f233193b72214487cf3e8dd90c11f1466004810ba433261962b9c412b22c98655b06421b3bfe73ecfb1bd95aae30142cef","priv":"965f07d8304bab4719f071d1e3b656165a70eb31fb57d5cbc27e03780416d304","pub":"02e3a67f5d360f10b1786406cd2f1dab2abbf606fa014502ac9a7bb56616597776","addr":"90c64758c772184848b10adb3f841f14c86096da"},{"mnemonic":"citizen fire fetch luxury tumble analyst pitch van sketch measure effort danger","master":"e3469c68ff7e9f4e68af468ae8be59df246ae039ab8ecbfafc9677d6fa0b3d5e","seed":"bcd37194bce09d9704926235b5c83323ca7a71ca1b3b257c5436267a1e14b7b37fb44ad7fae1b818189240e9006cbd920b36aeb204ac00f98faf9e1b1c2b7034","priv":"d3f4ebbfa161b543e250ef0b52c027e49548d5a36a8bcbd8cecfddf0f1ecf92d","pub":"038f2c2418d2a68827be4807f06bc9c59ca291b34ee5284e860abdeff90197d40a","addr":"a44c929bb81a0dffc76e8659a44f85873578c005"},{"mnemonic":"claw stage toy keep crisp memory donor surround bullet ball innocent faint","master":"1025d24a465ea26b933c44575b283057daa066d0f5f0e12c9411ebaaec29d26d","seed":"effa6fca939b041aeb89550f138159090189a0ab3c96fb9151bd3ef69d29b457946695331804e437353d134f0d069b28092f122f35e74eda8a2d643c3d1a0f31","priv":"a81c4bc682ef7609d7ea9bd370703eef25006557166b9e04e589083bd7cd65c9","pub":"03b4d5e3abb4a6eff0409b20d8a1a88088e591a6ac3e6e25fb66f172303f55e590","addr":"09e4b6c1a32ed0e0b671e0f241708806a46fcd71"},{"mnemonic":"rigid neither track gesture effort venue vital bike spend unlock special swallow","master":"33fb6294ade198c457bb6d318b2eae4d2757977af36b988e042f1c3bb42afb7b","seed":"58b191573da33c6a4d94b8589fb32f8c5af326f5f40ced92973c352295e71d7a07251c8b42355b0360fe3ee2cc42b3217fedb914ebc61faae8a0f8cfe579fa98","priv":"db272ba1dc7e8aef500e29a4acf750dcc6fd92e4ee2f2e4235e7f82034a1857a","pub":"039d506e2c16bffda4127fc073a6e1b43b2c0ec68cd6d86bcffe0f0c4663b5033d","addr":"5485fe5a806040bf059c1e0d90822b49d14a51f2"},{"mnemonic":"sun ankle door drift sustain task home retreat light say wash pretty","master":"b0a3d174b40c1f2a723e3a62f878c1d4d19673c632a19fbea460d4d0c35d14a1","seed":"63e84de6c5f71a4b9dd5fe8998f00d0f8d0f2bf6da159d82bc8fe30475d0e909a939d7498936ac183e8220acdf104aa5dd0f721e65eb06e99baa27e81314a2b2","priv":"7e2d6c88823a8effdb5266c8fe605968ce231150169e0174e140643780bbbfa8","pub":"0280cf1699ed3cd91a57b8520c1173c8e8ff036cf759d4e076df031115c67e62f7","addr":"c31630d1643d32f652d89791c5de3a4b671773a8"},{"mnemonic":"ball symptom nephew dwarf mango crowd radio shift degree envelope science job","master":"449cdf41d10e6dc749aa52839a9c23a74c41cc7be85bd76f7ef0ea8347a76db1","seed":"303c978ed8b692e5e334bd1dfd0ece8615af24457129e7127e2ddc69f783628cc48d0d31ab522ffb6e70761dafb755f5878b45579911d52157c37c1b14b900f5","priv":"f6d3c4eaf86ce6c5c8d640edd4a67ff7dc852b6fcf36918f2b9e36df710b2049","pub":"03b3e239dc04042dc6c83a8ee1973917cacbe375786c73aae74a6b46cddba54773","addr":"f0eabf6d01285343afba4b7005268ed3af052d90"},{"mnemonic":"cactus trend empower board street stick animal replace media unveil recall proud","master":"17b6f0a996810ab534ac366a8890f7618f372ce0168b00655740f9698cb8595e","seed":"6ecace1a5b927d3058a08f1a59bb8943d214ce5e48e3627be8995814640782de30243f5a552e5600a3e1c62b3a46edb558434ac56bd105e4fe23aef8a1c0e4f5","priv":"69bbc1e6bf17262180141a0b00e6c410c3ae5b10b69b20d6321aa3893250cd6b","pub":"03bdb7edf4aa8f5e6bcc5bfd6a898671b0fd687bdfd9f8101f4ca840a183ffb226","addr":"c5fbfa7d4e0356d88cbb5e5bf47a67e877c1b1a6"},{"mnemonic":"source note bundle laptop pistol business only dust bright govern illegal melt","master":"9e7f939a19be0a48a3d9a740d8082b968fbd41065b1f5d425cd20d73d327097a","seed":"22b6512400907bd050684ea2ef220c4bcfd35d59de2c4c5dc3527436c417b68cec186640ea1be40dd00ff27b13884cfe7146c84ee3d568b8f74272f0edd91574","priv":"3f378db3f2004722591ed742f0d802e6c4eb51f357c1d77180a777d083b2ce35","pub":"034c05a98ebddfc54812ccfb797a99f3cc09e525759b7f40746513d58ce8577177","addr":"d920c5b1bd40b6a0c3835e5d32a8c8d5897a18ee"},{"mnemonic":"pride mobile flock dash second emerge seminar theme lift motor pave grant","master":"786638e9248b3b0ed4196533a1a437e1db7c2a83908c71823e9a8cf720b71975","seed":"59bf3e8f03faf407d8427e9b53093cb3708192de0c979c2e0a572a905af89d5ac43c2d1c2480cad58c63e3dcab5b5679a4bc12a4341cc618836d15f27c2ca623","priv":"f7ca55ff74a0f55f08cd8efc515ecc69d9cc6bf2ca389a3116f906d641de1f2b","pub":"03f538159091c45fadcfe4ada5d2a1a3827206bb4fcb756b9573ddd381b39621fc","addr":"14a320df092aafa1fd0a5207b6408daf532072c5"},{"mnemonic":"obvious man chaos alarm symbol novel accident label engine noodle inject empty","master":"df206751043497e26c74fde7e068376bdc0771e3e06a1e8bf17209bb9e1880b5","seed":"2178b8972916ccef4040e2c50cc9dc039a6ef7f799f2287d8d16aae3edb6ec0a20bcc4798299d2569cf6183d7aedcb426dbfca1971aaa31dc4c202f40c906a55","priv":"ab864f86be6e1970df2fa336835986e60fb7040a2edf05a196eed2ea9ff42627","pub":"02c8db2bfc3c7377ba3ec38f9aa7bb1be7d70ed6b15d76d3d5980f983552ef6fdb","addr":"c595c4572aa4b833719c935db03afefc56c0edc2"},{"mnemonic":"client increase remember size asthma source evil venture column truly risk clerk","master":"a0f072fd237c6f30dfa920940d04657e19ebe30e3fee5b0ad8e63cfbb6256d86","seed":"0ecdd247615ecba50ea404632b4f8e2a6babe067cf7d395b038935bcab013f0581c69f2d07ad330cb6c7660feafe8b21af062b474dba193f1121a65f83b71b99","priv":"4b54d2f02c43241d7a45efacbd48616f6293629fc0b539487865dbef626c6789","pub":"0336182aab2751a5399b14e0ac2a856143cc679405fa55141606ec3b2a09c3b1dc","addr":"48d6d2441e609507ca554f8f79e4340f257565b6"},{"mnemonic":"latin scrub oval capable drink common hundred ghost candy avocado stool dial","master":"3c8762364ca16a70f174584f1f276df1c432e0b315e08cffb0d5874760e8c587","seed":"40991c77f0fe52213ce2ccf4844ee6587b3595aee4e79f34cb00ccd0813f78f0955ab8e40a5f369522f7ae3ba0290db31fa1b224baa6ec5a91b57da8ad2b479c","priv":"5242eb4e71fc9715ce4ebf1ce08fd81d362fec9dad2be045ee0d6687e1662df3","pub":"02344bbc8ab1313883fee563a175cf98ba192e8570963fb7c99bd0dbf6368fb656","addr":"3db9be587f22ebc28ae33b4cfa2c86124f450440"},{"mnemonic":"envelope van become minimum electric inflict denial thrive congress visa jelly play","master":"e94c4ca894e31aa091dfb2ef9d7733fbc67f1dd45e5db389a037816e4ae9ebef","seed":"01a5a19c5f75ec7ebc2cf0d96b7665c4c79efa0cd0b7dd5e21c2cf8954f5dc5b1d23daae831a6e18e5157c200a603fb2ffc87a068d1dbfae1d4443eee76a1f53","priv":"7ed896005729b7de5c6c56a19d37f5352ad6329e948c256f11eeefbe8c0c7dd3","pub":"02025c5b38b96fa00b506cb0360cadcfade6aebc6eddddb71dd6efad382b0f6b3f","addr":"1b7ef9f1184a0da787b1231a0f44eaf4035c3ab7"},{"mnemonic":"grocery embody emotion wisdom picnic modify opera lounge impose junk scare ocean","master":"8091cf08fd5f50de4ef91fbd4b9eaaafe8f1c17624fec94cd47de656ce0444ab","seed":"ced20dfaf3a902a7b71ae459781e5013d215567a617a2300b49dac4d3473e624885ba0ca8df6f13c91dfaa9829aaf06c4ffa9ea22f6f17826a1629a597519507","priv":"f0ace0c797c7f3a93bf1f9ae64dae516fad77d18b11c0e32b5d0781d7a231f02","pub":"023c38bcace9489242f81a74168475ec29531c58523f476bd068195d18044f80ce","addr":"859850c7548250084438b5829b4255ebf5fdbe6f"},{"mnemonic":"oil inch eight notice okay gravity dynamic trend neglect bag earth predict","master":"b235b5a4e01f0e64d68b063f09a878c8b0785b84c5106431f4bf9250874e9d38","seed":"96096619deaf5792701545255d539f120ebc2ab8c23ee72de058874b6413e51774b7c2b61be1b1197784fb63fa7e509374449d4c812e7c8f8bccc711c73ba703","priv":"7d05f98b2cfedcb506c68d426b298b3450445a1ac89a3407f4ccef1ddff8def2","pub":"02274745f11a0de371600f1ab8b5ddfab91372f044ceda14c968b7e5bd953dad37","addr":"098fced832e9cc1c962630fdd2dbfe262728f018"},{"mnemonic":"oyster ceiling cupboard quit today neutral repair genius pretty gospel dress rent","master":"e669becb784c8ef38698f778cd27cf0b55ebebb5828531b65330d51ea2b1acc4","seed":"af8030276cfdf70d129e66467a09321eccd9505f662865a4776e1f5a05ba1ff6614b37b54583333e3ce931c9d44378f636efddf5189284f5fa566d8db01801b8","priv":"c0ddfbada817464834555e46ed3eb3d50c1023454f42826463e71754b9e6051d","pub":"039f5c467338b3cf8ac16e6677c8242a67caf89f1201f0f22d99ca1e7beb9f1a32","addr":"53ff0701507c25f97dd1e6721b218184dea2e3d7"},{"mnemonic":"utility angle dynamic fire canal current level trash chase praise witness mix","master":"54ef0de540f88777efd1f3c37929789620eff87bbf98e61f9b2e0783d75450cd","seed":"8701d5ac962b68ab8c34092b44210cb9c11c2332515815223537fcab99909b44a0394436074e60285c7b306917c1165a2f281bca911798b23832723abaf18971","priv":"bb5602644b1af5bfa019f2f81ed0d2475c1492661e55c8e65d8d5e94ddb33e52","pub":"0314f5e5d817f2235e3a6fdc0e86f231825165777c69314de63bd88738e7e7ab46","addr":"6d596a5fa6b1818895ee6fac51915a489da283a0"},{"mnemonic":"cabbage sauce filter identify potato coil bicycle river observe candy maid monster","master":"4e834379e58e480e0cde698f9f8e47b3b6e698b4c1325a995504980e43689706","seed":"a441b8fed73bf3bf06a27aaac9355a79d645f0c7d5d47ec216a8d42d6edf97e6a00dc48de9d9ad9d52279ef26f34990581caaba9d15342935ffe857c10456382","priv":"40e878ef025dc6424f2822e38c7a906b3bc39940e8db21262e6bb99ef3de98a2","pub":"030e41c103c49d2e54e5ba6e40b1dbf04245dca7da0738ce9048d0391da872365c","addr":"9d4e8dd66b5e16369be39000c11b03fd5054e0f8"},{"mnemonic":"method surge demand ginger pigeon chunk because wisdom stadium salad excite stool","master":"b8f4a0a87e42871e927b2d5775fd212dbf911351c525b92f5742ba15650aba63","seed":"3844f4bc75163d8dc39c53cdd0e9ff31182a87ad2d630286897b35b39a14afc5e5ecd3be988c9754ef31f14452290ff04c84faddfd195a3eaea076e48bde47c5","priv":"db0bbe779583c012d78f9b60d6648b72d699c2e6b5e9eb90d293852553649a91","pub":"02bb40395d5649363ec19874f2fdc122bddd8748234c1c1ccb37e38468c6e9da4b","addr":"bf52f59b2e4f01f23b32f502acddf96bda564682"},{"mnemonic":"stuff extra hair depth angry jar drastic jazz diet olympic choose legal","master":"5e09c2cd0aa6504c4a2e8bea31e0dcb7f0b82f040567b681271493e35ca910ec","seed":"ce48715916de04f9c4f9a84e4ca25900ca0292de3a7217a42497c0bab2253693ee8b5425c40ffb2700a65a772e98989a2adf4329a93596a4d6695f6c7f236e64","priv":"7f06d4f3cac1e4b2a7e0951a55f78ba85aa6e6b03872dbc0c930086b8e8e25c4","pub":"02b4ba9df766e58ae8a5164b4be48159901f421b8e8f396593b66dd3a715f268c6","addr":"fb2f7eb9e28187a7b68b02b7f55b5dd46fe9ff49"},{"mnemonic":"leader now arrow loan eternal prosper myself lift limit capital aim twist","master":"8a4e78bbca5c37b40feccb9bf053a24ffd6d0809fc2b89440d467bc903c03244","seed":"25f1e8641b6095446cb3d7f94bdd7d81d92d78ef808b18c48050985564543efcb99f28b94e2e935d31d973a848666b95bd183e05860bd0950cdf0ee8d7e04da7","priv":"a2fdc724702230d79b0c564c34fc4e68e8a10c336ca053278cb3be419313e07e","pub":"02e2206433e526fd4fff47b58ef262eb558e79870c0aad14290d40e912ecde8213","addr":"3389c22a794df27093c11dc80b6096dc3ed0d175"},{"mnemonic":"increase month viable teach spice pause safe mouse allow sound access grace","master":"919d9b6fd918d7f223acf91ea5abd831a1a3568d60fd2e43f0d97e000ec77f47","seed":"f4cec05a2bf6a00a7079213c03c36d765e49914166f497d6e38a522b1cb43fe24260008dbbad00a10d998f7963dc8dc09fd539570f157c9bcff8248987d38626","priv":"f145657458462f994a4e972cbd42ef4de683da47b5b6f95b14ea417b39e702ab","pub":"0289419eb27318299a51fce4f0e65827d0426d72543fa2f05d0c5f21bef86effbe","addr":"cbe298ebb714dd583e7c4d541ec9b38c56710226"},{"mnemonic":"move catch empty dilemma only online ginger rapid enough turtle flee retire","master":"39d365c85d0ae4f31811c665217b718bdb90a4f2d328587bdf430ff622d019e9","seed":"402b62437898f76f87f3e080c3f33f1c6b8ebbb848efd467ee4ae5d3303768c57a15fb1cb03a6befe486b0c02733c5c892ed9878ea7713cefc58b7a616d7b286","priv":"7e54e61877b8413d06251167b239c1a6213ed23e79c1ec8da7408e23928d47a7","pub":"03d25f230b5d12ba142046fa80c23e51198987254bf7f7f8a009b712783d9311aa","addr":"173f71a2ef94e964185c474eb310a363241c4621"},{"mnemonic":"audit energy setup mimic dilemma amateur evoke tornado machine artefact shed artwork","master":"40bd9cc381e632be6f25b822bb13bc7cb5c9697b09d7ec725aa21e13cd3eeff3","seed":"721de71ee0b84620bff8de317edf7c4ddadcc2dfbf19f3cbbbf61bf26157fa07c46119cd2f8387d67fb0cfbb98f62a3e711053a308496a0ccddb944ce517d90b","priv":"825587d79a33405a3c7cbb8a25e89cf1b3975de3763e1928e02c3f4d0cc8d44e","pub":"036ea297692c5bbd85ac06ca8ca238bad6db83d1acdd02fc012325a1369df4447d","addr":"5e45e1683f7c34754771340ecd629014297b72ba"},{"mnemonic":"vast noodle pumpkin sugar time iron screen begin among orphan glimpse deal","master":"cdd2cba6ca23c96a7967d3f3f5739009f2fca93bda0a36b85bf7a1cbe0d8af8b","seed":"6288319e4e2c7471be7088e9b50db78741c1da423892da1bfa289bbc62d4a014a6d9b7cce396cc3471531342a61d92345a3b043224dd271ba46cd716a0952af4","priv":"1a746edca60363f3bb4118e316ac549be3161be28c4151c9fb9cd63728abede8","pub":"03cfc321906acb176564624dbf1855f00188f563b14f07075b1d5c7e4dc25b4419","addr":"5007b4c128af77e8dfcdd85a925044438def1159"},{"mnemonic":"evidence element stereo crunch romance trigger ten ceiling cigar wire first frame","master":"9aa2f09eb1b6094ab52e39873444f04cc682e60305e9fd4f485af27d7c6e85b8","seed":"9adc22bf0cd328df0f54c6da7f5e43e9abb4e9a607aa02c312de24c12d9a18f38945da0188834e149aaa5798c8594fbaa9109d47363deb53e17553f2edfcdd2c","priv":"281e729635633787eb40b08d43d806a5e2ce178abe659b37c91c6c073e720448","pub":"039e0c68668af7289a7ab4c7f9b24347f10d38eca095e991207cd9ee55bf61f0b3","addr":"49b25bd31b9fed1ca7e2c32d663bd414d6c3705c"},{"mnemonic":"labor capable alpha robust suit trial media bottom pig hundred verb hotel","master":"b3e4d6c6bd059bc9548d33f6ce0aa6674160ce38bb231fe354950aab11651403","seed":"e1470e44481471f4c947976fdd4fc9119619571cbcc90d0d419f4a8c4e1102f84246da2c2fd0c02bccb34a23708cb6bfc25b23972c03fb6a70f5018ecc5dd2dd","priv":"9a9501487f7f9844ba521b3ef949b12b30046e927bbd8054c831434a4309131f","pub":"02b25d30e144102b7500d57f3c501093f4dc8708afa3ee2c9d772d5672802bb9fc","addr":"49bc8135a631475412f0b4bb0db7d437ef226243"},{"mnemonic":"resource pencil other subway knee small shield excite forget such annual opera","master":"955fe71377d76742d6bd94d49457e6cb768e57517ed010648edc058f65d6ccd5","seed":"28a7a3080633dd2485cd88b9c1ffe92889eda9d33be7fab5b8aae3448170282decf20587d613cf06f0d3a7da6acaeaf5c9918616b4d22f8f23bb6a17c67bbde8","priv":"ddc57bfd0d27c98a1d088272ab481407ba95f8556f5603245466f4f2d83c3168","pub":"03065ce8033103d6fb42bb382a59053797beb33214c9d16f2b4ec3634cddf857c3","addr":"b0ca9d5f91fa03b1350a40e4ffa84e99167e4115"},{"mnemonic":"dinner tone antique away vivid lesson frame floor rent field monkey race","master":"21cde220eeac2883dbddcc6927f73423af840e675eca3a6cc82bde4a5cfdfa39","seed":"16c220be97967c5fa8ff2176a9e0d748e0aad37c8ad32e590c5a35ba08247e2176369a3561c5eb0cc4ebc9a3d65bd132e31c2640968eea822ae76c6c34d17373","priv":"13366b2855dee63a394c4ba89378a35b75ee07853c78765dd1c5c8927e52d4a6","pub":"03cea336f71a793319bbb298bb3c546046e69b6abdec405302739345047cde8355","addr":"251a5f4b01da75091e938d782ab116e0e4ac37e0"},{"mnemonic":"peanut potato artist define merry brass nose brief dinosaur planet year blame","master":"87c46a1f19cc7d1e59887f445dab57aa835bf116db621e9df97c5f3090517e7a","seed":"f8b6aa2a59e9384933e0a88c76c5fa889ad82238ee7173a41a57638bbc82e51e7d89c97bf3cd2f6031e65edbeafdcad5760cc6d37a527eb0372b03281e7806ad","priv":"a7e43f8b98838fcc06ba6257cc64086fd1b6d0eef12eddf9910181bc6c0ff204","pub":"02db3f433577482b62d057404b61d9d10f25df66b0742c2a3471d2e80380355cda","addr":"571a2abcef5e4f690174e2d81d9ca035742e17af"},{"mnemonic":"orbit have attract dove horn liquid social maximum penalty slight mind mountain","master":"5da625838972cb1684ff4e45326b14bc1d73164f82527934fdf8b7a03b9891c2","seed":"abd2d4cdfc5b8330f58b7757efd4fece7854e461e22c71be5aadd735c144a954594fd8da84df6b8db3ea14c5db03a6952f093346ae94b6495a8635e72e4a38a1","priv":"cfb3afed34d7e53d459cad8623401f0d6071d77f70a96c75baa511179ca59cb3","pub":"02e9e07cdc8d57e321593919431bbb6c0761910d00e4a242ecd85d0b99e9ad3f36","addr":"78099b6cef2d14ad8f3ba7db73bdc9538e382464"},{"mnemonic":"squirrel motion glue best prevent fault goose evolve shoot decrease panic very","master":"2fc7364fc6537a38839ddc9dd41e0e58b2e972072e92ab8ec9fda67360f2a042","seed":"78718bcb53ba532316fc641cbe2027fdf4ea649563b36ae94a95415b5923397585b4d10b1026cfc8a00069cdc02c7ea8c1ebe04364bd68066195c748331104b4","priv":"7d9073ba21f72f91ca39d1f13c05108dc75b56d3b09bd08b7b8843137fba91b2","pub":"027827c957ea1c98f76a076bcb75ab8faf534dbed44beb234ebe9f60086fcee393","addr":"10440fcf67f5b2b6f4e81a0b6fe267941b437811"},{"mnemonic":"pudding tooth market kiss exhaust donor tattoo olympic uncle child bean nominee","master":"34f62b6ae3c01c03d64e0041bd50a9cf7027fbbc0b0fa7d13d08908422f72520","seed":"4f02768404f6da2b7654bef1e4d35a42386bcdbf167d09212194e20a93070030eb0a471945248a36a8d062e80130008cc16a001ecc3c05a27db0aab0f04c6411","priv":"1601556ec13ac16d4b38ee73080065756ef276473e7649c713ea1ce69367c087","pub":"03382cbb99d17b144dec0eaacaa33d1cd2041bd30cb658fb97ef2654e24addbaa4","addr":"e2bdf4c0101d49df4d8aa0782c4a1fc354fdbfaa"},{"mnemonic":"earn shock finish ritual segment post then note dizzy diesel jelly horn","master":"309b4a016a064d4bbbbc220c0fb0727114b0b83b600db73aeb4347a04ce52873","seed":"bee7d3de1274abc8fc05afc839de0b14166b86f1ea0a1f2a6b6484f40654aaa7cc4574a14996812974b905da6eed437576eb7f8fea704afdaca3b146b761f0b8","priv":"a269a409951e783c280a5d8afb0bc232f303618b4d83328ee1196cf86f2d8f04","pub":"03b79d6727f3d6a0c289f2efac4938caa94ee57a36a3ac70e3f8e5f85f7e4f52e3","addr":"8ed4fb10d7b8d66f4244e83d7e6cc89fc75460e3"},{"mnemonic":"venture bitter tongue learn whip palm race pioneer satoshi wait hub genre","master":"e01f7f5ad0a782b56a034b68230df72cc8440f6e4cad89ea0bb9b81a71b430bc","seed":"b6da5129dcad44188c654c9c50ea640543b66c0c98edb29099770eb6d89ff197f5e9fbb7725ada5b3b0191a9cea89ebd8f35698d5ffadcf3ec43f6b92795c1c3","priv":"e3ca3c8028c514ecacde54c73338ef5fc78e0ab05ed8260d4a70553c68390bfd","pub":"03913989f1771a015b6594b60de23017fb31b96a740507873cee53770684fdd5a6","addr":"db8e914a36120702031b4498a27d6bcb8c64da8b"},{"mnemonic":"opera wear actual virus pause topple leave video garden guard obey item","master":"8fa7f1c161b47e625e351c775c662eef0d5cf9d9c229a780ce0adee5fb045ccf","seed":"be4f43f613da6e02ae174310181afc71462ec108601eab58d369f452c4133d14bcbdd05462676d872b7aabae01e7e6e22ad38261ce70a2f107ff9f42ace4411e","priv":"506a98b80534c824f67233bd1840ea968886a57ab500fc0521da20fa4f24fce5","pub":"030a5a585b4db663ea11944e5be0bbb630b6b1f436989c8e7128784f7f59676370","addr":"5ad5c8981762b720bf74b376205f69a91c6f3cfb"},{"mnemonic":"captain tray course secret betray bag disagree boring umbrella liquid door memory","master":"b7974cd18de7e9e6abe2280e567fc51efaf3e80986c98901ae2ab7378eefa08c","seed":"3a3c2b0e7b237e37e7c92c12960ae5b8856a8a5795386d243c6d9eb7dae1b98170489c47b197a794e8f9ed0c323bbd722ca052f76d3cf1ac04db5f7ef6bf5b26","priv":"a13d741052c66e487ee376cd392096d9e56db28d64001cdd807427678b765016","pub":"02fac937135a8b0593c50d06a7b113c372d8c9d02a338673e3e07f267725536417","addr":"e5d9166b331f86253444f3198f707a495055b768"},{"mnemonic":"dizzy guard goddess trouble absorb pupil stove mirror nose couch diamond must","master":"d3bdf420266d0c5824a621cd631ba014a8ea614b85c628cf64bc3a77cd3be3da","seed":"485d06d18708ced0c344c4025d93cc194f7c63e2aaa1d19970a96db8dbd7e2f802d39d319338b0a92faffc2af408f69f1522481fbefdcbd3842ede957c663b0a","priv":"abebb4b15d2d9e3a3dac2afd4423d5da2b2260da49bc45d44d014e8d740ba064","pub":"02e39342b82a9b4bd73b165ea9b309e20b0cf9c8d5ee93756cf82ebad0b00e0cda","addr":"19f6fda807d1a0f99fb730923277d4f36601e2d5"},{"mnemonic":"rescue drink absorb brief unhappy rocket subject receive green echo marriage cactus","master":"a6ce8546f2cb2a62c573b3bb5b1e7437f70a44b7cddd7171a41d2c4c3dccd641","seed":"0605b45920c5894d2d351c091c7c31af1b6f0d77576f73716ac96dd7a22dddbf42155aa19bbc3c2cef3c757ff25c3e7998d0ca536b696a498c9a206bc53e8ee0","priv":"00a6e55ef1853ba31f2b7e76acc7e04649a1a2037a9bc33c74cf82261e956ceb","pub":"03de1a877576f6e77bc06a53e7b2c56afe7b58c460341b74c469e344d2b87f2e62","addr":"a4014c9bd6c662a6d4b20cbfc0524e125a5963a2"},{"mnemonic":"destroy naive mother audit tackle coral crater sponsor viable clump bomb bargain","master":"c0cc3cb63a702200dd06ba3355314b332385c3a0e1ba73bf428243278825a6e5","seed":"fdb9a430d0fce5ee93e6b0ec23506f65e76cae8be1f773605af71687d2f9fc14a9a1bbbb769a5c38f654398024159b48de392cc4a88e29030f4b7699a3ed6824","priv":"8b73cf6e42c216a7978f63a28abf839d0e2174cb10ac2abef6870c9a8b938462","pub":"033257c04174083656be1bee39ddf01b34aaceb538ee86c7df35a9ea4b3a3c282e","addr":"5ced7fca93a8e097cf58cffaf7c89141cc00697c"},{"mnemonic":"paddle image cash sadness barely sport employ slab keen riot solution switch","master":"be10364b52d5cdc0b8eb51215301e8468c82498f0d7b2de44013d382c0441e80","seed":"138194b9dbb5c35fc66755736c385e12ea8783c3208d85c58bc140a5edbbd709779d4b42a2c56b94d82b5edbb9de212f2eb315edeb20a5725f3c24a39ca50f51","priv":"06b0b15085f8af9cb90eb081a7b73d4f8b781467926c2dae68a0d300f2d62a71","pub":"0286afa72dc5ce3416e8996392d0cbd63a0f9b9d60701561d3596a1c9d5fa18499","addr":"bbda492cb736571a6bd62d8f5d8836b0e0c761c9"},{"mnemonic":"gossip choice orbit insane honey hobby split exchange uncle wash tower lyrics","master":"7b39b437bb8d0b66c3989df6debf35846dac9fb69d2f570c4738afe92a57d708","seed":"d0897a14b1958fa31a898e38fc95b6dbb2a9a5019175bf8e503149f9d1ee4958edce3f1f570c3e015b797b475f5eee882ce54f68c7f64e310571e0fc6296da62","priv":"816f5cd94acd51821291561d6aa30951d89221027418ca697aa2b621f733b2ac","pub":"03d4081dc8446919e4a949c323b4c8d6b76282325cc7f35c18791a57200577f082","addr":"fc5a9ef94fc8de5ba7407669ce04d8190864252f"},{"mnemonic":"ceiling shed aim oven emerge year sock achieve ask melt endless lecture","master":"ff1480b11529ec8240e79bd9e35275e1805a3e117a60f9b6b22f66715b4258e7","seed":"1aa288b6bac68936d8d2a89396f5be1659a12fc91a9d7edfbb45446de8bb39327044b6ed7451e820317882f162560fcbb134449e85d517a7f0eace2da2cec272","priv":"216833b820c607646ae504dfa7fe28b364741509047b89eeff48545fee07c11f","pub":"03b3c3ce98ff9d2340849c220a5127d8ebe2bfd320c9db41e94f57b4e067eccf0c","addr":"78e3043b376112452a22ce49f6647a0b1d20180d"},{"mnemonic":"deer defy door jungle sauce summer sea globe crane abstract minimum diet","master":"f7440871bbff95cea261708c1cd06220a5aadae4a86c00f53b6f510a50e8ad56","seed":"a1868d8a30b498e1d397838821bf762c5f448d3d8fb68bf12cb0e2e26cc69f95be698efb101e76ad6ab84447c0c2b2170fb2b201315f5e5023bed35490f43986","priv":"b64d5f61a5503b366e7296a5b060e42d5db420e4bb8c4d0248c07ac25d2a0b60","pub":"02f4e32b1b8f2ed1b75ea26def62a6e69c7cce521788bdc182663ccabe4c1da4e1","addr":"32a90701856a1d942f58f41f6cbad21a64494658"},{"mnemonic":"position course virtual distance fashion oval slice round rely key spawn shy","master":"255409af8fb802395b9433c062310fda250cf8f9df7d79bd16381a7ec7b4d27d","seed":"1dcf6512b003b07fc299098ad2b8d4ab3eb1be11cb8949636ff2dd0baa0081ba78a9fc117ac65666c0854387ce0adbb903b482b85a20b9e591f0ff156a59d30c","priv":"a9157f3dc6ce3889c4d8dd4d2434f0e080090e4a0c0c75cf58bc03b41ea507a8","pub":"021b68e6fc74dbc45d326f9d2c7efe9c718e7c3c1a084e92c1f384c273b2d41513","addr":"21101638d066b561f8c43f6e9061f3959e3f89ef"},{"mnemonic":"model absorb cart athlete helmet next hen indoor involve ladder engine tone","master":"4221074ff1f662276f167017a5d43611b1d6e666c0c5592a35c81d2f5389c93f","seed":"dc9672d8e648fb4da6a5de519d08fb677c0d583a988701f2ac57e1fff273c3c832d31c036fa36d33b029fe0e92e8bbae350c6b96eaec463588f1ee04209add53","priv":"c4662a26101f0dd36e56ab0528a3861547015022b9e8a30ffde845d6207ae8c8","pub":"0285c5ad35fd9063e8cea4d034628244e790261977eb0225d4da90c5a2d11ac25c","addr":"8fc4bfc728a5e5fe2423b8c380aed1f2fcf4d2c4"},{"mnemonic":"armor happy become inner fossil exhaust upon under offer sheriff coach huge","master":"154c74bbf5601f7fd35c183e77ba32c03eadb2fea62563d2221199cc694a5fe2","seed":"db7910b6fb6f406f146f857b5c116033356cda61099165a7b1f782b2201878f9a4104efa15c2bad266db1802f9d15719fdb9953eaf3e245f0aaf9f5b0ff8d296","priv":"ee1d3af46fafe868bc1a89394c068dfe05cfcf7578c10bd57750511276e829db","pub":"03db053e44816be4562be9df13d8ee1853c1336aff0d13cc516b0681521d96a9af","addr":"fa65a0099684906c758eecf10f7a2b6dda7c5767"},{"mnemonic":"long output ketchup question hurt drama bamboo globe manual chest luxury abuse","master":"b180100cbc124ed4a9812ab4ff3c632bd7df77209598d4b26af9d31fdb8bbc28","seed":"61b7b436746323085cda66fb4c0e21079e849bc4d2bcc67cbcfacc97008abeb7ee57c2ce751e5c63fdb676f0cfec68442277d4a0e5db1ecf82236bb2f2c9380c","priv":"1ed983d1024d453e2dfbed2278c3c8ea3abda96836db2462da4738f20ba1d772","pub":"02f9d9ceb9a27e4626d09331f645d40464c99975ab0b7344be3f6cece6cc0de8c9","addr":"d092b8b49065f0698b483e416f4b1b032b416dab"},{"mnemonic":"ecology over output enact system curious want oil denial ivory hamster approve","master":"f304cd809c371db0fc37fca212810e75134773494e5c1d20cd22753399ee6433","seed":"6693bbddb7e758825bc3c2096108aecca0414cd1b523460a14c8dd80c15b27f5f37cf4589e710a39fe663392874a6b17892fbf473da8d00d86af17aa19ab0cb4","priv":"8b13913b6f590abf399aafa87fec44961218fe45ece0f9ee8b22810839c46e5a","pub":"034738f122cf61a102148156d40aeb129bc4c54fc55c5b85462917f4013d7e3024","addr":"1657b328a5f1ddef43968178fd8034c685e9e312"},{"mnemonic":"uncover climb join country march border rack ridge track true master useful","master":"b1f2471d8e6e712e20343f06220f847caef645d9cd9972ed17684b3a44b25de9","seed":"431e56eae671e0f1ae12aeba623fd4ed4c7d3ed102588d3b39b3c0e20c104aa24a435b9ca504799214f95b7639e208dfae17fd866b2f58c0d916cd744b7e5424","priv":"1b0e22bfd60db8880827761411390dec4799efba98348052400deec1838b04d4","pub":"03c6d27aa4dae3b3e5754cb3bf8c4638576f113876cea4da0d915964cdff0cf7c8","addr":"0056ae65805ceceb8c17c3c1246c5f70dde2be6c"},{"mnemonic":"rally cool artwork leopard skate battle shine text ritual rookie sun way","master":"72c5b3c5022b033d71c7abea54feea3d3b37dbeadeea5db4c8847a7cd0e20d3e","seed":"d7fdcb354a8946fc3449107361e4bb3bfc569c0d3617b450484e5a7fcfd5c690cde3a511415e08be23672789d090a3c679a06be36a2a20204172e1d61433268b","priv":"dd57130e658e43c9adde730ca57aa6d43d31efc3697a752075a7cb491a7ff390","pub":"03b7cd7259877064b403af9a65ebce47f210141356a67efee77ce456d46d948db3","addr":"a8db1e5ce299462e4943d0eb05c146591fcc3297"},{"mnemonic":"room vapor anchor forum stage corn credit jelly level cat detail auction","master":"fd531ed5d65637f6031aa02ce031cdb366bc8a07b00fce1104675d1a653e7995","seed":"f42ae529e339d9b204165f2b5556c1637395d9598cf5a59717d048d7d5abf831e60abdd457f3432ed2ced4c13a5a73625f716f235d51bd7892cc16c294925cd4","priv":"c2342924a2792e7c4bb8523045faaac7a669fdd00b2621bd38077f58a32bb0f6","pub":"02df2b027f4597da0a2e8f46932929044dbefbcd5c5ee38c2147dc1ea061dbcf8c","addr":"642b32cbc358915bcb802eb30690951710f597bb"},{"mnemonic":"have offer number egg canvas uphold memory snow know orchard cause wife","master":"8ff4d3e7e6ff972e24682d1f1116c7b83bb94ca8cffed1db9ddb4adf89e2bcb1","seed":"14cc60691b49b9036c0bb64ed24da69478e01deb36184f58049d694ccaabc41d95b1e6734d9d06e7009c394d54d80fbd65cde6ea49165879dc306c0125b44681","priv":"c57093fcc3c593fec4002a9040d90485016346a9f4f7d896a105ac268face5ae","pub":"0252fef0dc82142ec121c4b01275b254d6a78b4600f417dd0f09639fd94a23c0af","addr":"af5cea50c72de4e54216fdcb9334a5f5a8a0393a"},{"mnemonic":"garden nature witness stable over move among pledge woman cotton worry behind","master":"48d57d0dc1abbb7142aad3371d68c41ebf078970c5fdd4bfd7294fb6f8d32b45","seed":"bdca43aa42eb2a34dccfa4fd48202cdc386454683850a12e7eb7eaf9998ebcf57a01a6fb1a6b9cd8aaf2910b160038fa6adb42daaa914c7628e27f912687e52a","priv":"63dfb6b77a4286875868db4877a3d0f3f0ae8c2766b9c5d9225f48071421d832","pub":"031e57ffbf90b85823505710bfe5be2200f1d880171e8480494b50a04462b98795","addr":"a7619c6704a7341472229bb7ace1709b88ddf175"},{"mnemonic":"pizza sting refuse olive final hungry kiss abuse nature junior opera tired","master":"397240e78b72dea36dd17ea2ef3a15f18f8fe64c9e31a30687d2fb013e1ac6ab","seed":"1dfb236c6bbfdaa74b02300a0da7b2d57a2fc2f736a5144186cc89b6f20a23d74ae59338fc04367a27e976e41f1d1bfd4232a3f386cbf74220c9d0c6fc5c7077","priv":"ae5a8c5bfb71adfb89055f61e82a6ef5258f6bae9056313c360ea454bc30c052","pub":"02756acc7cd398fda3d485f6aaa15e7e4e558be8725d9766119e570b2b64486372","addr":"c4c6e359acc30099a524b67223da51dfb6557de3"},{"mnemonic":"deer easily marine thrive author despair puzzle super agent life rebuild soup","master":"7efbef221b4d50acacbd20a10c1197727e9fbef29bf2418f51141fb8a5368618","seed":"2ad829ff702c19a138945f61d1449c32d6b16ebdfa34350dd434bca3899b6eec3f66a3dc8de7243539f7d6d07f85689a66b0e9f6481a4767a5630c2c693c3ec5","priv":"b6321fb4900455eb1986073f5f705d088e795d26ec53c09b6eedadf439fdcb6d","pub":"02e9c7d430122627396412df161a58813327f436bdaba34f3e855263044e1fcc77","addr":"47f0fa963518339112a65e54948c5df8c23daa72"},{"mnemonic":"gate calm appear symbol make can alone wonder cherry couch loan firm","master":"9a727a9574790f29c890079fc9e83b0bfeab84d9e79ae6b273ea8266f4a754e8","seed":"f37c4b52afedefc86a24bf4edadf6a2f151aa9d503fdb3da440d53134fb040f7ed60c29407e4b74a0714f5fde8d650b93d71da52568d0e9b2056412092125c76","priv":"41e13797f2f7c41a44db247f9da73e8d7893c2be4a689fe558145f2bbb88feec","pub":"0242c6981834d9c7a14b96c39c6f902ab0a076e4a7ed29fd7ea559aeba3727da4c","addr":"dad747d0295dfdf151b6267e701f8d889770b4ca"},{"mnemonic":"opinion spare hurt three insane sick place sphere ugly sad mobile icon","master":"e6b6704a86504c2552e7db9928c6333372fa5630983e5a9aff32b0ecf56c8fc8","seed":"bbf2fa3760c82ac61467265053828c9cac4bdfd8aa43ff860ce50a094bdc448468fc6d0e6c53368e42b95aabe4f0098f9af46018595badb4f8cbac787d5c00a5","priv":"496c6fc85e550d78a931b51e6807dbfe843599401dae033db98e308430939d34","pub":"037ed7cca0717526969db9101c62cfa151cf97544ae66408317fd798d705a30138","addr":"a1fc3fc66094cabe3f7edf5b630003a524bdcff7"},{"mnemonic":"include relax onion depend animal stock essence basket local result rocket panic","master":"5830b22230ba22060e22bc4ee3323c8b1e02e5f53caeaf90759f4e846720b3e2","seed":"8fc74e989ab5b4ae04472887a59bf89b501e1813e687cd27a06bbef858c9a63b35531864b177d27841abe4999a7b1901d95303a395f5614a176667abe8aefab4","priv":"99a7444212b0176324718171a318f74fa5721fa46ed18b3677934408b30218b2","pub":"0213e7320395ca9eae0bd4f550f7f5f65a801066c12d95c3f9b443556011b13944","addr":"a4087ec7d05b08362bab9c8fd9406ab3bd88354c"},{"mnemonic":"cushion hover joke lottery gym muscle drop scare purpose share food strike","master":"dcc4792ae42c425fe278db48211f6bf54551f9dc58268282a5a61cd620832d4b","seed":"0bb05d59704318da60a1697d09562a05e4133fbb8f5a4750f378f65a5f0d6b9c0fc668dfe08673d6b10bfc4557250759c9f70aff9df1a5418821756f4017dcd4","priv":"741dcf7d371948cb17723b1b58759d8a0520a341a29d581abd12274014e945cf","pub":"022dd390a8c2d4a826ba8e725f54f5ba65438c97519537701001bd7a68eaef91ff","addr":"931f12464c90ac2bb3b25fc00f13c56ba1c49679"},{"mnemonic":"point action veteran fragile outdoor vote timber cattle cube deer fade razor","master":"ed95f0d3557ecabcc04fa2160560dde68517d4fe7ebf88584d0993a1a861c6ed","seed":"886bd48b9c9e337480538f1119148ac4f0a8d00cc3ba17a34cd7076bfbe85ba2a1a8f410ca44f210d9cbf6751c10bf15b6f52a725979e613f4294813bdf173b8","priv":"c489a82eeab534dac53396b71dfcccdd6880bd441b89386baf9700589d92f169","pub":"03e2e7deb2c03412bb42d4b32cae6591e4e0db745681900436999ee51ef422cd35","addr":"f9f93bbebed5d2859f83fefb58bbfa5f93032837"},{"mnemonic":"ozone pulse whisper cry ordinary benefit enrich cry name bargain muffin case","master":"ddea83ac1fba7d6c79dd073d29c913a767315bbae6c3648617b7fee73a04595f","seed":"ee93e7ea1bfe194ffdf6b0f70c2d5b5759c223620c01647fabdd1e2a94575a61b211b301cd6d4e979761febf15336c9bd1301406e338c9f6c0b8b938863c1cb8","priv":"d344fa49eee22f5cabe1362f36a026bba1b0419c126da13c6cf335759a962d36","pub":"028bb9fefe8418dbf0fca6857526f286d9db3321d12c6a88ffe8e2bab7004b4a29","addr":"b9bbd7d328f0947669fd1c81cf8a842a721206c6"},{"mnemonic":"huge afraid venue bid visit decade hurry put swarm couch gadget book","master":"8755848478c71a1c3345cc855a10962382a6c27e6c639c4a4ed245bf32bbb2d8","seed":"b04392d13e629b759aec3c28ac4cd7eb0b7b846f1e241eb79f862d6c30e79f3a5cf5ed26abcad0dce95ed6d639e8088c169e49bc20df609b5555b0bc3f3e5e6f","priv":"f3ab0ed871c3feb01ee18fd374568aa378651815b6903a2b42eb43dd70edb9d3","pub":"022d2a9a829f992b3d16f9374b6a6946649630bf553c8eb11208a68acd03ec3c7e","addr":"c61f53c2b19de0ef11583048fd19404473065bdf"},{"mnemonic":"update ring situate blade term enough evoke balance absorb pupil wealth era","master":"fc22f89a860ffe871a7a45557fda9f38369f99103e02a2a97066517190d10e0e","seed":"d18f179ae9c4767501a8238182d3fef3f24fa3259d41a07b601179f67fdebb6b47a78ddbb056170c0bddd3e5f5a884a3d4046964c0f4ffbf7b37c3e6debeddbb","priv":"32a6d9270cc30fb5bb11411313af52a3359249c1b5b38b753a83ebf516a1d21c","pub":"03a579f47d1d57202e02e7f445d68d6915a3304b256cc37c5d474e699405deb613","addr":"8501c773ed9240be9fb0f83ac2af1bda6511b1ad"},{"mnemonic":"horn coconut protect box cargo switch ghost among energy easy deposit fly","master":"df4a2a6d35731478a3dfdc0e1595486bcc245f83214a974b31bc20e2c0e637c8","seed":"454ec603e16c8c5c522192885768d941316f0736929046aacda1a93ad1a658e70c21a7e924974583d63567acf26ac15725b1148a75522c6bb26b37d9f92fec22","priv":"447e4c3e530ee519973a63c6ddc63b9e5a474761eae12e8c1fdc6d0cea806604","pub":"0359c72dce4c6c9edd2774af06545c8996e4832ae35cde19fab2f7dde55316de1d","addr":"5a49f88b1672cd9102caa80ce55454030cdaafd7"},{"mnemonic":"price envelope myself under helmet dove uncle below extend gadget limit mammal","master":"abe0fdd5148a6b93ff8b281d084e4bc92277848c964e3698a48e5d50d6503d54","seed":"f8c27b37871dd5aea7f7bf5fef1c561beae9d029b3fd937a961ad39fd09100993efe7b84699f7abadd49b81d16382e0677563d28daeeb08eecbdaed50b27eed2","priv":"8ac79807c2a1bac4cedddb4768fe92b7a51e0cdab5cb79758f5876511a9b09e1","pub":"023277dccb7b0e017b461bf483c2d3a63273e83f3acc4688733776ee3ac0f649ef","addr":"0ad65e63beb8258df8ab0f17ce28afe3bf19a96d"},{"mnemonic":"toy grain guide crisp error then group clock coin civil space paddle","master":"7c02340aafc6a15a7c6accc312960631cb3a92c4a7c6d98c43897a1c4c55e59d","seed":"a08642010ea9779615e7a55b973f014ae8bd492630f9fc134159501e53a12d402842899978c75f553cc78c061b59210ecdb20648a1187ea55d85b7ef1b206c6a","priv":"83ab8e2ebe208b1f32ece9530ddf03e0727d3313903ef13b2d09a3952dded8fc","pub":"028582791e93e6e6b4270353aac091a58922c0067fa440a645dbb4673858e9bf81","addr":"4f37f8c3b16183c245ff4a101bc290c3ea9eafa2"},{"mnemonic":"atom border bubble lift day soft rich rely gather ensure that arrive","master":"e6936ec3f9876ca2c44973ee13fc02a08739655b71a9880b0c7959f9c5c12286","seed":"00fcb87f619a1033adf5c9311bced58ebd5fe56a70b69f65b61228732337ac46cefc48b1e53ed5a6b0ef658b002fc162ce686529120a486230f3845250ca7f70","priv":"4e527b2fbf28914ffc78f84031c462f3b33ad8d2b62357ac816bc4c06c0767d4","pub":"02b77c89d89bc757872025a0933d39ee65f5ae037031359cc1e692dcda3a290c90","addr":"8c8ed73961a3055cbaf4ca0b5ab0b0f56bfbc32f"},{"mnemonic":"require panda tackle valid tenant treat boss oppose where thunder zone rude","master":"fa9c61113d7c7ad38850ebccbdc2301c451ad272d86a7b6ac7b384c4560fbba8","seed":"936d1b0d443630cdbe8c98731761ce80f980728cdb122b95753ca3549670dda6663bd93d03a5cf601edbeb0b835ba3e152f940706aab856682b9de0a772e219b","priv":"9ca97c10d757f03eec5165df506d1809850b1d8f9369a89b0bb118d1ddff91cf","pub":"0368a22ead8cf1ca5b0bd3b6b4a680d47de8342b47d7205f4ed41e85299d2f9260","addr":"f03eaec270d04d368df8a3a5408b9c010f283b8e"},{"mnemonic":"thing gorilla large fog mutual hair gorilla soft venue ahead neck remain","master":"4b3929a08e30aed05400a3a7fcb91fafa085de08402ab546258c10346a21c14b","seed":"af471c7488c0046d2eb29429369a14b2b3bd6de6e89036285dcc9a121389323bdedfd7072ef9bccfc1ea472bf8a9d3f938bce5ff58b303f9c0b24dfe8185d917","priv":"13d5e5fc0f6c184e4dad19c4537603b811186a3a5aaaf272762ee236bc826367","pub":"02ecb5330e932bc89bfaaa8682e044f6a1c64823887aab000b2409b467fa94da4d","addr":"c6d1e41d9fc95706c276d85b5d93d657d59c045b"},{"mnemonic":"ketchup blade myth tackle neck gossip obtain write script grace mountain glass","master":"3d2d55b2b706361eab66a2724609c1ae6e7bde50f3ca78dfa72be5e784798ac4","seed":"ca3ff2b26ce97cdf280654a05e388ba2ce5ff909e3bf253b35c66c4b9f8d630a81c6367537039ad09d05ad7fca337c479db1b34544c26331c5fb860eef84f953","priv":"968bf9c285110ba33def9cfc3f47c82ff8050b854568cee2ac509191885c4c7f","pub":"02d8719b0bf9e5296ff70bd88c8eea612b5161e80be5315a9cbd4ba84eff6dc788","addr":"868855cc81bfbc80fccbe3f1fd2d526db7cfe298"},{"mnemonic":"violin toy phrase advance banana timber viable half nuclear friend bundle injury","master":"494774c8eec7a45b2e54e69d4ca64766ada0b90ab1d2f6913690b7b43f489b52","seed":"d11d7a22d020dd5e4ce9a9c162637f47223a4162d5b1920d7ac83d99d73c40ee6b67fad2c534f8100d2529afbdaedf7d2a8cae2e921e8c6e02e3bb8d7417205c","priv":"57827aa1804ff699ea31602eca3ecdef41b722bc2d321187b48c5780962c0f73","pub":"037fd67f44683a2613f7b049a87f47cdc7710d0a834658091675497600d07b485b","addr":"6b13a26e1a545c77cedafc8592e55363742b55fa"},{"mnemonic":"forest unfold spy harsh pitch alter bottom album renew siren find bomb","master":"f19401a9aea13a1daaec39107b9b860d4159b8c66118bf13bca736937eed4e61","seed":"606f8fd5651b2b7cd9e5d9974ca44c8dbee170e6c60ca3d7a4764bd2a1a31ba79b60d0c32b40f2998a3fbe784edc40f93a917f726d2d0a3a07a3871358bc4f7e","priv":"40bee09d892253ebaaa28579840239123740d952da7bb782e66410998405c2f4","pub":"0310455b5a6e7c5d4d09a3ea71e2dc7aac95e8457e6db3bcd605010e6e8f96fa7b","addr":"5d40749e1f1e8aaf38b91c12907f561668f3c691"},{"mnemonic":"goddess isolate speak arrange tumble ivory give message palm wrist slide drill","master":"424c0dd576d73827d765d558616a5c5abc92ff548c82cd6e5a277a5a316e0245","seed":"36d58066ea3378f1851c1e762f36697248c2799dd98b19d74e69aee16e497e4014244f62f696f34dbca202f78f7b6e21585f91531bfb8c3576f910eaaa64b524","priv":"f0c0691851dc50e5ec0897cb29a8e05032b7d02afd774aad6904ff44088f2850","pub":"031bd47b8bd9a56d24874a1df5c15834ccd5bf553e7858e2cc1df2c045966d5ea6","addr":"eb4f13a437254adfcf46d5cf7fafd4b2a059a99b"},{"mnemonic":"penalty trigger panel ring menu toy behind forget tunnel various giant melody","master":"770d401afbd35db8afb7a1864b794ea5a59f2c65127457d4675128b039638e73","seed":"81256b9fb40b02feaf3228eb300d1b002f9a8c0ef03a2b0db187b265b09baa4fa28ae7992c1ffa893381e572331a5016e6fddcf3871d1d836e92ba94a44d92ab","priv":"380085bbd1a2e2f50eedff2c758fb63f981adfe46a25db54ce7f1d7a68b6b7a5","pub":"0367f233e57390fb166e45ad792a054ba908fdbebf11c20a3c199ddb134244b7d9","addr":"ca1e2a50753d833d16c10ac03551839734b5e3c7"},{"mnemonic":"usage real inform betray ridge call coin warm meadow gossip river predict","master":"8aa38fef2d5a72f6e97cc57244f0baf53b976ab7263373dceef0b46ea52651e7","seed":"9b806b194b9afe0f5f46b4b40c4658198445b53462b6aafb2b1e82e1c98fd29731d193681ee43f3d9d70547a5f512344809e02d15ae441916725da5e63cb3791","priv":"10835079af496655bc2dd80c40c0b10f18788fbb9350a7c3f2abfa3e00ccbb2d","pub":"02a3077b5796d8cab9a90186be1c1456d75b3076760f2720225bf4f38eae7c0e1b","addr":"f7deda6ddbba1cb091c8091d2e43c01408fe0d8a"},{"mnemonic":"mechanic share spawn limit panda quiz glance dinosaur gold skill initial replace","master":"0a84289f0c2aad1de0e750a0312a2a362f99b8f0c7a15b1e11dadab1df18593d","seed":"c45a8faf2b5af3ddf883837378d03bf6566c6369005df0c7995ecc9718e2e1482fd42d3411b58bb4a94a637c41f310a8faa0209117031ffe993c0f04b2878935","priv":"10bb410b31a37b51b19165dba5171d33e826e06f83b8c590a23b9b2c8bf11b45","pub":"0331188abce7c6fc99ddee0d7335e872b7cb2f48a7ba7dcbd9ef093c30fa16a5a6","addr":"d3bd3dd9d928d4bdeaeefedd058ccf7047fe82ef"},{"mnemonic":"velvet renew spread mercy volcano always snap column loyal possible ordinary sock","master":"a2fa675336bc532f8e1c253861eccca1909a195238dd202e45f2f38ff421e721","seed":"89c8378d8a7c2a2ef02bbcbd2da9e39f6ef138db1d02e32cfb492c09a132e726c69268f9743e464a8421fcc0d5a0bbdbd00dad61798736c673df81515330ac17","priv":"ed486dbbabe3def74d052685a75e65d25970d8d134724968941a6b8e94fa2352","pub":"03a06dfdfe1fcdbc8e9ae8d6c55ac974ef4075c8aa0a5783bc87f9d9c2d66fd5b2","addr":"00c4fc7760ae8f7986f35efc66d18401bd352978"},{"mnemonic":"secret weekend fatigue anxiety second ramp tribe employ quality yellow game choice","master":"0f326ef21360ac2929e4f8becc2e8320cb49970ed229f987f15b9f58ad383d96","seed":"a29c1dcb8899cd716ced74d2d81cbfbf81eb8b7ca7ae0214ba270be71e8f4a77d235a607079897f6ba6c5aef44da1005f3ba8195775a562e7d243b2428ea288d","priv":"db24d2fa242ff540009bc15ace40783c1535812bd0c79cb145187e4d648627b3","pub":"02ebf506214798f631572bf5f45321adf084d457de1425c929059bbbc328948c5f","addr":"27b810c5c8307a20b949b3945b82c0ef594bf192"},{"mnemonic":"crouch gentle hip then measure brand enroll camp vibrant lunar still action","master":"f10577e0eeb7b2385b797acad2bb4e4028bf1ae52cd59f0f53ccb6eda0727166","seed":"955eeb623726361c94806c10334bf9b1df08737c2b09fc3bca332d9f8008c5f357dc69e07251fa2cb1330c1099352e76ab445f824361533a8e30175cace06812","priv":"2e0602e9dafe830a4fe783c1b53f9c9b2f7dc0b69a52fe701f0bc6f88beac1ea","pub":"02ca1fad1e6ee189fb124863445fed2a9a923d7ec23348771d3789978d30a275c0","addr":"51cdfbd7d00e618d63a64bc662cacbc183fb2b9a"},{"mnemonic":"cluster slice enlist shift world satoshi mesh disease season ready can strong","master":"74d52d1a33a53a722c7319883ee0f47f2f76f39ff17e26b77ade53d45df83a5e","seed":"cf8c965548281a449796c37a12dfacdbf395e474b5336073985e5d7e794d80ad0ff5059a3df31381d9eade948dbbb898f4fb7ff697d2f398655573170b416329","priv":"5b8824e9f9a0cb0c0fc19f4d06921b32a76e1baf98c249dcf01c77bff2ae59af","pub":"0309e87c2c54481db5cb4f7802d2488872f07fe08dfc3a984b932246155dafb6c8","addr":"dd84fe8fef92aedb045bbf091b93c7abf4f34352"},{"mnemonic":"series element media flight next blur fox impact joke review token emerge","master":"1841af9c8f47747ac1819c178e62673e51e2957292ee608557fa38e2ece61d6c","seed":"02de6354734c96841c8fdff0806fc5a0237d621ac98acb7eabdcfc94e458bd2e7d71a9de2f5107e188e153946798775450aac5c62cc293adda42a03e0f50edb8","priv":"a118a4e3a22a82e48a4847a644c452794946169a39d8919c02f131dc177b4c8c","pub":"037b3f5d214185886313379351ac7e6ed054a7db85b9f5aab74e2bb78abb519a2f","addr":"f70fa3d5dc91e442851e6cbcc827fee336bf267d"},{"mnemonic":"engine surge protect goose warm bottom frozen menu royal fox escape sword","master":"9ed672fb3cc919f26c925be30c6dce07dc101af5baad5b6dc2264f5580819b3e","seed":"21bec398901ec8b5b4bcbae5aa2e261f96190a3e9350c03a0e23da3755a4d36ba0532ac17fb7a41266905e76f2d72e90b577e86bd6b8f7ab62a4b835292a94be","priv":"0c386e0854877e7a34bd8a9c9794f107ac2114e05130861f77353406fe9db555","pub":"03a3740fa2bf35d6248bbb7be20d6c264dc526f382f72696a6c1c28ecd2bf25944","addr":"d59ee54eca22ff7873b68b429be08245b836141d"},{"mnemonic":"dignity almost rebuild habit visit come carry deposit stone page soda room","master":"f4eedac55ceae98a3bb706c442d3ceea7caadde17ea5a2d0c81cefae9af754a0","seed":"5ec26bdfbc0d587473ceea390a99616a9c8c4a03527627983cfc9cca8f7779d1ef7c08abfa0969eab1da7c8128cfe536b6d2d5a07c99cd1afac0052e8a753d7f","priv":"4ecd8b9d596eda21b65ed39c8f53dc6ef2e19726d6eaec60da340095aaa3be91","pub":"0392dd87d441269c56e78939eaef320b6a9c0f0ddf5758e57663f9f268dffccb8b","addr":"eb71c884b8e3c1b215445ca2ab5d5b51a6bc0be5"},{"mnemonic":"input sound bacon tower fun evolve song pear various laugh code sausage","master":"b0cbb2481cc2a131867c6514b194146b937a6e46e497d6b4c329d6146433b13c","seed":"1276370b1081d2b48f45f8df73af1eddececf2076f8425fb0b593557392f3853e5298ab5a55f0e367a578932f8daf640d40d8465ffd33ab4bb6c41fc9a4ec9f4","priv":"c358f0d976f10618d3d0a600c0ae754fb2d0a2a97a385091436178ef4bfa332f","pub":"02b2e45327f09ab88143f72f6bcf5f4fdcab9101d55e015022a5f7b63bc13b1a6c","addr":"ea33c880b7f4cbb849c551f61ba630c4d9b97155"},{"mnemonic":"tool lens message country slim wide fresh front merit science argue cupboard","master":"17e462a6a8c9e854a6a7443f0f903749ab8967d8fb3a42af27ba3c2819d0c750","seed":"506cf27425374254890839b40a5a05218cb5e8d7c143523058f74d2f955c5cfdde30cf034589fb7846b9ba3194bfa9fc1eedbdf2b706b75c9b51719cf7bbc663","priv":"995d94dac98165acbec37aa586c52d9c7f0a65394027e3350338eeb69a801155","pub":"022f8ae9595f1f48654fb99985148c5c041dd4a1da396ed59cfdee3f09d7166e93","addr":"23f909e775cadd631b1b3c75df7027382b702167"},{"mnemonic":"beauty fury random thrive grab merit powder wreck affair bitter style girl","master":"2b5ebd0f07795968a7fe8ba12da106195f1fe540d417190ddaf4b11527e5f2be","seed":"c2df6f955aa168424697c97325016298ad6361c3a197ea9b446e790d0b2e877f03692a86dbba512e4afaaaa975484969c14cf0034cbc3f5571374ade85e6e714","priv":"ba6c8ef770c6258ddf7a395670a13cbf661deccc4edf5601e70bf44d1d40d63b","pub":"032f8907f58fa7592e6a8ac556f605a981b7cc80c94431e78bdd20ba086b22c2d0","addr":"9fc0563bf0185e0e99f266af339220588c655280"},{"mnemonic":"code aerobic tent hero install segment truck foot employ manual dice time","master":"bb99c30775706beb704fb7a7416c778c295b82d93c8919d521ee915468143401","seed":"bbf14d684a22d95920436c3133dcd0748dc6e3a133fc61cd78e9f1bc9aff37c473f0ced555265f961d4b7e70b6151c9c7aedfe6930e6a352d2da531275833a4e","priv":"6b766aad48cd0ac49d4ea1cb1bd9961d0c0d2f38f241c1b1ac2f1a8b1f7f86f7","pub":"038450b54d2d0dff23c557b3c66613605dff4df0afd3a5b22dc1c93711c9718d01","addr":"e50e364ca287feaaafc0a6b1cb1bc8f3f1410a02"},{"mnemonic":"media custom wolf spider bitter require blouse soldier barely pause upon inspire","master":"83ebfa6de22ec8362e519d5430a1479c2185bd44749be80f3f5381cc7051d125","seed":"ec99f944a7043eb3da146ecf22086de374cb1b55c64f436f9489b7f4f1e0ac6adb0f937080bb20405a4b225bad173729abf5517e92c3bb75aeebb516893d54b7","priv":"0771719a4060245c49152ce121c01ca8fefd04eb559a610a5a084a772741141d","pub":"03b17977e89ee44c699e018352461bb244a783c4e2187ed49fdea72a479969e745","addr":"493f3d15f460402da46eea1dbe4b767273eb15a8"},{"mnemonic":"build key hope learn place romance parrot ask spy whale input chimney","master":"d3734ac55147344c1aa411a2a161f42710308a5463ed2183b9cb561a8f1a92bf","seed":"5065c3b0a1b3273acb090c991269ff667513cf41e34a11cb802b8880591fb5f9e89ef614306261b0ae2148e5747649b6d5a375ada3749e75e084c3b28faaae4f","priv":"ed51941c62cb63e1e232dc903894fd4c8797d69f501f41f85e1763745ea7247a","pub":"038ddc7d19d6bee458f791b34d2acdbadbec78a228066a4bd5434ae538597689c3","addr":"ee83ae098ae348e6c5464eff4d177c04e97862c2"},{"mnemonic":"habit pill guard artist void crystal various owner shadow inspire plunge price","master":"c0a23d72eacc59b5a382bbe6b59d4541f5c65abf8840a16255a1610ac56df1f2","seed":"d7d1bc83db47fd6215a4e193f654c8246957f7f62b6f8b4766ce867ee58d69b01e749abebb2de94f607e2c442554047a65570c4ef1e764c56295a8326fefc232","priv":"f2cdd0461e210bbc69f810f796189167a71aef2fdd769487c772135924d35060","pub":"03a0ff432ff63da4b30ad757931bf41927c0311f632715aaffc41f1a39dad92208","addr":"a9fadf07acb53dc1003c0de03f40f73767cf84bc"},{"mnemonic":"miracle chest bind idle bachelor science catch scatter current argue fiction ethics","master":"fb1730aadf636789c12f30bebf66b5c9b7ec1138e126b9280491f61013e094b3","seed":"2139c6cd3f1788ca6f91147c60d14498295daebfcb65f0732d3c2d327a1ec8e01cfa011e840503f5c49c89e9092ac88e5d688d0fa945b604a851fe4f4b48e404","priv":"a4d77dc6678d78fab38419b72857914e5848c4daa7bc8e47e960a74708fc30c1","pub":"03b946212019343e657dd0821422044234507602641f389ce1698256054e6b194e","addr":"c67df9937478387372ada7cde57712ed05e6cfde"},{"mnemonic":"garden box bus under chat pen connect access police mom crunch elder","master":"c49d46b19d0078803cadb2a63572295a9cea729fb31112b48cdddc9311ce874a","seed":"fab44285c884dcb44b1adc9823cc021c0560a92bb9ebe23ddc25a08c68935e64733aa1f7b7a4ed30494d8f74cd8373a77e114884f74e6804696cf94a6b0012f1","priv":"79ea8bec554ff6ad0f20806224d7f0402a07fcac87db0b4f5a6cf84221cec17e","pub":"02492778ff035fab9ee383b424a90d694121df7cab7ca984aa8a665693c44cf726","addr":"2a899dd4387375c42068e42fb90793e5f689d413"},{"mnemonic":"morning street camp meadow moral chalk pluck winner light same grape drill","master":"e5a773479add64869e28f1d1a01fd6200de25fd53debfb000504a6231d2ab263","seed":"5e24f51f1676b996b470c01db9db032958f58e1d22bd7efb2bffc55baf73700d948c5f82eae0f6b82f0b9158141b173187ffbf4fc792e43af194c992884d41cb","priv":"4794fe7f9410adf7f567728f98daed1eeda0248d7d0607e57c4ec184bafd8504","pub":"026145b6582ac105e06921c3856db99ac7ff518621d984214cf34f5c155f0c8736","addr":"f263e7676644a577d7b535df98f7eb6d3f45fcbe"},{"mnemonic":"annual very slight slush tomorrow stage mother girl forget castle emotion move","master":"53725daf3dc76a16b54a2086106ea4eec394802f70741e2895a06655ffb4ad34","seed":"fc6f22026780d6255cc7a21746c7ff48fc773a350784471350837ca92d9131e9bccaf78ddc60a5bd8dfa9838755dca0c22e6efaaa757a5bc4b2ad341e4cf5d15","priv":"5296ceed1517058d022c8fa5c8e076851745b98465e0fbbc834a0aa872222bbb","pub":"028250ee9798cccbba647bf41f7b338ab4d15f7e5dedfea1857213e125fc8795f3","addr":"82e76dc9270c795c2316a618abe828dc2f09c1c8"},{"mnemonic":"novel swap prevent funny lyrics erode wool pilot kite junior alley inner","master":"dd900d54ceda698e6ade447839e3eb3f64cdaf8f006d41ee8e1a2f3b66b55754","seed":"8b6b71539ed5ce60bf33745f1172fe3de811affd5a494050c4672f2acda9b4af9aa57fece9b8981c94b1b9701eb27da0f67b8dd216418ddacfc5b84f0c835c03","priv":"4fa69bc81f76265d4df75bc208294244c5191ba7c8d6350bbbf4445e90b9b4ec","pub":"0281946e059cd4dbf81328a3b01ea285e106a390ec6a1b938327a26b85b3e2432f","addr":"12e1ca832d7826ea5c85db514ca80723f83a59ab"},{"mnemonic":"film erode thank mobile file ball inner wasp unhappy borrow polar mass","master":"61b10af9d2c25aac6bf1b1d4fb2e0899c86e40b5b3aab8a29986d241aaf6d414","seed":"f1be2b5ead5055a4446bf8d608c754f4b112f25780aefc7859e9697954910d827969b8ab2d78582ee6f91985c7f740e3d5d5ad08a7f3db9e265aa977d4ccac58","priv":"816f805d3076c855f114b1f8fbe1a1476fc02a71b7b800d6c5fb9d3b1094adf1","pub":"03f08001ebfdcac89f9d4d4cd52f8529b957a6e1ab500d541edfa086ffaf219054","addr":"ed2fc0f401d326f2ea61375272ab741d648b690e"},{"mnemonic":"aim owner direct pizza enhance range need raven divert marriage gap hair","master":"6ebc5c412f961584572008b5d531c275d45e403f3e3672c12457fcdedab52be6","seed":"b07c83efb4979dc2978756f0457d7a4574f5ca3c06c133f2b9cae206f12282c29b8fee9430b22a347aabca5fa91ba9a742901aa4ffbf2a1fd5a30b7a258e0566","priv":"16e205a55aa370cc54cd05ea3805858561f4213c315a4cc91450097d3bf75d45","pub":"0309613fee96c3c5bd9af994d9805aef90ec3b4da315a2e7731f6aa1c25c28fdc9","addr":"ae3778cc1c0df866034a0ba6fd3e4d9308ed4429"},{"mnemonic":"base effort water actor slush space three tuna walk people proof siege","master":"96ed3fbe9c3d5647a24b899dbb2c67d69a629fde37f4973c6032555a48de4706","seed":"1dfbfe4c352e01a0d72fcbb4cc82645a81e02946ffdebeb465d424f92719dcde887566f784be14784742eafec3925160e87c4861663ac1ff722b554e2b1cbd37","priv":"7abe37156bddcd043fba717f9be6ebe3f9894f6b814390d0556053be00566e84","pub":"035621b9ff867ef93278aa007087ebb30bf8a045ea4bde45d14969bef6054e806f","addr":"b8ac9814855c57ddf5d9dd367af8d74bd7740f67"},{"mnemonic":"violin naive wrap margin glare sustain suffer nasty whip loan tuition car","master":"df6afd71e01d947df8fac4730e6569a23002ddeb2ab53ddc23c35349cfd55fb6","seed":"ad8e656352e03c098c0ddd1a5d9556b92f013ef9853264189968677656f0b12d6afff540bb8b548671ec2ed60a5bd61204c463a80c10e5d44380db05fc9cc4d7","priv":"607de82b3e17947b94b43b0dfef04eebe28acd497e6d5b7773feb983c0067b6f","pub":"02dd39ee3d3456e77be05aead5a1d0b71b03237929a8f085760d2e1496c3914286","addr":"2063185bcca6c0602cefec61b752ca5cd47982af"},{"mnemonic":"rug pulse coconut equal coconut soon helmet trim peace fall please robust","master":"a47a965d564ace3708293df5216eeb7b963ef1c814805acf55f76a9f44372ef5","seed":"e099210b6d5259379dfab4cbddaa188fd5d61cc9bf9354f6546db1eec25eba33a34ff535fa3adf285e7460aac8d724dd5208d08207064ff6d2f794f34c514747","priv":"c8cc7b2a9f01d89708fbebd824fcaf1251fdbe0dd4953f43a9079947cddaa2e1","pub":"030361dd18f40d337500a32de0adcc92a2044481876e17562863dc32412c8b9fae","addr":"90165eae1989ce6ab3edbb2d8d35cf843138eed3"},{"mnemonic":"expire company bean basket weather apology lottery energy column used goose advance","master":"66e2f9149b1c2ac8f5f9b139a52567d1284f8484d9cf338b016c4d361dbeac5d","seed":"a4218fc8ca69a1661bd0cd9d9a458c996c48502cfbfd72b0b018f7432ef41c8431f70cde82e7bed983e49ae7c01bae7de6d7bcc590677e166456e5a6e4ccc137","priv":"d7377837e6f73b9093b13741c27c8b25a0a323aa7046483b3f13e9ebf4d436f0","pub":"0368018fbe6931afeda06980639c2f5b532245eade554f5c2ec73f3a532d056718","addr":"a41364a6daca7cc6536aceb4a32e657f3ad22a84"},{"mnemonic":"track essay chase camp denial ski worth retire expire amused paddle ivory","master":"d764799a1d97bd937a1b9dbf4a0f7cc91bcd06c6d7c1a1dd3d25e2dc8d63b0a9","seed":"e3e62475c7d13f79f2005f61abd2f674bbb1613587b3e694c70f24f6403f0299140b68567608420af5a7d540a3707eb1817fef98aacc3e861c17172e3a6eaf53","priv":"b2369fb324c5ef9e7e7313a87470984de6ada9dbef59def90c594c374cecce93","pub":"036ecd0c3e3312f15b3ad399ca5281546366e33368c00d7066bcc371919df9aa40","addr":"42a6d89451dbd00904633f43389133bf199a090d"},{"mnemonic":"mean hello inhale jungle brown cause curtain arch orphan spy aware deer","master":"a66b0528350e9aab8e3f7985a658d50bc31d3cc88d145817f77f889de8afcd3f","seed":"3e240baee99e3e3c0030af994981ee7c10311faabbdd685cb41b971b647aabda05df165b31954506c1dcbda0d15bc9dfb3837d8561e8b346439d059431552c00","priv":"f516389c1d667c77455bf3ea25789d8fe6cbc52c62fdb54849f857fcd35d7f88","pub":"03fc762324c6a0ad341118a95cae96d737eb0194e05272b92160ad3412482d6fb4","addr":"0ee6e446b5713f87b9a8384c3fe356e45a4d6e49"},{"mnemonic":"clog just stomach title gauge park couch coast fault demise march smoke","master":"f964ec3cea5791c86c3740626bd8316bf3373dc874af01e2ee844c0eab7b9ccd","seed":"8175672d9e9e2c8e9182f0d6520eb1b0ce82a17a56d51019acd5edb9eba0c9abe7ba77a895717eae9bd565ff0312c65209c250ea48965be46292a4cf7c1ec7bc","priv":"445d84baed03c168e29c5167e6257198fb2f7fd6893b4323e692bf3514364719","pub":"03b43255f28016c8961fd0cf5dc49e427105f290b7025b6138ec444491e80e9be3","addr":"633349488a087a2789bd2a99feb62554bb35a4d2"},{"mnemonic":"silent burden donkey napkin churn equip artwork lyrics wage enemy fade sunny","master":"754eecf77fe825d148dd76b15601f36ea3c1a23b1535ebbff1be9695fe293bb3","seed":"c61d6da1ddb2a00797ec94d1bfe43df5d012c75bbb916e0ce42672f043a979e8cbbc4187867ae36edeec02c5526eb540f1ea4b9778c2a0b534d0b0e9d8a42286","priv":"530591f5c65acab37d4a98df46cd6c8ac259dd019dfb9c97fc34b1c9269cb42a","pub":"030e423006cf8ee7ac079b31591ffcd73f6d63b8e26e765a4b9f3dbe1022b2af22","addr":"e4da6fc6965990f17c8c827af0b0c2a2d9d87867"},{"mnemonic":"quick toast trim image exit clinic then leopard slice recipe acoustic meat","master":"068b8703650bc546dfe41908b04a7cc430add80d2c247784d41b4241a321b339","seed":"73126b2fcde7ca4509ee115803d5bcb22162748ba465c71767e32d5b271ac53c63168d2a16032947c1dc87d5e78e5117c0171abb1bcb4912de0331d7a7d7b171","priv":"a9251969a43a62c2b25f10aa0ee4d621cc1d5aac612b6027fab2a505a5dfa0d1","pub":"035a135e39da761bac2346f7b896ee0d2cbceac71d9679a201bf2b75e00ed047f3","addr":"f7f4f03d57d3726337478e5216c680c4543ca9fb"},{"mnemonic":"innocent struggle abuse math try bright craft lucky excuse fly nation include","master":"631066b05d71d61539a24b7cb2aa659f1a8d0e3dc76c5ea28d4702b18546bd71","seed":"6ab66876fdb7658a98dcd39fbaadac319ca73e280cc471ae3954e6899997f35576a4b7a506ce3c2b447ccca6203092a2c47f1018ba6d75ff58c416a3ae693f57","priv":"4c6c4c01ea2511f4ec731546f35cb469d424fe6af5dbd8ef3f4d27b7013e014a","pub":"021d951f161be476c1795f1987deea93eed12181b8b1a251107d83efe2d96c3a01","addr":"eb09dac4658f82aa173e5388281877403b124b85"},{"mnemonic":"weather fine valley envelope convince cheese primary scheme invest rely science pitch","master":"ea23ee8d99adbc168bbc367b10cec018bcc7f15717b19fbd05de7ab502701ff7","seed":"0c485f94abbe0e9ee91dd661eb2c6670588c712d7790e9d6357eb7dcc1f2bced5d0c8db8dd0b7aea72a6a057ac97a12980d753ebba11c2fb627163e729a74a8c","priv":"272a773d44247e0d0579731593d568c31017567d6dc29ee9cb2324598d1d7a6e","pub":"0305d1ee431078056588a2d2e503c40d1ec6070e3b06a78b2deb04c6de9f4b00c2","addr":"bbb37db4d3d3f8cc16178fa777ac23200c05d78e"},{"mnemonic":"portion visual market hurry enroll stuff upper pistol tired question barely surround","master":"997415f4d0711a371b522baa2a003fb6485f4979e170492c3104a18e7fb90cde","seed":"51a7489d52481c5fd36a703c9e832550f10bdf24b06f9ff023bec374c5089de64e6d06d61ecd509fb44972a92094b4cbe1dc13fc1ce1fa6ba04b03ce803305ec","priv":"8c8acc19030ae9e9ede5111a41637a7f69e624be9f098660247cf0154579018f","pub":"02ae3bf3047431b9d799b99d56bead936c5459039b965a612673a70ab9209e87df","addr":"a2d63ec58cafd042ffac57128bf9ed704d9735b5"},{"mnemonic":"intact elder sign valid party enjoy trophy mix hood bachelor near sadness","master":"fd40da840f8bc5eb4fe8e83611c5ffc897dc315583daf95a9e255bb8441e8605","seed":"e9f3376502c9e4506568876341ab89527694bd9f0184650c3f30fed6fe8b8b8705860e0c63276f0d92db398bfc2cdb4b816d58dc48a5b8ce9325139c1b96d682","priv":"bcc54e226725e41f96f81587653d60b736a8da21af6b24d9306bd6b94d1959e5","pub":"023828cc58f153451683a39c3cef165e8f3a5499eefe018f945b63062fe05dc82e","addr":"cbb390ec8ede1eaee76a40100c1b551872eed89a"},{"mnemonic":"unknown order purpose spice master small inch isolate loop frown page nurse","master":"b8b282b74a246171e39a795778958bfed4fce9aa6040c3e9013b1afc712ccb40","seed":"403e11937a99ae4a4aa3ba4e0f682c158dab10cc5cdd3b79be276e5283b0f91fb7478b6b33e30841b356cedd2091417a1fa09925e40c1ed23a9cf54484883129","priv":"c22ff234c4bb00b72005e1e88909dbbfbba148c90305eb81de0671a5d28da59e","pub":"024bfbef04401d5a5938c64619a6c566011b3cde0c1418f2b62c3a921f3d3f14ba","addr":"f0fe3107cd932d601abf273b7547be623bce653e"},{"mnemonic":"angle blouse weapon upgrade enhance frost fine pear install method duck okay","master":"aad7d48511dac2782ad61a97e3ca94352ad24590f1ffca0e9efc3c6ee69297e6","seed":"8651c2d20d4af238121b528fa601c290efc255a569c8db892ca8f77d634fc02f7098efb7a9a45262c7e86d3d71cd92c7239fe4bb780e69ded7782c00b1ee0ca1","priv":"4b8f93833d5896f673ed59c0bd75a34917a61d521cb8b8bdb22814a0da0eef19","pub":"02e17e65c69b471a9fdb75515aadcbba673dac78c0f34df920aa46ad65623400eb","addr":"c404a9b79ebfa5ed9066e06aca8e091c488bb740"},{"mnemonic":"trust huge gauge culture garlic fluid type drop arch camera true claw","master":"b74303ffd6d878d1ed69a0e406741b51bc725887df08a1c8efac15a959b8d0c3","seed":"715486a3cf1e3db172fce32a23868a832fe7d5ac2844990fc14e951a9a357f16e2b5bdc669e415a40efc7ad14020991497496e980395639a68c6c7b037690cb9","priv":"2c0d6847313ed5c928480a302bf3fa0bd9918a5debc3ddff43cbb4c9e3f12802","pub":"02f79fa697f78fbc6b154d7b14a3b28dedb6b746b9de88c0e9982a54904ef124d7","addr":"c15d6b60ea16407697665acca000d5f792fdd3b3"},{"mnemonic":"shadow sister evoke wing radar what trust main improve moment flee erode","master":"cb1d183803a2de896f83834d19c3e1ef518c3fb6382dd68ab310696bd1d69b7f","seed":"444b9c8d29447c024f11e3c6c1618e767d908dbcf380125a062ce18a552f39fa108361fd18561406eea36e63415d286eabe5d5a5fbd23ae5bfa846a3e8bbaecf","priv":"dd1acc9e8972c3bf4363b3411ed96f41477724b4353e514b339baebbb03a65bd","pub":"028658232d2a075b2c68a519c47d2d74636fbdacb8bb31c9af70a967682816ca14","addr":"f8db02ece9c267f8f5b7de9c801432e694e22731"},{"mnemonic":"guess beauty gift repeat desert oblige pistol pottery lemon clutch discover dragon","master":"67ae574f5ec3766b3a0e1699dfc188f0ec78b51e69faaba76dbb08cd3a9e6382","seed":"395674e7b70cdf97f6072be527bd79a6fcbfffcb4322786f8d17611a3bf87947a87fd59146a59e7143a427c4065759ed6973a00f6aa522e6b13058382eb8b080","priv":"170df49f85c0a741bd5a6647d33410f944619de34e9ebbe7387fe8785b470960","pub":"03dbaec7aec40764a0365a6b2b00384c7966e9b2c97432273abbdfd089c519fa4b","addr":"af3c030ae37cd0ce5d3c41012b904738c7905887"},{"mnemonic":"fire duty baby kidney coyote arena bonus convince soft party blossom brave","master":"2054fc16a8c8b5955c76150c43fe447fe7a6d083b323eba70784687f94780a75","seed":"c16d9aa8d945a01871a46a92881c10ffafeebc0b1183e97812169d8f6e4f094e70f82576947917f3f6e551a9b9dec573478180053f6e0d71c5c48eeee95b54af","priv":"fe7f533210200354ea9c5c972cd0a4445fdd8a2e6e6e830cb541fc894e2e0ddb","pub":"02f9fa53e71e4a2a180d6daba5ae9806ed5e338aa680e2bac8fe25ff1a1a151d0f","addr":"2f028ee2adcec5023013e7a3756fe18c9a87b669"},{"mnemonic":"poverty inhale unfold strategy insane usage festival dizzy drop divert august head","master":"148e592f2c22b1db9d693e3777470b27ed0fcb2de1c0ec2d1f9f47421ff98cd9","seed":"412368afe4a71e2a37b1f87b7ce82f64dbef5579b16a6c189fa2ca29759e410b7c1e13a7b591711fb3d5bc8fdcb3292b3c828e52a2c1cd20aa55c830b8506a39","priv":"7e070b5f714cc7e0e031be68dd03e6b3e18673b5966d9c17616554df4e0f3288","pub":"037227c68b192bd6ed034570d5b5d532354dc47891acae0815d0acbd8d0346ac2a","addr":"439c830a56e6f8299c4d859c2cd5fd4a821e6dc7"},{"mnemonic":"gossip quarter proof require develop about olive boss fiction quarter rely build","master":"8b7580ddbbb3b766cd08088792cde2429c003b8b0fa5a9165747275685223a9e","seed":"a3c24f6f125702480e2d8856095a96f3e6d596678f15817414631ffa525472a01bceb58a0790e1df38dbcceefd73dd9b6bbc5bab841503daba8d73033494c254","priv":"5bb1bd6cee64ee4cc9b08f27b34dfd3da9ea263cd7fe7b4d3fc8a6a2db4e0ec2","pub":"03bcbabf0702cd56f459b8cde03db89d3c953faa3c108e90b75c65eca10485b5a4","addr":"c3ba63ce6c961c11bb3f7cfbe7667ef2c1ff19ad"},{"mnemonic":"dash small ensure soda crime wheat future style guide repair diet panda","master":"468770a80bd9e0190ae3a7a695da6a7bf30ac9bede3805c7d1dd4f6052e4d7c4","seed":"59eeaf79145cd625c266dce31faddd42eea93d15e64be3a430b9fbefdabc85cc3366115a07d819bb5ee026e118ddce46a2d906680b59917ff7adcb3314d6b077","priv":"99813e574552f35d2ae337f8754afb37d8387129c5e714461a0b72cdb30d0bd2","pub":"039e8088eabbbe966cfe54264bd1335697ca335eb55d56a89ae6a2af0bcbe2fd60","addr":"b3926244d741397940f6218c6db7a7c71cc012af"},{"mnemonic":"profit brush exist mobile diesel keep oval guitar cover maximum media file","master":"f402407479104621247ca60a34f75391ddffac32511b61e83324d85d873f0da8","seed":"6d538602ce7d97d7cb5469aede489a9a4f8af829d76712c13e7851d9e63077dcea3233ad51a7c311d367d4d982bf963c016c23fe39604cdc3d1dfe25baf1f515","priv":"cadfc276bea3a62afe66fbb5a4d117aaaca562b272aca37a0ddbd5f5a20c95da","pub":"036aaa723e425f879d4b2e731fda45dd95294608daf9d553a40f59fc4cdc37c996","addr":"0b6a4c2a542c624ee95719f53c99e3f6c6f7df19"},{"mnemonic":"oyster twin legend bubble bacon wisdom affair bar search just daring teach","master":"722c8eada15c60706ea1a9fa5aa6225142a623d6f5bd946589b22b3c9e69f56c","seed":"2f3967f0ef31b8d1bfe4b125678ab07328ada854f5bb589b5fd2c5479c3306eba54233f3386409e4b68f95be7f4b20c054f7930ab022f720979c847bbac99b80","priv":"73b2d8daa926db7e9072d4576dfbd511017e1ca7876bfb453112c8308ce70fef","pub":"030a96a78ec8dbcc9d62b9a8ce221b0f740358e75ed7ead277b56a2c56bd93a468","addr":"0ab19ff6566e8294c16e734306415bed696791d0"},{"mnemonic":"say poem daring wild toast force fall bread cup crane next patient","master":"89a87aafde53a9a8fea6b38549b6bfccfc950dacacda40f83b613a6322299164","seed":"b86bdd449d73412f10419a9534fc545a5f062d615ae197b6ce5143a1b00ac838b09e9db2cebd5cb556f469a4eaf883b8d9683b222f9b8843314134bd718b0887","priv":"60b1a4533e8afb1ac5eb5448db1540b859fd3650dd4e7c52b8b1a98ad3eac169","pub":"0255161266504a58a273b413e75fba8ae3c49046a3bf8334b2bf4a203f837ed383","addr":"2c390e3e85f391607962fff3ef9c3a7ca4ab5704"},{"mnemonic":"bone path relax awesome planet exercise road reflect life ability device frozen","master":"fd23233c87545130d43a46064fa11deef11d56a3cbb0a2e52be1aa21eed24f58","seed":"c72634cdc1fb47955eb7d9fd2391b3098d407bb5da35c0a88fcb38746c4d673ea113a96707828b18549271af8cd0f9be51f5caa9718ba31d783a3b26d450e7d4","priv":"d946ac6ec053521443b3d8d2dad6e947dd544b58912fa7b87b0b7b55f8570981","pub":"028b9c6677d3fce87d4b324ad336e486d382f7b56c2a1c8723d993d247ac1e1caa","addr":"6ed322bd71b762e44bf4554937122492e039380e"},{"mnemonic":"true solution afraid clip year symbol burst alcohol orbit village arrest balance","master":"3cdf923de0656e5340979c614d12ca869b97bcb476f8ddac3c10162cd23ceaa9","seed":"13c3eb909b83529db1d166eca7cad6b918e1f58c6be120aae8b7fd2a2c848d29550551ba3d710cb4d4a8597485e20535d6e65a941d206c69774cbdb04113ac17","priv":"1432f702f33b6c318f79d2655da268dfba6075126108cab3c8d88f4de2a6a0e1","pub":"03d100bcb7a2b81bd8e49af05a92c9a874f4aadcc836be590d63ffe8a08b63a0a7","addr":"3527160f146f542703309ee02b4ef783416fc9e6"},{"mnemonic":"family trumpet pact beef stand naive book escape ensure puppy envelope dune","master":"ecc1fb248992b1402eafb7d3120569255268dfa5ace3d04fad48b1917a42c3bb","seed":"f0f55ed35029e7f123dd153df36cfc9bc97c633b9b8752264bbbc2c33bb5932ffbd1d657bad87f8ffd7d4d9a9355226d2155fff92109adfe573ec67a18657f3c","priv":"8cd151b71c1f1424e2f53a35af5d427965f453572a211d8b4315894d370184b6","pub":"022ec5ca227ab19d758ac5941b9e7e7e13a06ee9a59c94d42dd6d013ee7c3d1cf8","addr":"93f08bbc6109187bcba87f2b6bf86e73eef60483"},{"mnemonic":"feel grocery tone drastic clap great pizza artist current true diary suit","master":"cf0614735905c88cc0f2236dbf71fc61accb6fcba39fabbac4ba1275a1ce6e9c","seed":"75bee915c2f3216cd023b878d06aa4d45241a49d10085b851303bacf82c36b392e01478359e59b54c77882948aae3026539d687298b85c3517f31ec0dd80e213","priv":"03e47eec1c8f7d3ddd3bf1997bdec4802a5b997e80a9a9fdaa8ed93f2641b146","pub":"024adba9bba7c596189ff4b057a2329740e03166cf6416612676d68a6df32c56ae","addr":"ee63795d783ab1a27ba8fa2a64665c6a563134f9"},{"mnemonic":"health across rare laptop broccoli verb course bacon offer hockey vendor venue","master":"a80307838f0014f827d55ec51e5384722d7a6a24703d757aabde32dca9f6dcd0","seed":"5fb4a16684f338f15b5fa6ea48975ababb129b3c01c726493abbfea837757fd27ff0a70bcbe2d08a7174fb7848169f7e22f483b8976adb0a4b2600657c9eb912","priv":"255717f5e26bd51d607b059c9a7ddd153d9bab0e832596df648fa671d8535d5b","pub":"03ca70b2fe6fd3def827767c0b26b25534bfe22ac74f77c0c4c05051154a08ea69","addr":"c4029c4186f3e762228f4d43b4d8fe19753b99b5"},{"mnemonic":"begin step squirrel window liar lock endless maze health galaxy swift scrap","master":"53ce62b273658f9ee3ef5b78a4e9d8b9a84f383053492d86825cd9d360763406","seed":"93d7f29ea325b084210dec914666f70ed46b83b7818d2dbd1614352134dcb021d539acfb2f4d916fa5ea48babd11d95f12eee97860c19db1bc2f369c6cc96b93","priv":"50455038499b153d77f388654037cdf614bb85ba5470d8937fb108a123241521","pub":"03f1f12d396494513c14a7508a9ad1dfeb1577af519a250b48798ff59f5efde3c4","addr":"5c46de48e642722b4325afe8446608a60e7ea89d"},{"mnemonic":"snack fall math great upon wing casual acid clown despair cage heavy","master":"c40433c68e968ff1081d3ffdd47249f1bb3cff2214f4e0f19227442f8e7be4ee","seed":"6962c13ba9d9b79b31480c117cd1613f6bb9dd6613e42b17b7434547694c96059026355a2c58b682ebccddc5f84f50c05b60b517e27eb693f1eeff24a038eb0a","priv":"972881fe79c997d86f11440cefc6c52a46a1b3b9953a255da6488e7ac278299d","pub":"0276ddb2041eef2c3b487a4afb36de7cc5ce5ee693461aff375131177dc4d28b40","addr":"17ed4db6f0bd80e929e048d526dc55a74ad58eae"},{"mnemonic":"vibrant valid carbon wish bicycle adult hobby lawsuit problem toast clever lock","master":"903e9b75fb472ad89da3b1bc74937415e877c1973910cb9ddbc85fbb465c18e1","seed":"b175935f86b62ceb93ed1bc1d2f3aee77a628aca7def8f6761df8b624a29d495a150b373d12a5cceec7d394aa91d0e68c5e2464a99820ac5add276d655be28d7","priv":"dd46bb3b1342a5a3c3844ef7fb4bcb247f9a81a48e20722faa1e03ba59808191","pub":"02bacfbf1b8b6d4a6e8a36b913d61831668cdd3dc74710c0ae0851b87c65789edc","addr":"e0520de38f2d2c2d3e461b1e2fd3076af5b9e927"},{"mnemonic":"obscure false outer neglect transfer other index debris bread crawl morning scout","master":"601edf66610cd4b9467bd73418a3dac8b937ef2d08c09ecbc89110443c3c8869","seed":"9d6168c1331c952ba5c2b19a0894bddbcd3d6a0960ccd5fe685db487ab8caab4109e2dda7c487d6161427895a9803ef3fa857fa2106e48083587032c6d30a217","priv":"2389d4e6527d9190a9ad8720debd487a00d47d6ad6228d643e1307aa727d1757","pub":"03bc72643c1c9a13f31de0a61815f950aae5e186328d07bfddf8e1dfe952fa8b49","addr":"add81ed8c06032c52445dea0db02a9f56b738742"},{"mnemonic":"minimum coast chronic damage page antique mechanic material worry alley nose tray","master":"d7f00c2baf2037008e9d1fbc1acee85127db59ce939491aa5cc19033f55f51f0","seed":"0ce817dd3a344f8dcce47336d3bff28da5cb9f5a71fd26e54c4229e9c0bf943077826d72c68e7570804b1992646641d79f8ac1b0fe157b7e12c70413d9625e22","priv":"76e0ffd8727768a428fef6d1e4186459d6b3664fec801ec542608c955dd8974c","pub":"02c0fb2dacc13de0d29fa26144d0974f90b97ed706c16ccdfac02eafbadf9e4e0e","addr":"e28e2564870c7fd74244b111e188dc82c27755da"},{"mnemonic":"evoke example emotion suggest apology uniform giant empower future surround pizza scout","master":"ae3bdaf7acb6660fd151ed30d5d299f82556bae13873f6cd9e65111d991b4d00","seed":"840044591bf305fed33beea796f2c5a8ef72a5005797762ceb8528e1c0343696c02012ef81a8e964548af3293454fc6e3329059e40a95e9225fa254fa901f3fd","priv":"2ae6395640b6827f7b3af5d2a4a0f0df46d4c6c5bf28528eb3a896d60c80e0f3","pub":"0378059ff10a1d3e0ba1876622e9d45a9b75f01216bf14737a68b48138920e7adf","addr":"c1333d4372eb2dea3311829c10c6d12f17437cb9"},{"mnemonic":"endless come happy cause skate short list laugh amount marine glad pear","master":"c1643f331f86b0cbf7297eca946e44d0d1a1b3e704b6dfce6d53d9e9c6eeecfc","seed":"f3901b079e9987dffb0378a76f099e39349cd6abb9c59c23ac3f1cf90b988e82b71bcb3466b7a2f9e04e0b5b27bc945a3b4b714e0272184cb64e9b4f8d6a638b","priv":"e80f64abaa7b55214d94b2bea74d25a45bd6385bb2447fc53adc4be4820edffa","pub":"036d7029b6f83bbbd1238bfe9a2b8ee654ebc1b2ea9d00494345783342705ef7ae","addr":"56fc7b9a42b8dcf74932b92934321f2568606240"},{"mnemonic":"boring math photo park connect wash captain drum kingdom replace exist beef","master":"4853a21045f669f43eddd0df88100e473320d2f76641ce5f9d010d654f4896c9","seed":"65e6412f40852556186217c0ffddd4291b77651f8568d97434f1ce3bafd4784642d9eda0c401f9ec57ffc80c161832afd43ab89080fecdb8d6a2570b27b2f0a1","priv":"67f6f9aed318eaecf6e80b3a89748900f3dad77502893e133024616c15418799","pub":"02b0f15eaa2f0b9c09a03280c9689aad73e3e60e6c971ada22b9352cf381d9a7ea","addr":"741b1795cdbffea0b144b22ead2d466413bc232e"},{"mnemonic":"true also hockey holiday increase humor main lonely invest modify penalty soft","master":"c1716c4c6563885c995c00990cedcf3c90734ec9cd0bcfa327b19349762d1bd1","seed":"e192cb10ec4d6813342e8ae74c60ecba75c8f9f23cd60a92c8abc44211fbabe82f4f11e30bf68bd447c8f0147be7ff9ee9b64cb8c44ac8697f2bd1ba886f8427","priv":"f72b0a757b8ceb4bb80b47704eefcb5e0448a9bcfb7385fa3b6492628c36f2a8","pub":"020584eefaf032c19e853bdaad1d1bb8cea4001b8d5bc919d888b1cd55f6e88b04","addr":"98ff8a4e963a8e8cb4a09e10a83cfb704abf92f7"},{"mnemonic":"inmate mistake detail main sugar find maximum crack soup tumble helmet caught","master":"9b6e9657a31f9baf6f303b2df638d84e549fc35e23f4cd7b8b96ba608c474657","seed":"fea14199acf507de04127191e47dc5d20d60ff473d5aa600ab697b7854a7351bddfc24d99057671273b62111990d5bb6f0088af026b38448609d3a4ac8f58b74","priv":"2800c0aa8490524c5add4d3a2def895d8d54e9608a05fd21a7bb5373f594999e","pub":"03d49899c17ac5c0a8c3720c1a9593950d2a8a591c8a8fc24812d198ec1931b5a9","addr":"e198b4a329be8be7f67e4c7d63bdeedf9ad5b45b"},{"mnemonic":"embody ocean catalog shrug valve extra potato subway casino father denial oven","master":"a24ea5416ed8d137670224056db9656e8c1a70f8e602bf6a49cd2f7e6968fc5a","seed":"447121225f8095e806b284e249c1625d925999fed396dcd7c36d9fbff5339659530fe2df0760a9d1d15dad32e1a4c1577c518bbb378272b305434d138e748831","priv":"548afb052cd083e9504a6d602614d085c7a20f37556030550d13619cc39241c8","pub":"0370f25b9cfe827ca110760fd13eea09082573b534411d1719a12fbc9867982e4b","addr":"e6abb5bdb479ce55759bbe1d0331db6046f1aabc"},{"mnemonic":"brisk present attend rib envelope keen mosquito athlete guess ginger budget interest","master":"8e34652bc5848d8fa141e06899c93928c5bcbfac5e1daa60c77af837d7771b96","seed":"4305389939cf757a57a7ecdcdfcc09f7699c315704a3d23243968932386f01dfc8666b7dcfee1d7ae26a747907c85a949843ffc91c9abf3f98007d394b1ba2ca","priv":"65e554264f67ab679321ab7fa516b5988e6049847de929d6e1949032adf1452a","pub":"0358503d0c6dc10689a3705838741f20b83bd5496c4befd2403f69760533f7b28a","addr":"80b6d095ea92c035fdd56adbc4d38f209de13000"},{"mnemonic":"never gravity problem draw arena very panic patient clutch trick calm topple","master":"a6cf02c1407405402557a745a96019f2516fd7ed03677871da922282358b23ab","seed":"ea44a019240e09c4c642351a7aa04625c309102032b9f77ecefb4d33c25f31179fc52c300b4a2e57603c08b5ecb77600bf9f4f9fbdb07cb0dc7e822f709ba7f6","priv":"38ac40ab37d588c0b7ed4a6f4adb378c9e1a6d8a3cb220853dd56abd7327df4b","pub":"039f5f8a5513c74284314c5c5775ed39c77ec9081b978a3b096af6670630046730","addr":"c6a7dfac1a85311dfb3a3c6191a6124ce8ba39dc"},{"mnemonic":"aerobic slush coffee volcano tip speak across evolve nothing deputy limb arrive","master":"d0b24358e5a1e4cb2fcfbb10d9b32330e02be92f3397e70c8a81b04f065958b8","seed":"927a69f86c0f796ef2a6f89698ebcc6c7d2df24672d1c597c10f2b3dac8123808b46cd63e726eb6f1699b0790f14da3a82d9da2cf0fdd32a9b936c1763db0522","priv":"1d736f96fb08caa2ee8c9d4c1506bbdf235cd3ce076a976f8a7be2bd621e5a23","pub":"03f6d508014c45fedbd92677a8dc94a72a7ada2c893d0e2d508c4c9be4fbc669e0","addr":"7ccbeb5e8927c714b3d4c1047e66757bea289bf9"},{"mnemonic":"aspect glue bronze steel idea trend win collect ceiling puppy gas flat","master":"6320f492fc27070bdd7b99436ebfdb25f462b588f50915e5c79578613b53e41a","seed":"e0c9803520833b770aa6febcf2a0aaaeaafa6d39400141908c6577d99ff4ff26062451a4f1b2ed4dd91eafa345f7efa1d565fa101cf0ded88188e9d07ce62e5f","priv":"f87d3a46e925d395a8c4539469e0474cfc0bbed8005b50d539a28c85e3a44a28","pub":"03343c7d2cf83e568ea0c9b92e766c6e021d4a95ccf169c2c9d085693490d66f0d","addr":"6dba7380eb165ea86e2b07e30c5fe1022e046da7"},{"mnemonic":"curve better narrow reopen vocal gossip fall tornado fossil scrap goddess direct","master":"3fed34f65702bb4cd41a309cf81ae4a8c13b569e1de5420103bea9cb264a0ff5","seed":"c3f0c08138f32640b3fa1e6d9fde51163aab66318a7709933339874fe8bad22e75f6c19004af5196fe84348a1f3eaa37add1b645a320acf8a1fda40fd788b428","priv":"c99eb1a2f56c8ccc3ee2d2bdd3d849b6a60e1e82200f72e55d236ef1b0a9fcc6","pub":"028c3c8e1902ee965f55211362b5277748a5da54b43f0807a216581e6d686158df","addr":"507e551fa72ce7e9da2b19f4258c2ae79793aa2c"},{"mnemonic":"insane screen heavy sphere turn drink direct exhibit turn pattern series pitch","master":"b060bffb238a046de32305be06a806093f62fd0d52d1ff5b44b70ad45f502996","seed":"0f75c0f282ec504aefabcc1cdfea3e4166b4f6d4782771a905683e26b05dd5603178cc3fde6fe4febba6542350b15a3c393927ef1e371ec450af6ae6f4ed5a5d","priv":"3f590738a71a45fb5f111181747b44e342212ad15350db1d3ca475b9ef4914f5","pub":"02e50487e89882de6fe3ff87c7b12542a8a6a8a8cd2b4a08be5071aab04b2d461b","addr":"66284b62f4b7f506c6aa0f935d034b00f35fe66d"},{"mnemonic":"answer mobile swim shrimp jewel smile security shy decade sign physical width","master":"64cb57bff4e190f89d2d7564be94cfd1efa0014ef403cedc6946eb52a4a78813","seed":"3f645e90cbdf7eb6aed9afb802fa22f1c0baf57a79c813fe21478a7f2d658dc83c3498c75b0ee4e01a02cb11609473782065c7656083d7986df7bcb320603691","priv":"12c7e6691ffe251287754234d7b98747f12183b5535be6c886f86268b28e9175","pub":"0375b4071b801b389cbc66de9443623ea5b86d310297369305d869e885e187a0c4","addr":"b6fee98515f241c4ac41fd1382a1d7211dff3af0"},{"mnemonic":"match car rice essence try reopen wrist party choice creek inner comic","master":"60b8c48a8c8cb2d68a92559d1ead30a2cac313df4f5a84f94d0b64a3d5569047","seed":"17a91ddd485e6becbb822434a723c5143a11aaedbe9275b36080f92303fb3ef4d934abc5d36bc51b35946a4a683f932373e4a3276feb0393c499a961b78fc18e","priv":"1d9e0692e0c3e8d06606423fd6fe3d336b893c13b38ae3339aa3d7635e2c0046","pub":"039de765de0080a12871f7a278fd27a21ff6052d864f36a01aab4895a3e20d13ef","addr":"6a1216c843cdbe2010e5f024e265b31aa01592bb"},{"mnemonic":"leopard garlic permit menu opinion kick clinic upper start vote truth okay","master":"9db65a69d3ee0bc07c5ee34244faa0f6e8008c51c5372ccad6b9d54497c27f94","seed":"f125a9285412d9aab52baf0045d628d41e870814cc1ee92746d0cd0fe955bd30e3f5519521c6c7d172d07d53f318cacfc5b9d4b0a4e508f9a1056526df594283","priv":"da4acc9d2c281a03f904b42962e021401602b65c815b9659bc4a344f6f35e934","pub":"02744a41865188a5b3a37032369fa4ef214dd2ad836a35dc738b501736806b6606","addr":"fd86381be60f3ed78fc53abf84a8652b3c84b7b8"},{"mnemonic":"vote divert tower history staff finish lyrics empty bless alien walnut hub","master":"10f25de189ec007f9caa97230456a55ae87a807178e8cf23e84f761ec7c69cb1","seed":"ec42f0f2043a01fa768a6c5e889bdc706747abae60609511755f21b7798b7e3c476d38d0b2894f2519f2fad6e279d77a04e1ffa864c9059697da274b32bf3b88","priv":"4073cbb35009f9e7ad4bb18a0c3c7178ece1b9e07c9df1d595f5142c51a92bb4","pub":"0340a0d2e43896e6cfc4d0a7ff49afb1ac28a5ba112af2882f86510865f84bb8ca","addr":"21e3b66a23dbeb25b3b0e2372e2fc7b64364ccee"},{"mnemonic":"debate between rent foster stove powder truth remain cancel pupil object romance","master":"aeb2d34623bef5822150858dfbc2c0c53986c363297e9c3fe1ea64613c6701c2","seed":"c95a64fd29b7b9f15d9077e6a67a8f754bfa55bb952ee35ab94ca001caaec42b45ea2ae7223fd10492dfb02604fbb87de28b4202c49f72be52b7c55db0c8edf3","priv":"aaa218916efc3fd6ad5b948ffa4a3239984b06592c3e7809df3bce89b7c50465","pub":"0221a21829f0dbd3043b9a7645c182e835cd14c95ce9931c1e17284b9172b77130","addr":"853104a703410c5faf86381d5d2adb4f3254abee"},{"mnemonic":"dismiss fire ghost eyebrow salt report pupil include case east blind filter","master":"636ab989611298c004b6ceca6cf887c25d44df49260a8f755cc159d74fa971a3","seed":"5ac06b4e40354a95bcf97270de3db0ac2c9bcd44d1a83c40e9f2557490cf794dc8ec43e71d3dcf3f13e6a7202d84b835c124405a2dc79119288ebfd6352a1d1c","priv":"ce591b790083433d60e3678d5ae488f6033c8327b494789f457a4a137a99bb33","pub":"02607f14149c2272136dfac3ba34476203424fb3eab4282fa6e81c0bce0357e81e","addr":"9b38671825a0fa55e15833ac583fdaf3fcce3800"},{"mnemonic":"awkward slot wrestle sudden core clutch again pepper private reveal shift baby","master":"868dc5c7376cb2ccca274744e97e1b6f8390c1f2fb669862cb624fda1e8d9408","seed":"065aa8d9dbe5769799f29e7a99e663a6e622f0463c6b8093486728d2ff2e8dfe2d9d30e357ac6416515f043b9c96267f3b0de08f3b88c6bbe9486c3c78cdc44e","priv":"e6d6be1b041e0d52d576fa52f4987cc2c8490d86a49184a231703ca0f3d1fc16","pub":"0375e417a16b94bbb1e8cc1789535fac4abb78b466d2a354045da76405ceb8c35f","addr":"280ab94c67d7bddc3ee6a83571a2941b06c83676"},{"mnemonic":"whip tired like merge crush bird venture verify grow fiction provide coffee","master":"1a1a931d51b74af1b4ba19a4ad97b2d5d8c79396cac5d7dd7883d83d79fa81ae","seed":"a03ee9671bd73e717e93830e97dce58b4b5786321989e9f446daf96a6f328d70f5d5dcc4c40d21b7dd4b27aa6809be2a3aece2f3c2469923b8e3d112c899e3c6","priv":"8bc19d1e811c334e4417013c3c85a2040cea8a3b61c18bec0c7520bab9dc082d","pub":"0224c968015439332e83d1737b7429c7bcece458a00a94cc83aff758c5386e3878","addr":"a069c8ae758f12a39e86b2858865d95e953afc67"},{"mnemonic":"prefer benefit sound knock exact pull clutch cabbage local burden small report","master":"9d8ac0f2bbe4caafc11f2cbd9e644e62ec5f54003701453e9c08ebb5b252aa10","seed":"a6d48540efcd54706017c3a5c47773a4dbade3044bf445f8e811b2b2a1a584230d070c296fec26c59deeef37a7487926783fc96fc593c270e90d7da08766ed38","priv":"bb6d7a3a4717541b7e33146b75789999b5d763d14f0962fc43ac30193e711b38","pub":"0288eee81a2e81977eb56b163ea601470d99b9024b5b99db2af88228842fc6d4db","addr":"62c96ec870a47a2cd540758e27fb19fedb11d9da"},{"mnemonic":"case choice castle monkey awkward kid submit layer bargain reward ahead type","master":"c3da04cb84f0f98ea8723f2b6d7e6a3c83b30e5ab8e0ef75bff51ca0b4a00707","seed":"c65366f8af99f805aad4f87c4f73c074d1c99e69fe65bd2bb0ac6a1062bf9595051133c32d5abf4910cda20b9e8a8cd76e22e692e31c02f9327eb703602a9ff6","priv":"71a0279874cd44a61fffb0e65d7fcfa0f4f7c24db912f18f587d6393f8fc1154","pub":"0265ace29b8dffee0f31e6bb3e42f91d90eceb13357e6d324ee2cbc41528ec1c4c","addr":"cd772b14963185ed989f1085142b2b0ae2e5f980"},{"mnemonic":"educate meadow confirm subject tube urge guess black friend later cement spirit","master":"28cd56e6a857ac35c617c4665c143583e0626dffdd7a5e0ea55ed75215bc45e4","seed":"bec29b984cb4df491eb1154fb2717662606fa63742febe91e10d19057c9134b4d4b8677ae23e006b450d6d485a67ae09a9c34fcf8cee5b22be821dab855cfba9","priv":"fc3c5da684c39ac6ae5a91a3b94f50680f6562187b5a138551d20149113d03f0","pub":"032eda5239cb98993519d44e7838c971f9bd8ef140da2fa4a95a70a2488f78f1ad","addr":"5a9adf7df64dd7f7e9e0d29b9fb90069e8230090"},{"mnemonic":"way butter chimney fantasy rebuild delay shoot toy ugly festival resemble promote","master":"599622e23b3db7ee9a6f8f95f5e39b2562170fbc4dc0d84b6869224b9304f134","seed":"a5e0489af660e70db67649c03622aa66b1a6c57d2593204cea859a146b1676893c94f4390740021a51a3a076b27239c7870db78ab7eea48da0a0177a10b8e16b","priv":"e16a619f8355c4cc276583b67fb2b2616d23d09557539fefbe915c6922e80ae4","pub":"021e6f57790a3250f24b6323cda9f648cd0b1907e5c7a81369d022748af8a9b0d1","addr":"9c7b9192469e256207f7758a906d0ab3c50e4fa2"},{"mnemonic":"sniff rely wine book guitar repeat civil elevator olympic wasp dumb often","master":"43a2904bc971e275f33f12109c2067877acb6b00cec32e3913725114b48bb2d1","seed":"cdb3853a0160f7ff9f3b6a9d10192c11ba3f74d45f4bdd4366c9153728105cee7e117de9e8b13be65d3a284fed6866ef4850898c9c2ac4821f55a9c6415f7e16","priv":"970e0aa6e521b0d938c41143fdd75983f5a315ab51fe0e2c79f5c37053e7dd70","pub":"0378b468aa83eb47cceddd2ec8eca4004a9e99ccca959ede92d9b03ce3e38d5099","addr":"9b285c714fbf2d0d9e39395b08d07e3eb87ed87d"},{"mnemonic":"salad print drop winner chicken despair bleak warm misery buyer clip glory","master":"77c5e3581d686b79e863b82f41e563fa5a487e11a782f609b4559ff5c52fa091","seed":"494e915c3897e9bbce29c8af192e7360865be489b38efb5f6484955a525d7120d7637921f7ce7cfe820fcc996c9d9d0edd76f8376a48549057267fc7193cd66e","priv":"a7e988c4a3e661ec230fb359e8f6f7b9593ef5bf33b9086c1460fabacd162600","pub":"02f91a2b6f0545a45ee7d50d6899de984dc0d29ebe6f75cdb3dd169c696daaa9ff","addr":"8bbb9c4b435d0f42ae033e2819a600ab49f3a21d"},{"mnemonic":"inside alone salt borrow fuel stereo toast hotel want arm happy marine","master":"0bbbbf5948912d5e7243baff26886acf316b6ce9f450ee0d60d262b568200400","seed":"afbec9326da69fa938e71403cac67aece539c5fe1156d34ec737531b6ca38b68e60529d589f887ae24899ed8ae53b9f8329f64d84fb62c95a7cfcad45e83f6c1","priv":"8e2532f0440ecb83316645940e29d0b522adc421fb9aa49a8016b6bb1ad34e16","pub":"030de4b35fe61c0fc2fb4fd295a9352e98c7080cc99a6f70d6f64229745c161be1","addr":"519f731ed0412ac24588381879f050bfa9b01591"},{"mnemonic":"cousin drip gap gift ozone omit road parent square lawn crucial color","master":"742d494238d59034ac2026b9a94ad7cf75df5e1b481de734c440a8507e2236a8","seed":"82a0149396a6cadb670d7286506e1a0fbdd771751b39562eee0531d1a2353d29229940395cfb0e00fa1a6d26c9d117039d2a1738ffc93b34161e29de73ee41ca","priv":"aa04e7953be44feea3ddf077d01644f5b4f1eb85fa89521dafe85c341896104d","pub":"02f0d80a4cef0f71606ef476aa04ccd34182bc12b0c45708b0aac49fc2781fdd35","addr":"4a2358c67e4faad28e0d50066a9da25912c1cc57"},{"mnemonic":"list power fresh cricket must expire globe noble park eternal tongue thought","master":"c5210503dee7e7530a84ebb0ca5ca9f15670dcf987e82d67ab2213ae76275b95","seed":"7e482fcbe082d1e9520fa44c8ad117f4d2fad839c8556ea3aa4096a7b940009021611938b4cd2cd82434f5ea37afb4dfdc3548af496f0afad91bfab3117b241b","priv":"c14825a7bf41e5daf44cd9917f33c682da9fce939bab16421bd7dca1e04644a9","pub":"029a20080d20312ead4612ee0e9cb5a2d641ab929865cfb19c3234c838e6f75c44","addr":"750b5d9c00adb243177506688d9bf4943a3ff666"},{"mnemonic":"bless goat worth boil street wing quality visit honey couple upon sheriff","master":"c66453fb857a3deb4ff276dafe0437ba6dcecdcfa67b095053a060f9d5e67c26","seed":"b29cfcf2aaa980c88ae8e0b151601e40ccd6dceda39b4ae324d6d906bdd3342db7ab0f20ae75c1f1b424bac7b679b252532b4d5990d36d91f7612120a5c22b25","priv":"dd96f23418a459bfe23f676db88839e63d1bce7ab58b76d28e494abb1da9616b","pub":"027f81c68bec50476477e5d5524919b7e40509818a16da7724c62de26f23fc2d65","addr":"8856e5d456716486cc794be572454bf41f013404"},{"mnemonic":"slogan outside park during produce key meadow cricket glow choose pass tree","master":"4d6772450ecb47b86c562d5accee0f78c09b182ffe324fe0078fd324474f94f8","seed":"a050602af53f0857804abe575f05a664c292abe43782589fbee0aafbb9654988b6a46ac26d93ba14166d9c6f887dcc1693c2aab5a782f4277c0f153e3572936d","priv":"92918d979c61e8c6a256548502714cdb0094ab6fbc364891bc094bdee708357c","pub":"03dddebad5131d93de5078fad3a380a717f2d2dcb65743f05a84dcf7f29a26f9c4","addr":"0c34fd5317283be4b9ae5a953f539028a5f201ba"},{"mnemonic":"coil burger alpha grow lyrics check page spirit sea mention course fame","master":"9b4a2e05f533427551d7e44ccef49057b2fa0ea57a5890480133a8cad67319fa","seed":"013af1c7f10ada279b632bcaf0211006d13e62165646ad3af69da3b60f044ce62e9bdc7c1c6758da037664f18f1a1189683db16fc2ed39192a7737154984f417","priv":"1a9a114d594bfc3e41c3f507114ef3b872b70563fba390dae992317f67fa0241","pub":"03c5ce908d87792e067ca19d4fdfc15e3abda1993f3ad1f1c8bc5168c58c3c4e93","addr":"cb513df0682dc11374466aea70d7cd9a45d4fd44"},{"mnemonic":"napkin mystery powder birth crowd fun disorder bike lucky core dance punch","master":"8fb55d8de947c13497a83c9631a4fe9b0b491cca2743a6a056214c1daf5cd87d","seed":"f8c5fa5fb7581ae597edbf214a2755ac2bdd58dda03927c21c983b545674de67d69e258a196ef36e3f3e319863a54b521ee1e23807df9f2432b5004b563c2509","priv":"3846cab8eaa4af163f79dc83e5968ce0a59b7cc2f6f725767f70fc1780c00599","pub":"0399eacd20a2a7426a0946fba205891d22fbc041d264372c6bc981c3e7200995ab","addr":"3fc8f92413e731f59ea2768ca40393a92aa8dbca"},{"mnemonic":"sock real audit mind page price rocket home economy glove water rubber","master":"205d5de977b27ef90aa092c70456b516aedb62bd164fac4e4ff638be56d9b9cc","seed":"129afead267c2a9556c3cd3618a29b659e98d651f52259acb1eb4ffbdd6e61d87ecc487123994fe4eec4f65808d9cab6228f8054f8ba68c59a6de8a1997bf420","priv":"94f20ab0cca31de6ed426a818e8cf11299b8112905d0bbdbed79de137337983c","pub":"02ebd561df3cbc137540c7b9bc0c919021d4c4765a9f602078b028e469dbae397a","addr":"0103fbf9c8f122fd4ac6635f9178154d66b619ad"},{"mnemonic":"option faculty depart orchard foam orient seminar detail castle warm pink pen","master":"90dc715ea43f91c4777eda4e9c1dfc9f909c2cc811b55575410d21c0a9fddf4d","seed":"94c306f3e3aa6e991b0f9a8d42af67d058bd2ef0ee233467ba0d23936bb0e982029a887e6b1f9bb9e537ace50e2235a9976dd79b03555cad90da5e73aa0516ea","priv":"ff6cdb1cd48968c64608ac08be92e28f9808fbaccda86c1f5fd6d905d49dcb5e","pub":"035162c7e9506539401c3a0c181643ca621f5abda005f6aa14792fbaf44b862edb","addr":"d724d1f5b4a987109f0c84cda0ed290d88e7c668"},{"mnemonic":"jacket goat equal source proof congress potato solution rival lend finish bulk","master":"cdef2991efb462f091fd3c4e092f8926a4f5e18d6013c5545224d3ecd8e61821","seed":"01e84e54b7faf2374a4b4bb4e56f07d8b13f0dbb0191c23fd41b4520c8123f26b526a463404ce264283c0f3d41c5927681b6fa388d9a91274fd693fa265fab69","priv":"feebee90172106d859d545187adc06732e188580754c96311d9acd825c1ec9f4","pub":"0305697df9f3fb6796d40145316d8f90ded12e8ca18a5956651ee96ab26e69001d","addr":"d0955fef013a29bc7666f1a4696eed57441e2633"},{"mnemonic":"canoe tiny raw account weasel fork still mechanic cricket address squirrel void","master":"9382c4fa09665993b8803f3cc92913c5564be40b63b1c19c81f8f9dd415ba83a","seed":"5c12270e9fa3ca2a008729b1d5fc1a8dfd52dcc6461969ae71d2f3fe04a7c59dae4faec17f84567afd7bab3c5934382ef3d8bc6dd6879fd3af22bbf30fa84486","priv":"9f1d4cffae3c7ce9fce5f987e1439167273c83b6b2dacf1a11ed66c6053c2091","pub":"030a2c97fc8aa57c7fcf7d21c29fbe00ca0866e58f64fa56a85cba811445e0ff78","addr":"48b6bf075dffc6f03e77c67b3f2f573cad8e28e9"},{"mnemonic":"topple recipe surround useless elephant fan gentle wall since street enough harvest","master":"353c700ba61c0b56bd7a3a65d29d53e17bf99abeec68fb79c747ab006592c331","seed":"9fcd29b6b00decb8c8e2a14d5695941854cb391bc25351d7030587a09f64e92bb409c4bb7429329504c19c7619212c731216fd5568dad8e2a1330fbe6efebc7f","priv":"c900c7134a5b92a2a0d3bb0c117c08dbd67f47f7562cf330d619aa3c64b7ab6e","pub":"03e60ac1d0a9ea441a821a780d894ccae6ffacc207ab39ff905122d435acb17a31","addr":"4202687424a7c883cb1dd96353e7dc4697f35f3d"},{"mnemonic":"any myself dizzy magnet hand drift garbage reopen fiber great stuff burger","master":"74aeb0c2e7a7655668238f6a090ce3657def8df96d7af744ddc52d4900451a6e","seed":"0e0a18cbadc5ab76ef4194f7eb069f266ae34c854933b3fa9603b4fa39dedcf219d73e3b283e08a067fc994d46bc59e1c42c18a6a5609111b8fa690edbcf5d01","priv":"f426009813fdcee2b4cd38966e6214f9559426705621ca8b862d2a4cacbbcd4b","pub":"03b75491e3a05b32aff6972e720bd694ef496f6a753ae309cabf4e9b5adc2fa6f9","addr":"5e8c4290a5ab9cb6af1addd261ef37ebd0e6bdf5"},{"mnemonic":"spirit draft dilemma cause main admit thank slide barely diary humble enroll","master":"cd538c907349401ba6605eb1ca7923df44a30a049d5cb9d5a42f0f66a5cc5f29","seed":"baab841c07bf90c8b1bb82c56e355fd6de5a2c93e86f0f804a897ff9c391712d2ec5281582ec15337aadf1f0e835a8c98c42e86a4869e0e1ec47c063fd19f04d","priv":"cacbe0003d96c8263f09f328663ab1b5c74cd6635504b778ebf2d7d30dbe524c","pub":"03e71d9a3ca15f3d481ceeccafe14e6ce1214cf854aa245bdbe28e2b27d2d40353","addr":"f4b073ca68bc00077027a2793e7d6a24dc4b9434"},{"mnemonic":"state subway clip baby novel broken stand soldier among fringe track wrap","master":"0fc4edec9e5891d61e74dd1ee6b52f9601010cbf2bb8949c1d38339ec428bc88","seed":"46ff0c2553e5494666b6de0fd8fe734a8bf523bf6953dbe8622c66c7e9645670624f85a3ef2e9d090e9b153cb5923460cc1975c481a5c2868e51cddd15a9ca35","priv":"4f92a517fe46051132e74178a69f94a2dcd9a1120a54e09188e7d243bc97db67","pub":"034c0b78b452dd0fe61464dd0a44facac7ba28f126fc2a60b82f82efb8cd153349","addr":"2da2b5a6ccff13b5281582aec90f4c9ef28293b2"},{"mnemonic":"nation shuffle siege easy birth motor also family infant siren upon warrior","master":"506af6e687482c47562e38ac6a41e46e2291d777fa0f7abe53ab698065f03f17","seed":"6a4cfce60d546e03f17f6d977ce6d9dec6f4cf8b6a85dfa3070a34ceaca022c5ca4c6f187f1c23d720078c41d540fd04c56bd5061efd027eafa9dd8e650e745a","priv":"b9354ed6da16a0cc9b4404d3226de88048b546f5a01375466aae09c53af3cbf6","pub":"034c3ef56d2471b16f17ecc3e1d8695e0b44057fc8ccf76625a271487781c735ef","addr":"41b9aff0432990ba791b76ebc13af27c634d4a51"},{"mnemonic":"snake manage joy opera creek dwarf wreck merge oval rule elite coin","master":"02a8c9db54ea6d54186726806f81935dcbf6b5fcb9e91d03ad618fbc9f9d3879","seed":"7d6db7e19c66ac1f54395a5a4f7d878e19c24e0cb720ab2a146e2502b4c6832efca2edc2d3f1351cdeefb53a53d66fe64455790fb687234381c017fcbf692265","priv":"76d273285aceb1d4686167749496ae591df991af93a8c29bd627747bb2dd811a","pub":"0208492167c3478e65f8a31f051961d2ac809faf7777dfa7296c54cc3639de71ff","addr":"b18dde1cccf8095ae14353ff4ea995b5beb01dc5"},{"mnemonic":"edge aspect sleep design jelly vapor car blame dad pizza own possible","master":"7d938db55ab464a9ca1e9bf65fb4de0e25addf0ee2e0faff2fcdccaf209de40e","seed":"2d2530b934297fdab1c193d6aa9b93eaa1ea353e776a8b89118b31273f93c2ae78d7b98f02ce1cdfb8465fec0a97b29b563764409813bb4b893a3683dc9d9bba","priv":"c183cb66c406d72e64eee84dcf330e61514028a82d56c56490c4aa09e26dd987","pub":"03e7b33c7123aea9ee99d349eec2603ec7c32c2863034fcb87df8399b73885c97a","addr":"2e8c251e27ee90d6b8f05fdb2c7c51f92b277f1b"},{"mnemonic":"cancel confirm rent key glow confirm indoor chaos flag curtain indoor float","master":"0b49f5cae01e50cc4c05bc466ad91d84ea13896d93d468f951666726de9ccf1a","seed":"aa4561254b44e01ec6b00048e4346754b6626000cfe8e566180a99cdf8739c0c76e16729ee4c73b055e7c59f5ad30abed0ecbc1499fed87ee75cf0cc89f9a087","priv":"7c4e98bcc55251dee796fe3960a8b842322c51da57fe5cbbccb997714392016b","pub":"02ffec93ac53e470bbdc2dfa89c2389a1db404ae6e57e2586b5e638e1397a85f00","addr":"c69d4ef8ebc35e8a418b00c7263295052191763c"},{"mnemonic":"become search judge nation inherit short history resist luxury moon garlic protect","master":"72a0a669e55a3058f1d20be19571673ad281e965667c6bb7afe83e3e89f0f30b","seed":"75518eca5861396c14bce066dadee8eb5f9a74e7099cde11cc9b0f1cb1fab1df87b5fbdfb675761868c81dc7dfc805bd2e425678b0a562447a6684160eaa6264","priv":"276b9a47745eb9266100e62f8ed8f8fa2ee3e42e36ef8e010109acbfb667c1ea","pub":"03a596424477e9bd2500b20cbd0290feb0d30b755562561c52973edf826bae3324","addr":"933df39b013756091a3455104d61244fd16085eb"},{"mnemonic":"profit execute broom clever wing noise crew purity steak assume april leaf","master":"bc7e3bda0564fd300d6f0033fd13d75f7bec7464ef692bc96f83e7ee9427c6ff","seed":"353344a63ebd9a6e78ded4cbf52a5f29a64cb7c1d90b001d764f5f4fa419f569181c07f8bcca22117c970f65d6f9c06b44e934ad21257e0f1bb500f8a26db987","priv":"9120e0b2f502a6b5b5804fb4eece7754ed92a59fe482a7a1b4190213dfb60457","pub":"025f809c0f6a054c4b875c7bce8791f23cc9daa6a85558d6cd48818f29d6b978aa","addr":"f25a6479cee5506bb53b4b06fb326a508ca77abf"},{"mnemonic":"menu library ten glass coral taxi prevent learn pelican garden magic busy","master":"7f4687dad9ba781a99edc31d78a2c68875f40afced8adc8a66d55efd3f68c169","seed":"607827fdd6fb239229b116e73be3993a6596a09cabfd19dfb9b03482d052568c5443f4572393b0e9d460a05832c5fc41e811311d9bb501c43ec75e234c61785d","priv":"5605ca7fee44c088165aa3474327c53dcc13ffc73d8b4787a8b0dcdcd7fdbf3d","pub":"024d754ca81f064cf6dae96fd1344cab8e917e46ec639f677eea33a21bb34462c9","addr":"663ae3370a5b68058dfb1b2efa62f4a2222b3a89"},{"mnemonic":"green useful pair bulk excuse mixed train talk genre inspire much eyebrow","master":"318169a8d80848ddaaff93bd0fc68b1282aa8f5e6f058044de6ff82c62446005","seed":"2095e4cf4ec5ea142d9300cf431e47c6ad401ab1693a6518d5cf7950d1d5d7e0c6feede5a29b3721924074ccb527cb962ddc5745b46b794dddb4ccfdf31ff1fc","priv":"e9c336d9e59b1f4c822899ec39d256174521097060db24f305e3d4c3b12c35c4","pub":"03f44d7d4269f3aa14466483d80ad483af1307387170f563222e843c554f215b00","addr":"359955417cbda69e538cc001d5aca0bc59a077f2"},{"mnemonic":"follow half desert universe canal guide pony two fuel nuclear pull tag","master":"1f3ffb60e2293ecf146f414b28ca6a81dc6768c34450f2907eeca2851ebd92b8","seed":"e692e2810049aeeb25672c3d07a411940a7a7308e9a2fed2a67210d14dbc1de2258edba62437cdef1f913cbc65cc8040bd52f601c2edc51cc7d4744dc1781147","priv":"3534e3fc0a973dc314ff3610ff02c07a1a9e5f2a2003f8ce754c691acf172565","pub":"03e7f0b65a215a8d78831f05f10db86874dd0d900059bcbd64d83d08b05d8a5f7a","addr":"dd74030f9d82c0c40d2798e731b7c5eec61a0213"},{"mnemonic":"enjoy chief later rebel avoid emotion kid reward find patrol leopard destroy","master":"0c8eadc9ddd4cfe9b2c1759ed1372c513bd5226c1aa4afea02c8273d226182c5","seed":"d522815571acf5953d4bf6894c9bb5274e876a5ecb13310dc3db73f2d55544174d744cbc7d63a6ea07c8b7bf8bdcbcfe161ac57dc0ee488ed9fbe0d21a070d95","priv":"92e9da2b0ffdfca29c83f64a685f6f512eb291b5b130c4c5c506bf713016859e","pub":"036161fd5b9ff9bafb22e61860d1d3130e007839939eb3f609352bc73376552d17","addr":"015b10da504e82eaa290f2f5057a2581db032f51"},{"mnemonic":"giggle medal hat isolate congress else guitar below chase federal absent photo","master":"eb8a28df4360243f9dac597fa92de914aae4133af8f3a18c2506f2fcdaf4945b","seed":"95e8d77d1709418b4ac0b8cbafa302e2019644eedfbe52233ba988b55f5451781583ecaa8b1be51ae18e17ee5bbb35d3826302701588555dfc8c851844161acc","priv":"35da7e9dd8200ed89f461c484e63ff3ab68a9b1cb162bbc3331394f4f2ab8793","pub":"02bb24e03a89e6a6a7d318effa8ab645c46e5dcc4f25c3e4d75308144b5d2a29c2","addr":"2c271833daadd196147eea05df28dc41314a27ff"},{"mnemonic":"use protect bag nut fault off absurd involve ramp cereal symptom biology","master":"0f5a77192d1a941ac59a41773ea7d6b4e87295f4f82fb0f43c5f12d605afd56f","seed":"7d74703c2442bef350254d3dce2303a8a56fe4c96e4ff80ed57756dd7b8266e566ea2cbc3abba9c724deb9c45fe4cbd6a8c8bcc4bcfea2665e5193b781aea933","priv":"18c64949d8fb6fd392fb4846c119eb71a6021cc1c22991706fb776e8843a381b","pub":"02b94512126ed2d6412873f61bf16592f02df176cdd4c29fcd70085fe3d03127f9","addr":"15e94aeca2bbd591e337d57152663e25bc094747"},{"mnemonic":"tool twist jaguar excite borrow social sustain normal echo fork alley hybrid","master":"d6c9dbbbe44afa97a5f6365066a11a8fff48793d4c6720ecc419bfbb81329202","seed":"164785fe64846a802a9c134d094447035eaaa6cef2eec9d5fea9aa74d333ab31433c7cfe4b712b6a3b04048d239101a8dae5cb4ed37699658725bc2186ffbe41","priv":"cc5c6aba1301195af2626001e3d19660043377c75e7990063aa45ebbd30ab266","pub":"02ed0554dd8861043aab2105d7dbc83809193c59952e829421f7b9b6e9e56d6f0e","addr":"7db5745b47c147e40ea9fa2cf54488974d0bbc4b"},{"mnemonic":"approve bright target voice relax control knife again special future anchor crystal","master":"332ed66acc5c24c6a19c450775329c946197872435d77b0ea594d4632adb04eb","seed":"da2c0f3433cdb37ff151465470bad3b227114c46ddb025542133b4c10d942bce6cd34726c85e638fa82c4295d8fe93959069d35253ee528fb1724be1d95447f1","priv":"41a2cdb57b5cf352256bf9c2b155016160c7eeeaaa5a3ab2f06cd1df3e4bd695","pub":"02e76d02ff3fc76c21a995add6962e08bddec4abe23994668770d6cfd02cb82f42","addr":"39dcdc76bbd5c2ad8821cc5df8e816c7293a82b3"},{"mnemonic":"like wet pig pause steak name tornado else limb february secret subject","master":"e7dea9fa8e88520065302d4227d84a3d4226aac4b7c04bc78dc7e68efed73002","seed":"3926c7749d953ea66414c369fbe3f26a7a3f442ca98a277dfb362eb74432cbee32e44a6174f1e3fd16aead63e798c894d88ef260747de219c1e8631d800c13c1","priv":"804cc7215bdd8073b9c7f8e1ea2648724ec3e2593f1c2213875b6e4022513ae7","pub":"02770a43f589045b52ee29065b2cbae37ff65a0ace98c88531b4cf88c94c3f977d","addr":"cf82c749e61e9961ab72a76cbd3f71e0c5a46221"},{"mnemonic":"memory core ice box board flee ivory apology acid warm sugar resist","master":"4ae1d18a2c3cdc0c4b383d20846866f1a2ecb799e7d2c5c125e81c30856a2bfd","seed":"5922aa04496cda9a17e2f474805f095fa2bb70cce0857dcf92acc7737af2978145cdad0aefcf201fcb5aa2666a136b2eeffddb5476d9d49c0cf0d76d14bb332b","priv":"fde667c98a06017967b9169dc380a7393797486d07bba6575629f0661465a67a","pub":"03f8e990fabeba27ea70082b69628f95e5b86cedc033578426995bc1358949466c","addr":"efcaf3eebd6ec30c44fef92eb59327758eee3334"},{"mnemonic":"vintage rocket today version chair avoid mean play decade sport frequent magnet","master":"d167f9af9105ff115790c4d31ca48e4ce5cb3b571b4596b8ee78be5a6290e3c8","seed":"af58c0eb0e62201b926ab4c04d67b942f6ff40147ccdccc02a3df295fe69ca661b2a23fd2cc0f9148c4e92165ca9725014ff0abe5cb7acaeb513cdda359dced1","priv":"33b248b4a292ff6f26455859924eeb646290cd54a2cf587c5527e2f432fcd6d4","pub":"039802bdb2bedaabe4201344c1e9276d1981f403151e2cf179e4cd13861a54d568","addr":"c9ed9bc2778a33e5712b90843f1b0f0252c5c3d6"},{"mnemonic":"crash lazy cruel match youth note deal rack gym robot work pioneer","master":"13a82f0a499ea45154151ad95d52c3f15d84436c21d734b5ea105c902f85559c","seed":"c10e386ea97bef67bd97e59c5da37442ffc968893fb80ade82097b87a76dec5ae128962a4d69737a31eba4f1606e030d4c85df6733dcbb03e209a4b7931660c2","priv":"eac145103c713225ce05ffb862cb921797f9f88d48628321162798117e37494d","pub":"0260d3fc9e0ef5e8c38e3de4da944d59cc575aa530dce9fe8d95fb8eb68d6a4bd6","addr":"07aa44afcad33d8abe6e83da72d6d556a3720924"},{"mnemonic":"distance desert squeeze eyebrow episode enough sorry gym still label mansion thunder","master":"0f686b29302ac0d5532794598b98cfba275e4fa3dd0bef15c0b0866bfa0c9c0c","seed":"9fb57b9bb255323d11b7479bc34dc706e42e6ae8bb3f3af212b0807ebc9fe56a90a36c92bd17eda435fd0ce87a0465cd10a371b44dfb2e1531c14c29cf8ba466","priv":"7a140972fd7e2499dab8e22a52b0cf79c33ef58d1c5df578e30515e627f044a7","pub":"02332ac4729e52ba3ff4344ca262726bb58595670057aa967451302bd19579e8e7","addr":"f7c0cab3704f9ba669e318d17e33b1b5a7b3ac3f"},{"mnemonic":"zebra useless blue insect radar century lumber clock daughter slight quote stadium","master":"1168c3de22b717bd3e840b4ac6334ea707764d25bbf7ac14cd5d63ab127fe2a5","seed":"df9f562a972569f8dde2ba35e53c97c536ca3bffbbdc990df8cdbca812747887904a4f983d661035de0b3a85677d0092edad32ef528c926bf31541ba63b8e019","priv":"282da5f2191001a4bdcdccbd0000317ce62b09c0a48626b4fc2b45da6d7873be","pub":"02790696da42d2b21cb031e9b77bf855e2f5a214f80cd05618181433eec02fefb7","addr":"68f483b9d998b9250d320c43278e423d0394e8cc"},{"mnemonic":"laptop pepper arrest tribe glad keep behind gravity ketchup scrub bottom parade","master":"06a978fb60c517a506d2d8fa17956f144d1a5d57c0c9567320d1b21b8e7871eb","seed":"38c05886932cf2bca3cb7732e92b4086ca0575db2deaa241a0c9295eb79d50765a4bd92a03b76255144f71bf6f197c4b5eb6e3de8dd6e6ddf6d15ad18c90de35","priv":"62c37a4349e0d4edeb293e50adfac737ce73e3e0370439c561d117bd4ef23f19","pub":"027d978c9355669fab1ac4db17cf12a103f7501ca2011e022110d5b4398810039a","addr":"6e0cc4997d42b970855685f8c9a196b97b2d5ace"},{"mnemonic":"alpha slogan usage lemon cancel cruise rice crazy laptop donate city fade","master":"e3bed02bc801909cdfb1c65b6648f4df19b8927199e3d0f069f6713b13f10123","seed":"9b73467192fc857c552d60dc0223e3c4b604cb1cd50adcb61c9aa723d245e3ad44cba7f99f0f24fddd0c78b1bea41a86e682c9c482b115d575b9e3aa27f5650b","priv":"7b8d2c22c398e4a046da94656232cc75cfd6fc0e0f8191b673414383901b724c","pub":"0279989cb1f22fc08f871d023632a379d038bd9fa902a6e46f8bf0a780637b4efa","addr":"a4d3a5579aecfd9790dafc6b4e89972933c46d1e"},{"mnemonic":"chief runway cloth craft depth firm task ready credit multiply program smart","master":"d5d076659b0e0bb061736956cef361aa1a6a0ad6a337a6ccbf4b76a40184f405","seed":"8e60f22168de4f2a6c9db805a6485379d2facd7c99dc36981d0e209746766233d5d5012b03f8556195737bd71b88fc54eaea0f68e4fae4afc19c133f2ca5fba8","priv":"adee70b6b1dfc264606e0b1c848f7b5deb46de4af91c5eea9eac962dd085bb3c","pub":"0226458b01eb1e4f0d7901841662b2046f17e0945230a3b1b2d8a65aaf5ebdbe8c","addr":"c9d9042f15ecfb29595ed4769b1c858d1f627468"},{"mnemonic":"invest glory debris naive pill detail sister cattle physical favorite squeeze rice","master":"2ffaac06321f9aa3783155de5197448783583c027d8aa9d9b787d2a07b7a4c2a","seed":"3016cd4934eca835d3246cd7c05ff35a0ca5e3e0c4b74bc70aa31582a6da334c0f7e91458bc049ba3469a8aa7f216d27d44ec8ca4cc5f376ea366a38106c7fab","priv":"cfa4b9f12156ae24e632f318be54072149006db7a4a611403afa97c978351900","pub":"029e3e54ae265087ab8066bbb7e935af291b3ef5120b00f44019d9dfccec8a4e9b","addr":"3de09d0c1ee046365da74449b6c98ce3205e20e7"},{"mnemonic":"private alcohol loyal depend force sand twist couch beach report miracle abuse","master":"8354e18ddc5b38a6e26f9cfefbfd4b27ce3f65c91174c88143d947104ba91faa","seed":"507df1232f5cddcbee60de019cdba03e9337896ae2fa0b26855d48c34a9a2cdd1e93f2b66e965cf7666bf7c7ad11f00b1ff764b675a5c3df8a1a17b253cb9e54","priv":"d486cc9a23d56e1dd8d865ba042aa5cb9f8ba06107988e1a0d999b14da3b667b","pub":"03b75ef54ae8faa3f3565fd6301ba7a70114ddd184eefc74e716fa2e3c2df6c2af","addr":"2c82b93644c227bc66fc06c922ec1566c3e11c9f"},{"mnemonic":"memory achieve vault hip prevent category cactus aware venue dutch raccoon fresh","master":"16bffabbf3a08959dc9c1780781133e6aa096cef9d9542606c52e8ca2ea0230b","seed":"a4824f3efa0c730e3669acb08b1cadc25f3f63943983bc4f4f1505cba5c85959ec16c2cab98008d10e22f3ed6239e3182bd9b603ae1536755d222fc60f91419e","priv":"7c2b66b79e2e99ef0f794147aa93d3da8e62ebab7ebaad7813b586ea5db28f9e","pub":"03298a67eb59a27d636c2aff41d73ec658c87b136ea53a534ace18fabb76486dd7","addr":"89d5007339cb57fdb72ec629027583b8f3aaa5da"},{"mnemonic":"alien floor comfort six demand helmet light actor distance success buddy burden","master":"36ed5350c3672be815eb365f61ef0d0d42870b178aa34fa5c5b7397cbb7ddcf9","seed":"ff46b78794944b4372affad3f096339f8d9c03631335d9eaf4e4fe68a8fd9d58a6d6f37ba31cc06bf57c5b66aaad6ba64ed28ae4188195227fa07bfa587f2f1e","priv":"3bb1328f115390ade3c08de4f9672ae96bc3d5b783bd9d26d7e4ec12d5818b8f","pub":"02b37bccbe6c7173937b3af482d4a92280b670d715e2619fb1fc906973bcdd4d7e","addr":"935788847e1517096b9f31ccc2ac48c2e5a738ec"},{"mnemonic":"soul upgrade rebel wash hour gain lady side own double immense merry","master":"039c6373307aad9366dbaf9bc17e70ec1b5fedbe382b9bddc55ff606baadc0ae","seed":"37f9cc349c21182a3b34c66ae099de84bdcf30ed20160c7251f43f831279834dccb95745207defbae856c0a38dda3d7bb251b97cd2150c155ec64c680c82ba73","priv":"377f589beeb549285eee37d34e5ca85f4e00af8483027afb655e47ae05d1089d","pub":"0266f715310d9fee40c5c95da1b6a9a9aa51648df99326e29399b10e9cbcc51f7e","addr":"89a2ac362b8804981ecb6043bbea65587c997f97"},{"mnemonic":"stove pyramid vintage defy belt high have leave comic brass online caught","master":"eb9be6fc059732dd9eff612f2e4ed7121093f07889b87e8c66e103b83724e1f1","seed":"2537a9ac9dfe5c31c0f40c69c9fbf6a8ea186d2cd6c6d2134aea2f3ec2f28f5339fe623ff593da08857ee84193c54e204049009f8c86ded026a4cdca633b2b9a","priv":"a8f4ea6ba49c421a7d310b83bec05902cf2f2629a3845e390261c3917af3a17f","pub":"038a6d8d8947723f80f65dee0ef8579dea5678b67bd258ca591d0ce5d2ec060bb6","addr":"38d61629cc3e3ce7a614825cefb125ddec897b59"},{"mnemonic":"uncle seat rate acid ketchup frame marble limit demand exile wealth dinner","master":"fb1b8ac2f5bb56231fc93615bd8e25720818819d3df4ffcaf63dba0e7e7a0815","seed":"8e0bad11dc7784f19715ab90e8846e84155680027997fa0314fe32efdb3c026ae2918740d362744dff754e75b1d54050f5f02237cc4e15aad165ba10cc7b046f","priv":"cd20e39179c66285edeb6df646de54f3510f166bc1821349d779fcc103f13839","pub":"031a9529a2b5da261bb540f43b860b540490262b10aa09d419dc3b96d2e9aacc75","addr":"d1b6e238bc4a7e63e0a15f034deaf1a5b5161928"},{"mnemonic":"human benefit idea stone hospital misery warfare door goose unhappy crowd stadium","master":"b8b5781ae12ea6db767cc01d644cc52179363b72a7b67ee8d7d20fe8ffe4f41f","seed":"fc3f6e420f688e8553a2cf8d3a6a7198c5523aa6e3b00b3e1e4bc352288f0390951bcf698bafc12334522e04979fbcfb36f12fa789a85dada9909304de559193","priv":"ca41478acdd4f0413a843cec85b2abff69aa53b4f900da10918810b89127faa9","pub":"026096644513086624a2ba26daf7da0e4f5c7455bf852336416737fb72dc1137fc","addr":"e57448e2edf9d63574db45ae06510a521bd80522"},{"mnemonic":"violin cave ask subway session gaze settle pledge decorate alley swing evidence","master":"4c099f1692bd7137bf8b50e51d2f6fef0236f88bacfc4c87f83fcdd43a3a1aa8","seed":"2c3cb4cd88a4de52badeb41b1e3e1d61daf61369d5badc36601c4baad611eec459a0a1edb4046cc21ff50f396688ba6bd37fedf24b17ae447b6f7ce4b0a7e81e","priv":"5f1d6278c5d244334eb10d71e4e642017c7d3d63076507b7efc9c63c8c7e5df6","pub":"02c26860be7973c41ef183ad6ffb901d07bac225b5fae444df8abdc605c7a1efa0","addr":"fa055b86c6a1da4666ea4345e9d98ea32198805b"},{"mnemonic":"dance hip come square bread reduce ask riot shift twenty scrub derive","master":"964f2b5fb6c3f11f33ee1bc9db915d820834cb1ddf9cd35c17effe93ab3e3e14","seed":"bd4b3ee7b0042661b560cf39f8a9f8fdb70bb75c7482b09b296cf660e2b6360b52263cc38a1c546d0f935f0a156a36089975a7fd5a65ddbc960e4b6418e1d337","priv":"6f9b31f5247941f3a0e3954b05f77d68c469aaf25f0755293b1fdb17bcba6478","pub":"03a3cffd72d5e6360090e4a0bfc8e1c691add6690614ee5fcc7867780d686259de","addr":"95ed911acfc3d1332ecd9c8b93a4372a27911cb2"},{"mnemonic":"excess route notice shadow post business cram kind ripple odor enhance future","master":"ab1d6e993bb9b533e854f15591af9e8a74bd29d000d5c8e77b98e3e34e96fcd9","seed":"4ab45c5fa427c0c81853c3b5c2754ab1f54873b0bba3710204fe40ac69c13d21ae011fe9c835566db313947749dba53496f84709b71f4dba08a7db209922ee4a","priv":"98e0136920ca7d3844e7fe1cff54db7229be2412de8de831b94235e8ddc2696f","pub":"03714b295b752de7f1cefd195578fa7257d5dd8b47a39e584fc4d2637a8f730d1c","addr":"9019db50e3ad4d56ece94e7d5067b27a33400a4e"},{"mnemonic":"flag maid oil survey first force grant equal brick dog where strike","master":"85c3230463b78c924cb57ca637b5af3f5910d962861ead4b16af5de1b4be274b","seed":"6203eede1ed8164b3ab32049def751b55d82ba6807d97b3eb094b4e6327ce732a54de31a9fc6178266a4fa7e6452b004d89875694ec13ad05475d7ad86ec3241","priv":"1aff198e964909f87d5b15c1693e5d191b9444109a7ea4bb58952752623e77f2","pub":"03921265a585b1ec932828f58cbaea6ae709c7f2af0691ba3f2f0636286119bcca","addr":"7f38e5412e9011a5ca91fdae448bb8b15a6bc4bc"},{"mnemonic":"jaguar panic thought mimic voyage able inch pole vacuum twist velvet pulse","master":"f7ded49975e280cc791687730225a70a89c79f5245ca72a7e538295aac1ac710","seed":"52f058e84e0809ac44c37485ce9da088c1617f05e92553a073378a0a0b3c9cc95aabb6d1dd2c99d084b03afb98024f9381d958f6ee5f516baef2db97c493009c","priv":"615bd1f706f7a88d9816200f4c3085ee2c748f9a42b25b444393f8cf2b46191c","pub":"02635816dcc956bbd8d9d2ebe94fb117ca20907a238c99245a9635287404d30e78","addr":"78105acfd135889bff6f0f70c92c38e0eaad72dd"},{"mnemonic":"pond stairs still avocado rapid peasant direct debris spice cupboard pledge budget","master":"6b5a25d678b4fb67cfa80ca3ab21cd6bd554e5434c4fd362ddb01cb46bdbaff1","seed":"69d5e57322a46cecbfe1f895c1b22e9bf17d418a06b73d49e3fc83012ca2649818bce2310f1b195c5b4873d31d6e797c5edecb8f30377f5e638ba1b4ce2f3823","priv":"9aea611859425145441b6455a0ee206327c2de06e2d26974197873f2ae9366fb","pub":"0236498052412d5c5dc3ef0d195a2a537359fc44246fd9c8fb39478caf29e668cf","addr":"faeac1dc66f281714303d637666c09606504a227"},{"mnemonic":"december cram web moral spell comic tag lawn since helmet moment act","master":"ee67281243cf2f77274bdc4b91a2ff1e660197bbca2fb42d5aee60e6f55ab4ba","seed":"8052120f630a33ce44aba16f1807236b1330ffa6170f985c630532fdd2713aef0e1d681699c4f67a9b9a72fb0432335c243828bea29489c92d1b01d016257ef0","priv":"a98bf3a99fff927ec2b0f208bd8a3a586ccc2571fc6333c57f2f1b7c22d2c8f8","pub":"02743cd05cb536e2384da4e0f110fa4f807abdba3e5e25e426e32fc4b5c65f761e","addr":"a1f0b4bba0be62c6b2497826612303892ed77b05"},{"mnemonic":"basket tool pink steak antenna process accuse brown walk pretty only check","master":"ce30c7daae3e0a5293ece548d66f07852003afcc80874474f5a94eac4a00c928","seed":"9572350a5a22b4c0f95fb2ce61c1f5e5846a3c2fd6e4cdfb2aba0d05e04e5b67f0fb394521b73836bcd4555cdda44acf0ab7ba43b475795868a6056295967822","priv":"edcff07e74dc83738075605d76a0c6923dc475ab122da2789b5a195a421c354d","pub":"02c03e024e6f53a1676dccd7850cbb2bc1f6a9a85b1da7cf0ecbf1c653a60dae1e","addr":"ac3c8907bc31fe66155a47a37306ff7b75905133"},{"mnemonic":"since equal mobile pond island before crew boat clean behave climb good","master":"1d1eca07fe5058a9dd7b26d1afbf2f4f71acf1420dc4ce9d2e3959734c442f36","seed":"4167279cfd447453ee7f46328bc40b4961f814229cd72762af278cf56a8efb18211420cdba43ccb06dfdb207716390df9205fa880cc647bb48455f437ec8e4da","priv":"60622d64880831974cf62d8f65be9e4d89e6579e6e0f1e5351a10b7574f3615a","pub":"03ba031ce6dd8976cfb72a2121165ea4bc0a8cdb14082504a05a917de09bccda29","addr":"50203affa88d87f3b104e237058807366f33c1f2"},{"mnemonic":"inspire immune poet penalty remind mule crawl drill rare fork track creek","master":"7c581d1907fb46fc46e6e9b81d83fbae02a75a2ee50a8d723e24700b530ce917","seed":"3822ac35fca2e3b5904e3284deb5c178b7c64ada6d7dd31347ea302e76ecb46d4bf926158016b76106ca61ae068fdc594808a56aae5e39da7893592310c33d2f","priv":"6f87d364a299b42c40a641d121a255228b62884d6f2d09068a384f7c6b515831","pub":"03f217a49a2068b2807a4f0500a08dbc7bcba6ffd60b0fe3e4f381a089b74506f5","addr":"c4a20e80863522069f8059e91bb1a162a7af7356"},{"mnemonic":"inquiry exile okay attend enroll author forget essence script conduct apology rather","master":"609da212416c631e8701b1fcfda5c412e0758270daa7bc796ac1492045a93a5c","seed":"4a75975cb2852f8dea2ef90535307e0a0063985a1c2347db1edc25bb96dffbd880ae88e8e5a21e91b6c26cdc98673effdf0ca84f416a45950cbb0ec74cb7fbed","priv":"c2e4db33ed61ed9f7a2b1452515b971a1bb20dce3b07efeb9437fe6ed481c9b8","pub":"03fb6407710ca5408d137faa85f2837879c4b0f4df59182a3d5f002e49c34c3bc3","addr":"c5217c9cd9af8ceff8235b2d127ef1cea8e94e35"},{"mnemonic":"entire diary route emerge moment only lounge situate expose hurry hip mosquito","master":"a919ae0bb832affae8e5269efc47936b6bf3e487740f8bbd2c286866a2224762","seed":"e97e0456756e343a7d56b1edf7468419f8b431c6c850299b382d3d957fff7c48f86114eb5640aee13d245c2a34d390850ec43c427bfec555d40a489397376340","priv":"eff22ef90183b533c5267d9c19f29f7a6fc2c44b45dcfd4b440181b977087585","pub":"030cb4259aefba8429f5e3ab0009e080674e887748e51ba2e0a055d2df3bc17589","addr":"d5db282d076f9d474651970abe5d2e3fece873ed"},{"mnemonic":"ginger glad purity aware siege tornado seek orbit sniff spawn process surround","master":"5498d52a17868a0fb5f1d2416277fa1a4220ac3a498f18f15e750d1140c57f86","seed":"3674479b527c4f27b578f0609f800de86a46591eccef6d40d3ac4436ac8c92ff12659e1e404af552f1058e9f17e90efc160903fd985f5b8069c66c9f6708abc0","priv":"5fcf38e09f4a3665256644715fd606ab60d9cd62f4c22962ec94b6fc5fccdfc2","pub":"03da1b1b03fde4241b05adc19515eda3ea96febdd5ea0e8f82dcc7cd98f1b74029","addr":"1186fc924724531d8ccc9f9ffd49701e62056c52"},{"mnemonic":"laundry reform post update crime page snack another boil pet cement primary","master":"3b1c3ee0d63328bab055d691bd29179ce5abb933759fcf83912adb41ff1bd9c9","seed":"60771d2e964301990d7ce6de87becd62e65852a4da9b819ce3fe28d72ab0e4619445d934172c1fc9361d2176f4ccc8d5b9175f4e933fd5e9681d8e8b177fadf6","priv":"755dcf792c67ba8a9d8b0694d21fbd33c51fb7aea67f05d2c8b0f38093ffa7ef","pub":"037118c561ac7773ab212b899b57f5527b77577a39a4f413232c8e7c6a33f9091a","addr":"bc2e19256932b58fdbbe5ad809e30a3ab2b2685a"},{"mnemonic":"pool bean dilemma foster reveal renew exist bar sick spot bulb trim","master":"4d1399a0181de627ea555f388952dd5d2c7a7b83e1a618fe8b07b03c1bed18e3","seed":"d788888f57bc052bf0d35abf7be1175152aa607b901d1040f4a28c8cef343f0fed2031e3bc9e1eff77eeef4e024234466a55f70150388824d6fa10051133a464","priv":"00b7f71d77cf0d4e13e51403c92aa66ba543e9cfaecd810049d17794a4c0ded9","pub":"02319a6d654cb42a231f7d021e2cb7c9ea7624c37d6ee32b218d5ef79a31eaeb46","addr":"f6d78ff49d6f12b82e24bdd77bebb536566a39eb"},{"mnemonic":"poem leaf scrub bag bomb palace discover pear rhythm treat negative system","master":"4bbecc45fde87cb80a4cad7a4b08068265eb8c12d4ed36d1c9a9a7e5e73c39ac","seed":"efb6bca601760ffb2b183bd4cd2e84a864eda3bb4b8b1369095d3df69fa7ead0b8bfdf5a097f37bb4b1ccc452cb8935baa165f7ab039342af64e9e50bfd51b36","priv":"c4988f397df2821ee196f98e62e4a1542e53ca1e46f966a4d13c4e3e389d8937","pub":"038c8e4571f8f411827ba778340beb7bbc29fb47af998a852da29b4f1583d5c600","addr":"67b94e1d532cd8e42e5a74cbf20f7d079f42055f"},{"mnemonic":"punch twin village ostrich frame goose dance history valid mountain volume high","master":"f9ba8580f4d53e34d9bfd3b6a2e17c5d8987c879945df9bd20407d3f8144b108","seed":"07d40cd18ec6abbc351aa23172dfa6582ed83d5bb24d5cd830d7cefd23d8a2ea6272efc6686606e61507d5a793b7fa06f83bf73504a072e32a002750f5f240d0","priv":"10222b81cc386d25eaf5037fb8fbfa9c401c1d192fb715397f6636dd94e9db3d","pub":"038b04836ce19b454a0af260bc1271ec73f1a0998d8659e9cffe38fa5e4d696a77","addr":"55bd4a574aaa1be2c02aa2eb40254f8cdda7a682"},{"mnemonic":"ready embrace photo find orange curious essay pulse frozen earn wild travel","master":"361e9e44283fe7d3bab83395ecb8373dff5d0a4d60274695637cb02955523741","seed":"ab50c5ab74b1ebae85811108c372651ca8d275e7c2b5d0fec9f261966395482f311a76dd297f2d2997c6c59247807506ed20f524a32dff90637956cb7868aaed","priv":"1ffdff9fd05b67d22f10076595e0025800a8d60f022f2bd99ceeba93681372f4","pub":"03b168906d5b255a896509c8ecaac4a8141d22ebe005e6dfb2892f6f12970dba2f","addr":"a7d30e12ff906b2ca0c6df3fc68274e7e30725e1"},{"mnemonic":"pass paper cable blanket meadow talk govern admit busy base hold broccoli","master":"db0e45010140df4a4514284d7ba78ac7a5771ee15820856afb1d15a4e3b0af7a","seed":"521ec955279d92fae9dd8dd43162ee216798f4a0276a2c98b29dec8dec9bb26f17e6a49ce999ec55e061379166f25116c01b8cb48ded23c3b3087dbafbfc5371","priv":"b5bf00005304278d5e4aa792de142a6cb46bd6283ab02222de50cc2f01009e09","pub":"03c188a8581f09d9eb14252f8d1f5cebf1de8189526992889115c6edb1cd180090","addr":"0f8fe4fac4fd85d649d7e19d1773897aa6e75f43"},{"mnemonic":"weekend infant spin powder hurdle pupil disorder always excess unhappy price decide","master":"b1bec76f3cb15f82e5c9c65aa23d0871ec06a590a3823285a412ec9a243b1c1e","seed":"5a8d16dbd0586561cc81273ee320c6c3d51bd90bdf08119ec81596fcab24335193b33fdd621800daefb49e038ee079184e569b941ef5d839987dc1e24f578039","priv":"90ffc2ec625f528045a432ddae8d20017c9b1a883ed22ed403783e10801077e4","pub":"027d4213cf485f4eaf3ea06c61057f92ae8fde8362c3b2f4b167639b74153db673","addr":"c9b1073f122b5ebd155d4904cbc32da4281bed6d"},{"mnemonic":"agent seven dry cheese rhythm raise junior sorry spoil tag opera bench","master":"8cd8ddb8ad3f12fa347780c4614e38198a51c00bc61ecb572616382d6f8388ed","seed":"ad6641ad541b411261101e5f76036fcddd8af62de1966a3b9a1122edd1e6057e38fb5e129c86427a68590c87cf9410fc14ec08dff184742a54461c205018f43a","priv":"f15efc08c8a578f7035a672fb51c2f6929e169e5ff37802ae8b50f1664c025a4","pub":"039926cc43000431dab0f0f4818fa024ddcec0ffe9c483f8ec294cc863f5133574","addr":"89846353e3a3becad919620dae0a2d22d0533559"},{"mnemonic":"floor sting insane slice pistol blush follow muffin acid coral aim make","master":"f65fa0d49225f5f373eed6d7d6f9f8f73f80840c6027c3871645679e51f2dc81","seed":"8782d6395c27d8b9a3b0fe29e44093e5150c9b82bfcb6344e6134e954c1240cb33fe8c9489b3ad3117f5c112f02f0eecb0e30efa36db18b27003df5e542face0","priv":"de11f15f7cfb0038dc07ea2007019c17747e5138cd83b37ad30621c9f41b1799","pub":"02b662800bbc56c144f6b39773bfb4d496c9f1442900b59641aa94c6b50a783fa0","addr":"70b1ee56807b9191f77b1d18ddfd181677e91654"},{"mnemonic":"canal today stadium spell accuse cream chuckle method unfair regret sibling old","master":"90c0af3882fac84793812f44eacb1d4cf13b56863c70ccfd6866bbde1195036e","seed":"c1b4ea5bc074259d2f25ad7338b423c5ccd2083b60f0ecce88f7c5d4cb39806f2da873c05cd52729ee07512cba3af26f21354a3769350d5bdd10868ff46d8e28","priv":"9ff9156b1f137d20b486ea125515fd7a2f057145fa8313203606ead961ebed84","pub":"0225998b8535e9f2e269e86caeca1ed90a86414d8c449011ea2fd9a488b7097528","addr":"40f33af234da7de748b02a01687a5e60429ee07d"},{"mnemonic":"object sure already seat attitude great winner session cool addict direct popular","master":"86a35c7ab59d48a897f6b4a78221c8acd0850010a063ceb912488352fa19048f","seed":"fae4348ff7c42cb1ff8542bd19721823917037d1cb017ffaf64547be8ad4b296212d6e952b2af66db8541c7e881136aa76e17e4fed926064bd5edad8f25e0dcf","priv":"2df0f9c67615ca9370f8ab957db6ad6cbcff1b5353f745dd24125ad36d7c77c3","pub":"0367582dda754c5345514b2618d0844e83f8fb49ca39a70d00537c70c86b6519b9","addr":"128a4f8786a46bb7815e59abbcd85bffb526e953"},{"mnemonic":"sudden more spawn have pig observe embody title collect junior sing bronze","master":"c71aeb48c73d6ecef04597f248dfef9ebaab37e9df625a483db1e883a972a36f","seed":"eb1dcdc3ecd77652223ccccacb85a255f350028a843bed72ff96d4e3de5566f667af1d5fd48aed32d2e580f625bd258cdcf6760d1089ee3f9653375bb1139f9c","priv":"455da9b7df9d00ce53973439b23a26a75463c9ce0bdd73eb16a39e019d7786ae","pub":"0327c673e375a95e13ab6a940c18a35874331db2c0abb283736890b0ed1a09b79e","addr":"d173a47de381e714e3873d1e0ac05ef526b0eeec"},{"mnemonic":"world gown final mind dinosaur stamp unaware apology foot flavor hockey bamboo","master":"040827137019c4a9d29c1d65849cbac940ca0dcdac2ba8def0421c990c90e2e2","seed":"48c5532c17475f0a4d63d76daefe7cf21681b32cbbf4ad8cbb62b6fa872411fd2b8821f8f2ea97cd9004fe4585e5ecfa27ee6c46caab89145c3b0b4b7ef5c073","priv":"d66195156c08032f912a71128635b25750335aab186aec63ec9a83e9b24c55a6","pub":"022d8790106436a60a3b74d10fb07e06cb48b2b13ebfb81a608039d80e9d7c1e64","addr":"fa08eb0d89958302d67d4de8b99fe0c53ddebae7"},{"mnemonic":"bag bridge trip improve blanket machine asset boat mask flash vicious pig","master":"21df138f80902d1ee79948ca3836ecc29a0f9093b06a240b29ac7c3aab89750a","seed":"99cead310304d8ef58b23fd2b9ce7fb71386111ffda2f609898bd59289862b6f464ba261855b1bdbfad8f7ea25e43adce10f7386cb6cbb744ee05772b883d176","priv":"c82490739f0d969706299c3ecd89e4f47d0247471ad2d3f7ebba531b8d6804d4","pub":"03dfb5455095553fe24c1474c5a5dc0fb69aba612b79568486345f73fe27d36205","addr":"020c6ac4996d1c91b2b2894c426dc8e32b083fb2"},{"mnemonic":"auction okay cousin sick accuse steel limb staff tube gold hero add","master":"5bc8d22635bf6ce1494c820527e26a94c57f6987d6cdf6d40825138c3283e6c2","seed":"c7df0872664b4b4b0a7deeb3c26545380bc61fa3734a20a82c96e73707ae975b76b12f31da65e863040b2215c34a4e9f525ef38e555757a9e8a42a20af2f78de","priv":"0bc4a9bd3b88ad78c34a309183da9a0efe4d8e27d098282e3bb248cb960e018e","pub":"0200d5e1fe0707ff11dca2c30a0ac83bfa40ebbb7e51197993c6910312fe91d75c","addr":"72ada6e822ffed23ac5ff5147a22537b984bfca3"},{"mnemonic":"trip below tourist offer burden hungry later grain quantum universe service group","master":"7990e7b10c0c6bc95f45933e8f5be1e758e7b7b2ee39b8caa00e8ca50cc66855","seed":"a96ab2ab3fa2bc2547cb20cdb3e39eab2ce9dedb053277c7802bc0bdc4ba9d08a3860b48325c662de187c935419211bb64ca07448988f903cde04eea9f0f6e68","priv":"6d922bc8eef11400f93de7ce47b55d3e862ffece29fa666ba05c778ffde8d91f","pub":"032567a2ff9a50d1c4e6cc525dfb96da1edefa91fc09c32ddac3ad446056f1ad7c","addr":"abaf696230fd241bfed2c76a0452456bb608c17f"},{"mnemonic":"bacon together open trust hood detail liberty bean spread awkward antique minor","master":"b96abff8fade8664e35d68c78f7609f1c8553a02b80c81857583df0134513370","seed":"772590bec2194f5b552ffdb2eaad756555b22e979ef0463222af6711c53d77623ad9c34abe48b7389e67b10e56aae448e9d064e4be58c5d45c4de16ad56599e1","priv":"532a98d8be2812f88057a91510a20ed4e7fdcad022162e3d3dc14a34104859ce","pub":"020020a4aa457c2944b3c333141e9dccf1c500bb277b846d85a77141f69332a315","addr":"3b5c6eb43438c07d8591e7c4aabe8d4540490bd7"},{"mnemonic":"bulb jewel comic drop copy wreck unit engage meadow hurry acid thrive","master":"c0755ca5e91d4ec8f6dc7b2582d65dc70786a3ea67cd40dd68462ce13535ed61","seed":"e808525cb5c66bf4080ace7b3ff7d6454d07723ec23fa16fc0b3a346d7fdbf71dfe5f383c13d68de5b5f04cae47503ff352ae340700bcb75f2ed6f0eac3b7c5a","priv":"4f592a1d10867d00b28197be6207977e13c9fc551449d05be284642c43597132","pub":"035ec6120eeb601d6b3b444e066252a4c917cefda62c49c0ecd6384c1ca4db826e","addr":"35f84051b0a02090acd509fc801b21864c45ce91"},{"mnemonic":"devote guitar planet kick now above act sponsor account blouse divide horror","master":"1d5329254a9cffc9de60eaedb1735bc8b25c77142a9ea2098e8227ad289b967b","seed":"462b9b3d13f1b1e9e802525e3bd5e22f97a31b352240c9457c1f6d5f194c6e7b7bc37a4fd2607a27adbb77dd837b9114606c8dfc54d78a1a4c8f703889a2e50f","priv":"d5a648822e5c20ee1c56ac5b08a54e561a392d540d3e964499a5a970362c3829","pub":"0381ee04ec2cd440ee26d5a37c3775047e0215b2919736e092c2aaa7152ae448fa","addr":"daf4d242b80955a2269006d530ff6826f718fca8"},{"mnemonic":"youth error panic brisk panel hobby mimic nasty address little original sense","master":"57a151782b47da723e7bc39b13200bb9ee0c3621e839e179a92f99ced03d15ac","seed":"600441626b7035ce2b4e1a90a872ae2279cda57d8f8f44ae3c99edfd0e23ed4afb3e1f4e9b01eb5cba5cafff6a650f2d586d1f0ad85254cc99caa47abab30b4f","priv":"08030c2dd269b5b60f12ee6bb27aad68d3490ef128ca704f390e283ab608203e","pub":"03a38f69571f6187ce334833b798fc0d32065fef197f5812e4c392de54fce4bab1","addr":"02bbd2f05a3c4979db5ac72246d7e620e3edb769"},{"mnemonic":"age excuse wall torch dove enter movie almost build shock blame object","master":"cb4958fe22c8250f41998f6e869eb6cff240550af2db41d0b92e9bb64041469f","seed":"bd585927d17cba54ff5b2b63f2a98267d197ef07caf6a82b3dadc45bc5348d99dc7dac59e45561e55c3513a62ad1942ae2763168562c74ed808f1a59b32a64e3","priv":"7923cba208f6bc84ba7eb134836b96b69bf1f75330caea0be218df31885cbfb1","pub":"0369f14dcd228c164170d5187c21d092b4238386e0c8231a132cbe41e4ba315df1","addr":"93a1e4c78f24c08c48572169fa949001049a6528"},{"mnemonic":"expand shine stairs delay calm soldier deny volume whisper island topple cross","master":"0467b91a321c4326fec8f39cecfbb2d273e628837044815cab899f8debb66376","seed":"0597787fa9ed69ce29f6bfaddfbda091c7b35b6dfec6bcec23957e6a547819c320504afb3ed7a7c5636e4496271d2681891ecafcb9a93ec71bb7b5d9dd06c710","priv":"ab2422cc32992afafc497d2aaf8e4ffb193aa02a5574b0be59cca80566ae8a91","pub":"02348311d8c7310491aaa1f3bfba7945844cff5573ac8b5788872f594e20746830","addr":"a1d27d518ffacde5dcc9a10ade764cff42399996"},{"mnemonic":"sense palace seek enhance hold exotic sense pyramid program fuel deliver heart","master":"715d3a14fdee63848d94f9269d97fa562301f6899487a5ccc9d987c8eccad3ed","seed":"e80766a81744ba87d4faa9199a2b6d1b829256aadfc46f3b647be1788cdf324f8a4ec4ef52af07bef0d60ee090d3c2f45ebad582eb326b688366ebd7390df61a","priv":"7cd5560b3928e4048efe644e39bcc1eaa9e8b783c0f3f0ef5904e030bb6d63bb","pub":"03c7759ec461940a6a3f90b4380286aff6307c2ff6acc234df44aff978fdd7430c","addr":"0d43f6bbde0c5687561d8f5d457bfa78581b407e"},{"mnemonic":"poverty defy mistake begin dizzy behind annual olympic glad behave coin rhythm","master":"eb342d1dc891e285f0d1822af5e00ce3472b869c73102f87c008f73099448ab8","seed":"710a0f8ebbefb347f83eaf54d2977cd64e1f90d4f8de33c8ff041f807d64e5444707432877ffb4697e2e554d1e5bec48ff7428d13ed83433c4200b7aa6bd7c22","priv":"6c36c88b1168a478325ad77e220a77f10a2c8933fd72a2babbc918cd683cb265","pub":"027934c90cc3c75daf4971ccfc56f672fbe33f86c852f648afaf260989961be283","addr":"d60c6edc1bb9b47b0f2baeddeba2723e61aae00a"},{"mnemonic":"artefact vanish security tooth rail claim drive black push ocean special uphold","master":"08d1f1528ad6dd4424ca11825ac1b47111969f21b0285b3bfca9a2e28aef095b","seed":"add463ba53586dcf678b32e6285d40dc5502f91c3dd1128351380f52a28d08b9ba747c28aa85164b342e95b44c1ee03ce9c0d9029979f346ab6d9dc3a614f7bc","priv":"e22dff0eb96c0599766b81a0399e62589bf6e734003e45bbea048ac37c8c9bda","pub":"029954b4e87d373729575ca9b1606c566108753e12080de2739f64ea0a9b881ed7","addr":"0c670a5b8b1fe0a5e43d7efe0a905f67c5ae47c9"},{"mnemonic":"supreme correct virtual guess funny grocery assume dash blush rubber wage chaos","master":"09eb5b5fab562805b57ed0f1a96e66d56b8e132d885f39cc5d76094a4e169d91","seed":"994fbf31e1213b7c113ba0b47563afe37de2acab7bd17ee071c04b1616c6cb50d853bcd5203a9a635fab9dcaa07f0d9d4168a7303fdb53ef41cf5ff15db83704","priv":"1b56d4fd8c5fc994f22d4c7fc856aa18814f269c0f43fe65b52c914a186ec265","pub":"03941aa1d30a3122695e69b6a7f8c94edf030255255a33d82484f90c491dc77f1b","addr":"ebb17b37332f0079728e9de0f2b40951a233a9ac"},{"mnemonic":"pyramid insane eternal man arrange earth predict panther atom fashion claw present","master":"25ad3023a8597a1960b1e6411d75a821d86000ccb3e92a66646017f56dfe65b8","seed":"56231905c46f23f005085a4618005b1851055dc3f639f6b1169189c9bedf1bec6efa219631c333f0cc488e06a0b5babbd781071b7327dd8667bba0467b6630cf","priv":"0a4413be4769217c1f03bddca1fa921ec7935b473e9f13ab78f2b377c08198b6","pub":"02f4e8d8f9f165017e917b9128160fcc8232e03a7d4905583e60a76d3e532bcccf","addr":"d7356ce66dd427267edffbc7d90b1499edb2fb61"},{"mnemonic":"enlist pelican teach loyal like false property ski salon kite thunder gossip","master":"4b0285f521bf09632466c22873be5543b1c228edfdeb25838a3100d72c9bab6b","seed":"9c0e2337f5f02183d2dccc181372e47f8d89c3ba580e144fd6bbcc4d852e49d4f3f093eb1e29e9c0a58f84c6339033b800af15f212b01e7c60f8b89c3525f180","priv":"63a88432a7998b7af6962bff643d46a1d8fd7d4076923eb4a0f76a3038a7f26e","pub":"0284e4cfc7f7513515d97a68efd241f25c47d0b88f57b5308e508141b27b9ef2eb","addr":"2ae41ce0a0a995d865357c09749d94564f91ad65"},{"mnemonic":"congress like unhappy run unusual citizen flush force welcome arena clean student","master":"478229d977380296130a0a3d61be2ed2f8423ee7021544c32372beedf9e8c955","seed":"ee65535652c8733c881553f9ee7b9312a5ffe999ab40e12fe5a7b54101bdf8bc078de75d8dbee815604ebe1fce0eaa7104114780e074d4907297d29c1eeebbbf","priv":"caf650347982b40bd75eaa1830cb5d0089bfc011156c927ddec0fd90b333f590","pub":"037d33ba4e7bafde02969dabfbfe3397bd6744f1552da1313ce129f49eae410396","addr":"a00609d65a4753b3888416518cbd4c25282f355d"},{"mnemonic":"science reject slim wife shove laptop pull hundred genuine method canoe globe","master":"c011d8e6c42749fe6f7d1aea4b04b0d6e618650b0253710c717ece6d31005d05","seed":"40209df29de5baf4dd6b82df091404ec2f1b61f47bfa5e9a23e6d030848d8bd958138192458d82dc60c6c46ec01bf77b5c447e7b2ed0dace4c668d08c86719e3","priv":"058091efb05990cc436342cc3ef6efb2d0f02fed6380370d60255d37a2844939","pub":"034048a3e9bc89ed545de8f2131437838e7fd9477a7c3fba98032e2305732cead0","addr":"dba1207953cdf07ef09213624b99ae24780e8051"},{"mnemonic":"hint where immense cactus sugar entire stool accuse suspect cinnamon pipe car","master":"620259cc620b3b806fec360f2e9b84c4c5b94f9ad34c53b40debd1181e2da675","seed":"3332bd304e7a5b1120a80ce1fb74c1e0554c2fc5d3c007fa58af862c4c2450d9a1fd12c90ca6be5dbf9b69131eac8804fbe0e45ff433bf4d2f634b527319458d","priv":"536ffb48ba8ba6872cd9065c0d76b511a522a7e3b38c84ae16bc3eda2ef49e6f","pub":"038d3d8f70aa9ea108a19076d0e90cdde8d302b709aca1129eaf9ec281672b8aba","addr":"0fcf72bdee5071ce4f241e3c908ab5b0b969a37c"},{"mnemonic":"load loan mail real squirrel gossip fluid wrong amazing own post exclude","master":"c1cfa046473eee67b03ab8be8519a26c8cc72c01324d6a7e6108f3993a76d937","seed":"0f20d1b5e5e93bdb2031411be4c5590f977ca1ccc4550d7c8d8211a62221e6a5c6f34f7f99edf1f785811703a3540bd2f3dcadb15947cd4181b6e80fa988996c","priv":"b0dd0c8d5a07124f574ed87b406f4d51a77491d78f05ff5e80569741c8f044b9","pub":"03c403433ad539d2bfc212628180632b8d860172c6ce4ad46a3e94ddb1657ae889","addr":"145995cd3905204ca68f23c3203d5fb6d6eb8fb7"},{"mnemonic":"attack zoo topic note remind direct inside budget section outside permit inform","master":"ffc2f55b2c123430dc29c09fb431b125b5a3f321ed0ab5f64b179fd3358b0e02","seed":"693b14c3a0b6c0854971fdb5edfe2b5e5d3d37e524a96186d15fb0ab23f6d250b250f5c23a44d28ef9b94210df582d85c17208ce468d09029039ac5dcbd1222a","priv":"76f689bf1d6faf5456946bca3b048cfdefe39b74eb3e0e9d85c2da386db80d26","pub":"021e00bf6a0a71e0a37a8ffac002c5d5cc6350fee3dae6fd197a18ec880309fef1","addr":"7249de82b9250af13b7c309d32688ff19e7ed001"},{"mnemonic":"practice hard harvest gift bracket panic weather crucial have play reveal athlete","master":"cbce18216889b4dd4d2887fc924e98ccb5aae1e9b5d7433c120c79ec3ecc0aea","seed":"02bb9503765066c4e711e1a78be25e7b49689e107f58a2acb252b1c16dbb259db566a06213848fab833a32e34ce565788d7af30f584c21a21f02ef30dd2878e8","priv":"e6e7cedca2c3b1306cb06addcd2a861d04bc383c1579ba9d044a5c752b1b38af","pub":"02b11ef0b566fd9f429f88385507d63575094bd21caf8d3653a8b829c394de0920","addr":"8c0edef9f59b632305c72112f160e9c3616e3ebf"},{"mnemonic":"frown mix normal orient tower hero attend occur blur ship ball motor","master":"87c9a61c0fe1e8760393b18cc556b8f6d1d4bef0355444aabda127b342865d67","seed":"8e35626433f0913c1799adec7b23de7cf6d0689822d3a2f8d1bfb6ab041c80db3e5703c96aa09ed0db4e4f72097cb652e6d01d065bb6ab86f19e498793fb44cc","priv":"47b7699713fc59ddd67a556639c3f1ec0783a3dc3424cdeae4335707a549181f","pub":"0281ee7c3669207a68e189aca625e1b6eaabc909ae611a6eb2072f51a6f26d545b","addr":"ddd6d8013e5c4f99900cb22184075afb7842acdc"},{"mnemonic":"beef apple unable rocket balcony tag tooth spin sunny innocent clinic dice","master":"6b08fb53a185b5da79434bff6de9b10c558fae63beaf5f487c36760da44cb28d","seed":"f06397170fc337caa0278b2324f05095d587887217f5f10b13b04e1286158e4fe6a15da54c7dca729744e268255f4d04530763580ac7d660b323a8e8fe163753","priv":"923e63fa8400088c1f464357746b9e95560c23a755427d792aaffbb73551fbd1","pub":"03046ea68a2e1930e531b00376a4254da2a1ff0ed278aa800af2fa17cac40021d4","addr":"3ed4b79d2755b7d95fe1626d26a2b674a927b3be"},{"mnemonic":"sadness frown tape chase swear cushion eight funny sight dad solar civil","master":"af805962cf1c7bd97d0e4e981d3157834a17d3dce23a426c299b128685f28bec","seed":"a6292e7e8f3a502c4eefa0cdc94fda1d528642e084f45b30840e2ae9e7be636bbf2d67156e3bd352d1bb0750fa4df04dc5b8b6479c7c98c116c05ad5fe2d4d83","priv":"0bc87cd2cbddab83294a804fca193a6bbcaa3a07583bb2dd35619f325b70b7e4","pub":"025811f4948be5336572285ce58c97da84e5a4b7c542180933a1f4b6200ee4ebe6","addr":"9c6867cf41071e1f7d84ace3d2802ee46a1c08ec"},{"mnemonic":"bulk topple anger gift matter soft dune hotel dutch guard cycle close","master":"816ece50d6fbbee470de36fbcf646a83d224dabf5ca206786202f59ee7be8831","seed":"4980fcc86c5112625b63300e007a26287fec1b2a9cac0e254a8f43c91d897c03a3663fee0b351fd877171ce708b3fa471ba67290d6ad32075f0f6be6d3f70ec6","priv":"51cb46ea5db7c500388df8310bc5c8db7bdfb7c797030aa8f4a262b53f82a904","pub":"034e93f88a8da10122de23e2b25eeaf19aa1df514293b1e8fbdae2ad9fc2782779","addr":"c81ba2724c2e99a7168bd74cc79e222dd845187c"},{"mnemonic":"account lobster inhale champion relief scrub poverty tornado romance build amount exile","master":"202f11a0730b769f90d0fa68b81e9fdd78be483e38a9a39c447e8315d8f9fba3","seed":"001ce5c310547070fc2169bf0cb7353b90e824c051ea9f285eca426cb7f2527cca995865b0466c86a0fb3e208dc1ded076d2b985c8557dc7a94af7c6631bdd93","priv":"d142d2616dfe9e3aa43634a94a05707a8f0fa58ae0186bb565ecb87c96f648a2","pub":"02ca5eb73da42320161564c42520ab1a4b5823805bdb4dcb44a4abd88a235c6b2b","addr":"4481e257f1cb7d8105823e54a1b8d0254745874b"},{"mnemonic":"defense knock simple usage cook shoulder alcohol muscle pigeon balance become sister","master":"26df035303f63f356b451e829e154cac27e3f0c1686679c784d405455adfe5a4","seed":"44955b360a1622c1a69d20315b5fbc982502903b45736acea4f146c2cf69632a99630195b1166be96e4c90449abe1cddfacb3be63ff2b7fed02846b0d9244022","priv":"b9dbdb8952ce34d5f575b8b012a5e3041521efb893004f45eef2c01eb4f5fad6","pub":"02e9a6d02ce5cc1c14421c3d6db53d16a048e0421128f1ecc1e3e41d7df9d4e609","addr":"4e78dfe3fc045b8f65760a337ba354e01851d82d"},{"mnemonic":"bonus surface unlock noodle genuine stumble juice purchase grass table call piano","master":"16474b5955a793884279a9936804299a953427a38d5bead30553ec709bf42c74","seed":"da8eae0d3aa27a6ef6637dd17d57fe98e75619837c3dac48b3b546152d5fb1dcc4c59a86f65e8716c82e3014ccde5779e6e33c2a2658c71424f4ff9ea6ca0065","priv":"c9bdbc26bc788147d12c4bc3b13ff3774a7aad1ac66ce45e742c7a96eafa2a5e","pub":"0398102ae1bffc71eaf086b652c9bb847dace83d0b3f87d91ddacfb1702762cbe0","addr":"f0ead6caf66523b7e655b4ffd26a8b35f0b09eb3"},{"mnemonic":"envelope scheme knife muscle museum town valley until quote interest film keep","master":"bc01f4cbe286c6ad87553e0ece0e142f49984c2676ed1fc5142abb75637d47af","seed":"89867eca31ccd75983b064d62a1b4061d1f64c1731e25e08c65259139590490827869749ec30e8218e593e2ecbd4303984dfdb7b15775a487ba0eba84953a940","priv":"b5c899498ecb94655e622f999bd7ef9a2c4d26c3f555ee6888e5b4e1abbce1e9","pub":"0316d5c61149c0f83944192a788b5b64b9e6b1ce49f2604db67e8e4f16416ae153","addr":"b2a48800c35e6592ebe5003a46883a00360e2b44"},{"mnemonic":"also genre defense valid point smile hybrid radar lesson sniff one recipe","master":"3cc6fb6c4ddaa98e3daa2e984189417c55c1bfec4089397855f809659f9316cc","seed":"e962b4cbed0c3d5232f75595e7aa3cb33f1b2e093bcf9a21a4f8c6dd9677aba42161fd8eafe38fd12ca0ce3cb58d4d26fb7d349b1a160bf7f6f6b6c56284ac6f","priv":"420f0121df8cbc367e966344fa28d913bd1c3a1032efe5a3627d94039281e98c","pub":"03a61034ea8ffde7a239db255e414008c8e913a1405a34d9a606108f1943a7fa86","addr":"5976e21c1f85766c535011aac79e8a5f8b0f08a6"},{"mnemonic":"flavor spy elevator parent theme become slender recipe media pudding suspect melt","master":"4ce14ced0d4121d342d2c514755ba73b17eda70cefb20efa5aea71ec27ee47d6","seed":"0040263c29e5d965556054dbe7a738ea35b46775bea5859bc2e5b3872c89574e4f18de3f6fa36df65f47b13417763dc8c020b498ed3e9f11f46f019815bcf9a2","priv":"d2a1436a12fc9e4f2acce77564b8ddd67c1107d525eb6128c1eda078d3d8d845","pub":"03246bd048416493a970d97130d54db7e263af82dff75cc9fd0cf1e061f5d3f8b1","addr":"7eecbc8b6082d62d5fe28846a8ddc20b16e6a9c2"},{"mnemonic":"path number useless federal birth such peanut rate swarm flee current grief","master":"01d57fdf15aae5c1d45349fcb7bda6ab271c15be88429ebd1122336b91937540","seed":"061d0906c096a3338ac0877a102b4bb3b375ec5b34809838dfb47b186051a0a66c98e0d4a4dfac2c02b86266c4574c141f7a7c9365a57449ade60e28aecdbca4","priv":"9eb30cd9489297f0c4793df375a4a497162c5b75c36feb0a979da41000cc842e","pub":"03e036866bb847db7570ce0e2459d009dd1a89eea3fea8c3ce4f1f47c4781e32f1","addr":"139b3c7e7cb476da573548067d0a29b5abc111db"},{"mnemonic":"observe layer grab few fiscal omit clinic manual climb cloud song million","master":"cdaa9864952fa51a5a10de9210ea9e0199875459304876fdce150f042a415583","seed":"fa2c9dc476532ac66ec8e219c69883cb9645129765b4698b7f2010cb4b86b2d25ebd45e6c582a9f886c5fba4cd4d7488e81d705e63508e67c1698b77b8e6a676","priv":"238ae189645958242ffc9b3b868d78bad1be7d1351573298aac47ee78a5dac41","pub":"02ba7dec8131970a8f4a837bc225fe1e8fe20ef90b6363c058946930fe6b8cf629","addr":"4aad44c69095bad1588eacbffcb5ec324dff7563"},{"mnemonic":"solid business era limit engine fringe recycle harbor organ like tiger avocado","master":"afb951280a835f1ed21d00d478a644451e254310701d8a8025f5c716a5843731","seed":"2692dff98bb318f1f583e4f5d87a453b9e1472781b38f3b6a19784f8fd3e9b156ac6a292f8ab56e1da0967e159438b87b73042cbaf3e9886ee2641e7e97dc821","priv":"4b4bb7fa92a26e738da657b31ae57c52f057540f1371066b2570fb247b2862dc","pub":"023ecdde05d734b6ac286c9b14e1577f691f114b6554d0f1b389fdc37e05af9a55","addr":"5402fb7a4751cb34b261a2a2be940d7bdd3608ff"},{"mnemonic":"convince thing assume midnight debate end best cause laugh sweet unusual present","master":"7cf2f1baf94a8487a364a742db15bef15d1d1a7583ea26dc575b0181357e31dc","seed":"1e267ef4dc1099a438a346c7ca4c546149d6a57dc4cc6623ee160677711144583245125cfdbe45629160f3da711fbc57171564c4cbc771b1fd2a21236751eea4","priv":"9eea5ab5b8b22018197fd3c9256cd21be7dc26a111c60bc3d853bd977a19c90c","pub":"03e17aadccfc20dc41e65f7256717c54f9eb3898fe335395f25a65d4a96cbd93c6","addr":"85d9c9992d5351d84d40790e65c29b52b929f7bd"},{"mnemonic":"property youth river offer mention cloth mention pride opera repeat hidden orphan","master":"7e0faa6a216e4ae162547f5c9639530abfd56ff2026b4f18219d1c82934ab2ff","seed":"dd9faf30c2ddece69bb5d937c9ee58172564ec51d760fbdfdebe4dd445f1819bd6cc21a2a4cb70fa94a0d941d994d3ff58331be94f57a16589cd7a93c19ff10c","priv":"fa343044822d07308bc523eaf778bf697302cf8b88a3431bb5a0a51974a43199","pub":"0383e1d8186c1b3d0c567c91966a5c7aee8a1492feba372be735f9a612c1910ed3","addr":"efb2221453dfd951ba456f1c5ac164d3faf08032"},{"mnemonic":"awake virus civil cash clump equal phone wet friend attitude ask act","master":"87a61b5729fc2e294da66541b79085aa3f67c03a3eec40559111e68fe5a80412","seed":"8fa5a84240149f39dd60a5477ac59586aa05d6809adffb8184e4154dad74c2ab9a446f296098c44fac8c839d3405e0a2c1edfc26ba3aad9665e6b6984d320fbd","priv":"726210437d3054875e785b12d1aa23a8cab85a0a809593cafa9c63c62e6e3c55","pub":"025494819085e1d08d8ee2d421e4ca873682c69446ec5a412d7c7a7520900397af","addr":"e26e023a2aa67a3bb5e5988be46ff266722c0153"},{"mnemonic":"snap control problem flip minute huge lady elbow plate fall cabin trouble","master":"931052717250728c04dc605a8cfcc6a49a4c520f9fc343607fce57f5ae7a9e66","seed":"f55dcbed51a9db2ddd39d1164a81049af71116896e79ced722a387e878d00633830ab8cbfe7ee8e16ee612e1e047fa3d3c2a0fe230adc6a84f0178fef6aedc61","priv":"72aedd9eca0a5f17b3c20866d6d1e98bf01a1b8b9225bfb1d93f93c594726ee0","pub":"03c07579c66433d1b676630a0ddd343167fe91419a14a7859092b6b7f81341dcc2","addr":"37b2d898f165d5cca507de65f103231ea5128788"},{"mnemonic":"wine foam depth wise faith parade tuition search demise skill boat survey","master":"5001f6ff67ae2a32088e0ad93a227206bd66f5ccc7be991a27b2809354050b03","seed":"d889ec2bfbc930c78f9a3fc356e0dcef9d636766af361c8492189df1779bf76f4890d738106132cc5202ee97b849c9928a8934fd0b40d610a38f514953e3b02b","priv":"c19f1ce95ac35938d19d41e45d7122e8faa102e219188d681559d4db3f6aa66e","pub":"02331368ed143ec22cb1af2794bea8dd5e5661b9c6b1407bfbbdf1c1a151250b7c","addr":"a70e3677cb94b449a400c870159dbfa448e137cb"},{"mnemonic":"picnic basic you priority gown town oppose penalty various half follow nut","master":"59f5a86a5f6cf3254607f5e9846c7725d7cda493ac9850042de3bc7e8902583a","seed":"85645734c0caad6d0f3be793f71f08f2b87cc92b515e75abf94a202941c45aa78f663b455c91b6d51de40284d9c26a5336d444346b408bc12d8690e541a43583","priv":"17efc82e851c2938c22527638f4f3ccc2ff16ab95c24429c583b6f68d79ac948","pub":"02e534acf511fc86761ccde5eed25d793831cca6069f09694467a3b7434cb3fc95","addr":"d75b0c916f2329006221b040901933b2bc309838"},{"mnemonic":"enroll shaft young ramp moon message echo piano advice time blame mandate","master":"02f99e44bafc4e61bc3afff77696bd72af71ef05c86dffb2bb3bc241dd60861b","seed":"6e1cccef229d10e15ac6f1d2b2a579146ce011411a6e807cd227f3215c32aa394428f9a11900fe21699ecfd09d5ae6e4e1a30f2778bbdc15fe30927e32e1fa5c","priv":"8300a73d51449f909e8d0dfd843aa4cbcc055259f7deb54f40bfcc41acbcbe2a","pub":"0251fabe51d7eaeb45a7c82ee6cdd100f338692d796e7f1effe6a705cfeb21cb71","addr":"ada0f17f1854fcec548021ce617ea90a05a2fc8e"},{"mnemonic":"remind lizard alert mercy badge sustain judge van spike obscure account twice","master":"50a01f4e2adc48491e54c26a8c30c38f451de1d2d8195661eb50f6e5ad6e68ec","seed":"1194a8c42df528afd1b1eb41b2721a9b05f9456b09d042f15884d136c1713788ed8a32dc2153f01b560ad904c93327855450bb93ca8db384cda230eaec68ecbe","priv":"b78c8076bc4378ef0ea80af91addee35557f0fb059c1b434c254ae6c76716ff4","pub":"0251109362a0885fa59ad162e24c8f55cf4895bde354cfdbac7278d69124f77022","addr":"6655b6a665acc146984fd188c3c260668fdeef65"},{"mnemonic":"chief report afraid nation silent tower defy display suspect dice switch finger","master":"472175c2f86fa94d913108eb3842ff03fad950e4c7714cab8ce0c46e8e674968","seed":"c3656bac565a87cf18a1cfd8d488905e4b18436f93d0cf1d61572741b6e0ddfa794ce94a8b05e7796a6c9757edfecc6212e8b0ffba1e71064f67c340829b36e4","priv":"f16f039577d1fd9d6bbc18dc26c03cb37ad303ee1b85468df3de138ad927d098","pub":"024fcbc106c0b515838ce4d32c50ca1ef6134c314668d98a3ee30bf27e18e2fad1","addr":"a88574f43c1bbc38c2db68fae3f73f4244973b3c"},{"mnemonic":"now renew same wolf host minor obvious tape install barrel retreat cash","master":"a75fa702bcff39de09bcdc8f55cd1110c396ffca982d7c48f6d3d2f98ae29938","seed":"6d62aa254ec89ab960c04b4f72b5fd9acc135ad79ce4c9b3fcf25e0caca06ccf05e63d2aa47630b6c7fd3dc274dea540ceb4808eea2032ec3373d8a77b336338","priv":"dd211f6c5037d095da723423be7c1ead08f09d44fe01ffc0b2c0b83cccba6ab8","pub":"02ee58e7d2d8abd00c101024aff3da181d54ab84165e0b5c02e9d53dc336f0d11f","addr":"d9c4235d8222253cf41236382326190cc8f3983c"},{"mnemonic":"bonus message butter logic disease coast transfer explain away swim taste draft","master":"ac79c0b183965a1d918ec19217ce40c6ac1d84e3d57c8d0dd7a0c6ded35f057e","seed":"3fd63c9c7e1745a0f2526a70de96f251f1f61db25e808e3a6ba500e1a1c8e0693b888837cb9ddc1e8d09acc296e908eddb9386b97859bacb10561d12e46056dc","priv":"842e49ff7bc56dc113d532e7d7b4fd4d721f4600af0e67088b6ebbd491dcd4fb","pub":"03176edc37f7b671f46248531479b45b2b6ec77edb92001b46c64c7b88e7e588be","addr":"8170b83efdeca9e923de156cb5da2e3110852c0c"},{"mnemonic":"quit culture vintage misery pilot cheap wealth buzz false donate edit lemon","master":"b2fb8551d9d84f229e26e7874d1ed77ae8066ae80e04abae48ea84f96ae448f2","seed":"2cad64c36d24dc0cb94a2b2dac3ceec1498860ef0faedb78f702efada34c350f6b7f7760b14efc177893797160a838ead20f5a890ab05c477ee70cfa0a5a6c8e","priv":"38d5623053b64b8df44950a9f305288e3af0c411238ae3a89ea45f28f8375c54","pub":"02963af6b3f4add138a3b45b5b8f01bae5e6ba0434d558bed64fff01c6750ac053","addr":"9aecc7332529b0982d8ec14350594438ff5562ac"},{"mnemonic":"paddle mountain rent siege length essence negative amazing soap pitch blame sorry","master":"f179f7a22dd44ee96dc443f7fdccadeef1afaf9deefc8819cf254a554a3332a5","seed":"b408f67dbcdb8089f6ef0b241f026f6cccf85753ae137888e80c47b3267f58902e791675cae2854f556b067915821516fa04e00bfec6cd8e474d29639972741b","priv":"1fd4e1444a9c49ab77235d823e24d70d18b5d37cf9feb550c1e0763c7f9980b2","pub":"02bde455cf78c59409eaa2d98a105b537c9aee34c53486a4247299af90be3cdf38","addr":"46269ed379006a40bd873c79a9526ef076260eeb"},{"mnemonic":"abuse office gather ginger member carbon trash detect mammal shield like wink","master":"bde4ba63249cf7e6ea92a5724ae2f34477e42a8303fbf5c100c85c3d3ab8fc6f","seed":"ca4615dceb4adac1b16195899d537faa0d6e66a243c30accbe4902d26e77004da08873b0899ba21e4233d048c2d171cc8f9e657971f2ba0dc87b843f782ac619","priv":"05d5ce699cfc49b676ee843c9f85e1510f27cd65a76ba4d46eb6db36fc033c47","pub":"03c465fdcfd7441ab8d34244970daacd29a30c0d972b92a961559906f736d4cfb0","addr":"e60e2b02b46ff358acaeba84fadce61d7361f482"},{"mnemonic":"rude depth finger strategy wagon cherry mixed assume sense aim diesel urban","master":"ac83ffb8b0b9bc49758a81e567d179fe060301062d332bb40e353b788bd986ce","seed":"368f7051cfe851c638722e3691048292a1f2a94a83f44ac9e7d6d5a882c822e75ed5116cb059f0a91550b8b2237d32b9a0bfe556217455044b3b44962f4f162c","priv":"4af19a58ee5ea6c6cbaed88cd83c13a57da1c8002b816c833fdda7388adf8662","pub":"021ba0422b1fab7261983106fcaa20a43d8629633c95948e42aee12777181c1efe","addr":"aaccb6d212ff003c8754147b89b0718a58c002c9"},{"mnemonic":"mountain bitter treat hour purity swim panda damp notable beyond rough spider","master":"e48be94ec031c9cc4361550d88facfffaffc67fc0fc5adf495aa18e17c431007","seed":"fce2cfd110d408ed37c75fd0a88fd7513a09a8dc577b38176150f7d2835959f8170438903a78a5d84b32923bbdec6d5069c532621df387c65bbc2a879fe162a7","priv":"dfe58c17756a93be86fd81d3c874bf4ff6c45cbfcf049bbdf999a8e798e448c4","pub":"020d3913b431030aba9c57920708c5648ecdba1fb0111ffcf44f91f67ae92bf176","addr":"1ed6bca6d4080f039a12e3b0e772052231818121"},{"mnemonic":"protect chalk chapter dream icon boost layer couch soccer tool taste congress","master":"c5d0b996ee26e80cd48849482caa435956d87476d3fc5087a900a7e666ef3bdb","seed":"e40c57922c038fbfeb1ea7dce70c0807a55a2c62f58f947d8f05cb66ea7b26131e8b2b81ba9add4185bb8fb72176922190ba2e15de9caf3b4749ad7840ff1acd","priv":"850e9d1840b28dcea6088c9a4837effa1254f48af181d63f660d18f5062964f4","pub":"037859452c974613068cb16147826addb72f11101db03017612d1eed3e5352d010","addr":"3b58443eca15b2061bd5d7b3240b93e012424579"},{"mnemonic":"rubber twelve wire exile shrug will alter violin crucial border drill pattern","master":"15c68b495a571a78a09687a86495141f94b2c015f4c51a9dfbdad96e68c6d871","seed":"ecb81c59dc0464e8ff470db36c567301543b2bd1bdeb94512db63bdfe6632d9c88c1aef02bbbe04176ac7a0789c9579431e732adfbf038c89aca077d14582a8d","priv":"00ec93d9115439212ee358244b5128b48a67645a4f5bf94fdcbff2c8e93cffa2","pub":"02e68bb8dcc584b4e54da27ca229a66d6a222dbce0e187a9330b1740713addb417","addr":"14f8f956d84c53acad6e5eb43e8fd7362d341363"},{"mnemonic":"loud ski diet extra rely melody space canvas humble rain park fossil","master":"1e09a38b1538e950b8ba8472c07b619334973f9075e41732851606645e318d51","seed":"a2d3ffc96f020904af3760c11e9a9e87e8824c1093b07c92a8e6d98c6aec16adaa8ce6995d5d6b58a04824a765d0232ff995183ac38a5cc2bac14f734ca8496c","priv":"18e45a61f9e6ec29019df10abca1878045553d9b924c859fe57621f212133edf","pub":"02a0053e91ce99b2c401fc40cc2892023b30c2db914403ea0da794bb77f69e93e3","addr":"bedc6716f1649fc2ae412516cb0a1d68ec2868e4"},{"mnemonic":"potato tackle almost kiss unveil spring smoke nature agent carbon swallow final","master":"5917e819604fceb3e7c11bfdf6b85809f509f89b3bad6ec7069e8e29258df791","seed":"76d3089d7214660adbbc748f9690b70f7787e9e028fb429086caba19c3b412f931b2768a843ddbdfbb6b6bfdc6349aa0fce1168d124a13d8eda61fe37b407f37","priv":"13c35356aea2324ac57e4c2d605c45020adcd4be336e097dde0b23059499e947","pub":"02e9c1615b710594269b4e86436bae98e4e9c00e7ca0405b89be47c02060705ae1","addr":"e9699c41d2da37635fe657c557f54f51d8e4a503"},{"mnemonic":"innocent cousin jungle elephant speak rent arrow maple danger menu misery breeze","master":"c2dd7273c7f703e2c66974dfd25a1e7091d83a7e6f8ef64954c8b61cfe4e84c5","seed":"32f96dc9661f448f82e2100afa787fa09afe19d90171a3e2d7b5a007316690198a3da22adeb22a2fdea43c3ee98a6ee2bd33baf1e84034d559e6019a30c2e87c","priv":"1e9f48b65f2c57f6af4797a41afba8b017de41ccf6be00bb2a6dad09a72df167","pub":"0268e685815391e6956df39750aa3e9ad8e4e558cba04ed4c136785e2bf82478db","addr":"3ecb6cf97afb26e1e0272df4fbad2e38be15287b"},{"mnemonic":"shoulder lock swamp goddess length trend tongue razor heart donate curious social","master":"c71c518c4d97855fbba7c0d7df9ea8f4e6211962ca9f5378b493c6c1d3b6afc4","seed":"e575bae2e1ee08815052f98f5c4bfb9873f171b0dedf4385e378348310c5c7f6d1cb021696e5913aac6b631ea1951bb977b3bcb548579458807cd565771945a9","priv":"2fea7aaea02fd5d5a5918ebd643bdab939edd18ef406ac5163714fd731e1157a","pub":"0363e2499272df247aa216ab8b274e146fe677bb18e706fc5377f8c921ff1c782a","addr":"de719e1abeaaf11712931d05ee39990e1331055c"},{"mnemonic":"bitter yellow post enable knee tag spend base blur gossip lucky lucky","master":"1af25d9330946339620183b1f1209c4d1ffc0aae754b82d71268400b934ea426","seed":"9e07914810a7e2d91a3ff6d4efb0686c14e59506dd9dd3c357dd5a30925a3f57c0a4983589ff113833abdb7d5cf7dbf79c08172888539126dc286848c1e49ab8","priv":"6e1ca5a3a31b7f805e412f0bcde7f82bb3fd984661a58c07b7967e327e664e47","pub":"03cc8ddeed92731c6b475a964c885865c5a11bf59ba24295d1e1117feb7f1f3e5f","addr":"8b516445842b755f23d0e671f10a5c0b1c2e48f5"},{"mnemonic":"forget organ violin inch panic sword report clean garage sauce math man","master":"29156bb726af212233cbc6c191e59a96d7ce44b6821538ea03053f36d51a919e","seed":"66c639ef4de2dec82b99ad4ab7bc73c0a4fa79d28d06ee393ccdbcc27ee375e9dae7672055dbf6d0d5ed67f2e99d4840614223d85aec64dd35607aa9b266d9da","priv":"f5e49029f7141b33f51703add1f4495e04715674fb62ad2d781f8c66269fd32c","pub":"034132d2bc71934628f435b93a9d161a3ce242e7d82dcda0a3a8c2f304e3057500","addr":"cb0a4d79fadb82d7b947889b26f8515db8fe46e6"},{"mnemonic":"under depend door lens retire faith scheme dolphin orange maid carry disease","master":"62ecf318e91f233b59acdb4000665338c8d61539b7b079716c85ceadcbd6300a","seed":"30ec1c26fb1dd7e41c5959ef7a3615e6d4e5bc21fd8af5efe1f8c0634e765f63462d7017d5a62c1e992bbb626ffcaed002208ac5f8867a97e454c1bf0bcad8ce","priv":"2babdc8642c9c9beeeafb728e948bc8531dd066679b85a9b58676c0b4247cd89","pub":"037f9e2241008d25844a96272632255802c7cd3866c5a83bffb3e2f724eb59d385","addr":"10eba132bdc71c162058500af51c53074ea1947f"},{"mnemonic":"swim topic sunny exist exhibit nurse ozone guitar trend page machine pitch","master":"5a30155bbaea42d54e9a27fa7587c712a19ad6c1c31052f68418f235b7bd5de9","seed":"673d936ed3502149d68172a22785c2aa2bbb3707d319fb692fdc6a4ace39ec3596fc406b60720ab5993af07227f42608b5a43e8e732c72d8ddfc82e680428925","priv":"e6759f20947caed563dad40d46206c67599d4d622502e46199fde1e17dc3d76e","pub":"02dd5474a52b623514948319697c646b519ac6e63581d27b01f0780af8af085e66","addr":"85fb1118593dd8c12acb0c2104438faba5dc236d"},{"mnemonic":"dragon square define chronic round romance scrub gaze powder visa please symbol","master":"1f1a35ac699063a47220536ddc3e988c055cee5e08303b867fdc16d5488861fe","seed":"dc2037120b143c919a3f0d71c6822f29b9b0ea098d286f8d4e40b3240bc9d19d4f45da3bdb983f49c304c083f534c7a26471296211845c13b49df97be61055a4","priv":"d99a6b75adef1455ff85fc94e8a4ad400a326662e01e9c0152c797b842c060e7","pub":"02eb2aa36f19bb90fca43f34316a18bb80053faeaa909cd6222128286af6c18bac","addr":"d24f7932d14e493a54a5384dcba3682e3d6c55be"},{"mnemonic":"first knife erode dice talk coconut act example sudden garment scene income","master":"1214f622b52ddf15c146c74bb0843b653117459901214a8a198a0eb59b4153ae","seed":"eebdecdd33e9ed6dd2e825c12a73e4325593aa14a7faecaea48d6764e6ee6d9d4140ed9e105247b2ccc0a1bda976fe7fc7ef8483c58f465cf393c4f833e86d94","priv":"ad3894b4f558a2e7fe5f0685e4ccd63f57aead98863617b081ac620cd25ffc4f","pub":"039de7903629baa0b6ef2cfa85dbdcb51af3fc9218b01bc57bb1f7eeba5267a858","addr":"fe6dde2516232383dc3382a75e86be3b82d2d8c9"},{"mnemonic":"danger expand toe talk course mask quit virtual reflect vital address artwork","master":"54c66d5d95de00c23ccdbe2defb6cfe78d809d55e457a0b35407ca74ed33eda0","seed":"060b5853c7f3bbd7bfc7b5d532f39b74137c2b6273a30682f768ad62800744e1c6a1db920d151d7e553553cd908b2878a31fc6c682caa05af62eace45a897b19","priv":"0ab2d63d607a2c56041fd953d9be60f5f7ff5e50f3c3a606dbf54bd799e64190","pub":"03f8b555aa7005be93d03e98b6f2a8870b9cd4ef654299be64b13b89ad839038b8","addr":"526ec814ef1712329c1cd43244e92d3c1d5aef91"},{"mnemonic":"custom flock clock grain absorb danger universe achieve decade habit phrase together","master":"ffc14bb5a243dc703a5afb1f904f8aa4f21790b470c9e05fc21cf872bdfce41c","seed":"71a82a4221bf48e1e97c8e144de80e80a9dc5808d579da185e75f6b88bb81038d88210c252921a2d72dd38c5bcb4edd442d2b481dc1d857965012d9249f77477","priv":"d9bab16080df04ffe43c57fa80c441a65b4e49a4425a0db06f52d6db77595d38","pub":"021f074f1e14552ea091e14e680814661b1a75148f8bd149fb8f6a13f6f5e7ffdc","addr":"d63213b298b92b726178855680001d79ece9271d"},{"mnemonic":"spare absurd book liar green humor alarm income sadness shoot radio indoor","master":"f9056445390a09170334e8a225d62719fb259a0c159685c29ec39e348b742510","seed":"a023662c39608142068683c030ad51321ecae6bf954b72465dfa8feb34f1e8ace0d46a072b855e33f7c5e8be70420a4f3baf7ec3ba370e975da88890d4cbb2fb","priv":"e5b8369724ab9aafb2bb44a1d3cceb2568fb0350b45f123a7cd0f26a27e70b2a","pub":"03b9196b842ae4db2b2409389a0747407baef8b19d502156a809ae02161cb0de38","addr":"658f62b688afb4773a0dc4c81925d7914dad5d22"},{"mnemonic":"anxiety salon have exclude build airport decrease unable measure reunion monkey private","master":"4f708611377bee900ca76817926b905bbca28bccced3ad0e211c7609c0562fef","seed":"cdabd5c6b9a64c302fdde1e7cc5e6ca15811e52e432e7019a81945264b3e52d89456171be0e24d4dffea0136a12a6204f2958c303f8c61af84f4b5ed135685cb","priv":"7086136c92846f7deeafe05dddd8461028edf62e947fda55b4f1ac584a78c5be","pub":"03227f8b0d42ee20d3c5cb4524686d19ed43bfa5595debe2ac4840eeeb92f3a411","addr":"6d11946752473bad3a3d593f85e97bb4664c2984"},{"mnemonic":"frog youth swear now annual mushroom stuff business excuse frost cause athlete","master":"0390c3c986b8d724d344395860504caf17a7a347d10aed2f4a0ae7ebc0e07f13","seed":"25b6bc7a888b35e1246bf8c7a289a79ba589cbd949047ba6690b47bbcb12d8c87a4d14d585fc0721217891396ce0b0f75852187a9fea4feacf320f9ae4eba3b5","priv":"ccd3755ba9b7638c2ad6815d34a03869650bc1c35b75c8e1a1cc9c2ad71d983e","pub":"0284806c57cb6013ca5ac1027a07784d05b23bfc4e6facaef108bc5af7ec20e026","addr":"d512ff91fe37ab6bfc605cf5470ff684d6dad743"},{"mnemonic":"bridge rate pen range tip web bunker magnet blue rocket dune evoke","master":"38d760387d07ffba1ebd6ef9fa9737eabb311bead38560cc464c7585b90d6915","seed":"953c78a493fa99014a542b2740b5eb2623f0fbaa765a5aa79e61a5344867dade60e05c4293df4076e218ad61c66b1112f54aaf7bdc6000b059b2c88558f582b9","priv":"d6d617aacf6ac20090788e43a7eeb58d1b44c36ecd4fbdc9ba287c8bc7f3b24c","pub":"03ee39cb612e75ef609467ed6250b602b90ee94b25ae43be9593d2cf34b3cdb938","addr":"dcfbe07630e2a9156f0787ad4e96de1bec09b3f9"},{"mnemonic":"volcano exact weapon couple logic cactus carpet raccoon state rigid ball tent","master":"8c60a1a859b5684bc6aa996738801f47adb8392ca3f92865b2f2b3a48c69425c","seed":"fc6ede285bb6e6fad778234a5f6c5bfdc23dffa2975667dda6c5470c70122f8aca9c63bd77c8811c43b4d4b2ab4ca55db7b4d457f393436ca1626ae6fbde03e2","priv":"74a1b74d0f11c8297f0d315f9556a96ec5e880bc59fecaa1283ec2a693cd9ef6","pub":"03f62cef4ff1147df7ca38cf1231c48632c4c4b2618e6c7d2bd001e10509f68f05","addr":"8b8e006c70eba973ef8945d89e33b6a5422e5742"},{"mnemonic":"match quote pet worry pizza stock flee tip kidney tomorrow giant ship","master":"02f8e676d2c4dec8e6a8430c22f8adeaf3b25054c8d22dded7e2bb6af5327a63","seed":"4d29deced03c572a5fddf55539a735228b59cbcfa80381a54c5a69dae73f56484318e511fcf46123dd8f390e2527de882252f3c0b69f49b9dc83c7059e876767","priv":"049f7fa5733f1c674a29721a025d410bf35891984608ce1eebc7ab48626ec3d0","pub":"026912ef70835b247c3fee238937842fefebdebf046b7f2afdd4f350152765fd26","addr":"4d221f1336ccedb6b2a9850a15bbd13c62ce0fd5"},{"mnemonic":"swap amateur unaware glove biology frown vintage dream prison bulk gauge bacon","master":"8c370390691fe152f7d6f5220704c9fe6b27009c1218a07d529768f40fac692f","seed":"5e3c155797cecf5509151218e30101e33da6058dad04f89dcbeaba0d1d2310482b278dc747298284bbf7e29a71cf4a869e0c2755f6144cd2a5f58fd581551b48","priv":"708a814272dd4efdf60665c491730ddb73d3d5eae3d74ba8ae632183ed014569","pub":"02e06b607086808b325b7629a95ba7b945e611c3062f967402f04966bf87111a23","addr":"d343acd452e5118b6e4c1a83cb08a521735f2a39"},{"mnemonic":"shallow chapter special riot dial sweet armed imitate rotate south cliff shoot","master":"bbd697f9078e47816c986596fd2af08818e0e84f3c2bf52ff52cf72974add88f","seed":"bd24f3a066e4a994bbd613d12f88268d16d2439f9331932a9b30da17c7fee4fbf5aba4f2f333103c6bc1d0bb600be1c86db54e323b6e9e9394b93eee35a65359","priv":"1ff3375c7c35230fdb97b8b8a2401a59278b383c355dfc1773024fe38acb4a42","pub":"02d3fa09d1e5929fa37218d16448800c9eec188e31614396648b65f3303bb3ce80","addr":"8c3027c978b9be60970e98790b073f62cd3615da"},{"mnemonic":"illegal hospital witness leader wagon appear trick mixture refuse kidney total lizard","master":"9fdb13cb834e01260d56ad2bb7c8db55b768bd0e76464d52dccb77ab806a1258","seed":"a96e21fc0177a251d86cb6ffa4057890112cafd32a7c270e782616b407cda51dcd914ba2bda90c80acebf8969825e8044ec77965e264e085ee6ce78fcc698f61","priv":"17804874b6872c2df6c5da2ae45830f752a159dd03ab0b2ef22c64018e91c14a","pub":"0221388d8dfb7416ae88426999f1e07d41aca9668b10262e995cce20448e315e54","addr":"4feb63cb3ca2d1f6b0add8ce1bb2db5661dbdeb1"},{"mnemonic":"unknown update couple lunch demise sick brisk market area kid service again","master":"26f5f1d04e6f20ae2a9cf5631a1fda6f119e3c14dfb35ff75ced5091ddd072ac","seed":"72e5f09a5c9e56832ae400cc69b98932067a81edc9c0bd0d97d385b0cd7b04f70e51f496054c7d28af2853064982c9625a4fe745ccfe8bf4d690ffe9368867c4","priv":"e59d9190fa1f4f5b37842807ec8c886c9850c7946520f6fc764c232222500f9f","pub":"03da97ef93bfdd16433aad5ae6cde252c062a9875063fa3b7ed2615077e4446c34","addr":"4302a5c24f1ef5cbcc1e286f498140769f3fd667"},{"mnemonic":"leg damp bulb final remain off lion fold run buyer help safe","master":"4b64059f74a801c81a66d7ab2e25597a3f3c97fffe760d5ca70a8857fcc5fa55","seed":"24141973b3a7aae69d48656fc4e535d1a2e094d9ae5d6325f54d6288827dd32602b128ef414240fd88c9a72f790f8fef560efc023a6695f133d8b46eed51cb1c","priv":"13e840acfed4b533303974eb1223a9d4fd400902041be3994101ca517aedeb6b","pub":"03ed7c577c28dd6936bff7eba4569d681abf5bd59fb97ba5d793a3f65ad54f8d21","addr":"3e404c844010458e56726cf7d0881a1c4047ffa0"},{"mnemonic":"observe budget library column blade soldier apart panda express frame version coast","master":"dfb6154ae9a50d8853f5fb0fac07d98cdbdf00fc4511f6f940490e48ec1858da","seed":"a16b567cc1e2c96ef202c9d49b9d14cb5ff14c7c514c8e2bfb214a9e6371fb6f4eff3dbee51e7de2e781dbd815d1e76af525d9766504208949475866abe29766","priv":"b16e831a50e39788755684d0b96f9e4f11b9e637d9e43c27cdd5242091c0a8ac","pub":"030ee1b1e2c7afccfe7f667ba52dcef130de06b35655deeb33291ce6118eb0a31a","addr":"c72adab4e3d6d5d8a9a72e36bd2614d0b4b6e78b"},{"mnemonic":"exit pulse poverty scrap relax umbrella rug clump cruise biology magnet area","master":"0d00e0698a0958ab8ac891db675471b3f7a998f4947115313bdbfb189a8d2308","seed":"a2831c38659377da9fcb2b76d62b76a7f23d59083f33f8c6778eabd804331d46f2f0f4e167b013e16b2b6ce066816641b2bcf47dce75522cd3d1e6d9fffdb28b","priv":"d0c7f92739b274899883175525b6443c265c288e0835233428b97f6f912263c4","pub":"03740d02a36387dc52d66d96357240ec0e185007bbb4457b3598d96680de6309ac","addr":"c4dcba01a757bdf253ed47a41a49c996657d7f16"},{"mnemonic":"impact random cancel imitate base purity devote panel vintage group pool twist","master":"ae715a39fbf43bf9d848024d3eb93d9ca4313c384374fbeb3508077a29017462","seed":"da887f0a16dbc3fed38134acb53466bf1c1d18d179c2f857573fd4a43b8e52b16e598306dc199fa2414700b350174ffcbf4508951c765680f4b3dc7255270efd","priv":"512494ad5290d4dbb69d9247e563188a8705dbeab8dc319db39743c319389535","pub":"03a4eb5469006a29621ea5321f35e8ed8d839a9be99be7efb9caf5e5389dc708e6","addr":"4ab6b8d6bdce81c88b093698870645e7a1f92370"},{"mnemonic":"egg usual identify trap involve winter card eternal subject unknown obscure scrub","master":"6b54ed0110635ad73c4439e189e594cadb02f22d84bdbc7b94027edef2658a83","seed":"f23aee9d83ccd474ac819ce7dc8a57cc57ce082f8032c242511ccd96a395ba8c769d07a7115d25b53cee1d12d6a703f1c0204ee152bedaec1b8c15d5d5b78edd","priv":"0f1f52768a3bc3ce2810109ad40da0126ca5527c494b226048382a9513e11be1","pub":"031d08dd21c95576d1a1a028ba2938537d1c604679fc6e59cd13ef08e62e566a4b","addr":"a0c1e6d5d63341a8707be1673a0dc34fc054a14d"},{"mnemonic":"crunch drive cereal switch sketch gym hint fortune install approve device gesture","master":"4b4f8682bfb429ef36e7ea355276981be015fb78b90c50c19665b6804f7954ef","seed":"6ca97b6725834344247fe5dd5fa0d2a20c31130d6b9c60047578181867650f8e734cafab2158f57b64a92c3f77672352dd71d9df03dd6d592a137cd19e67f3c5","priv":"fac29029531fdccaf85476aae13bb3c3c9f0083265fe6d5e6e612386f3be3ec5","pub":"03683e7d7472d8fe91cc67bea096aac18dd00ae858b8912ca9b172207b89639b80","addr":"aced36c9dad879576f5904d67f504e704726a21a"},{"mnemonic":"congress nurse found frog crane toy pact write manual version repair embark","master":"157ac37c0bbc0732a71858377479fe8bb236664322016fdfd62786ae716f9ef1","seed":"8f8269a5211027a2c6480e9a9d910c385c2e772e12cb756802931b169b602d0eb7da4c603b901f55d4f5c5cb67d7fded0b71f5f9120ee1ce08e74c3bee1f745d","priv":"ae12502606695e34c1a97dbf15b70e1637c4d537cdb0a21896cbdb17277181ab","pub":"031077cb5bd6bea01a470524322478cb5997c06fc77d7154c92f3b7273a36c739b","addr":"6ef29aad62d003f9927be9daea218167fe14822f"},{"mnemonic":"verify service fashion camera deposit expect snack memory proud opera flower casual","master":"7df339fc4837633a008a512dfd0ebe4f9a1236f048839025d33c574c4af0cc42","seed":"151551954b5b4719de472d6a96d5222c1eb688c476f190bc263d7370baebd0740e58f2c3fa00e3cb4615389bd306ed994d3da60808d1d08dd005c5292d3038d0","priv":"771fbf2a2c24130bb356f2490ca67799ea8be2d37b3f291323d5e9b079681cbc","pub":"02f6c6d95852798faa803021107d6a12d56bedcfbccb8110fee698b800931aa2dd","addr":"00b958acb44eb87590ec60f63bf352ec8248fecb"},{"mnemonic":"artist gaze ginger just pride royal strong absent wash figure adapt decide","master":"ddebae65962a513c384bd902b230fdb48f6315d6645a947d79b63c4d45cb6023","seed":"8f7914ef479cab13a658b773db99f56a3ebc267675e1a91a3b595c2f0616f2793cb862cf6038858d363576f994c28c630eaa54299480f168f05d7564261a2693","priv":"b416f93bfe3495ae2ea2dfcae8e587bf19650ee08194962b43ff97deb85c1bcd","pub":"03c12fd1c2e653e3990d15b59d64cd3c34f3f248fc2f1d52946fb218d3e94912cc","addr":"06c7ac564ab51a452c3fe76c0cab37541ae1b3ab"},{"mnemonic":"case mandate call napkin cash test ripple bounce page dilemma usage stay","master":"101248d364cc296423da1839cc3d0774ed090bd9e73f55f355963272129cc184","seed":"b5aa29ba3342da94663315038e9b6c2d61acde2e4cd7d08971d79576224d12af8478abe891de819771a6ddee37269a71b13c825f8ea056f7596d301b00a9c0c5","priv":"4b97318dbb30a0b86d6497a97f3138db00d268ac6165a0fb80f5b8e5d714e619","pub":"022487dbfb8e3061c3a342d75ceb25ad9a6acc6b8df0b224f3f521c8105a4036ab","addr":"984ecec7727a1f812b63b6a6899979b36bff2e9e"},{"mnemonic":"neither divorce grocery stadium narrow electric observe that six diagram hero toss","master":"59cb4dd0ccefad583b8c79c8dc1c5e1d1d77149cac9fb26674076287105a0936","seed":"9c5e31547f43116891fba52294c90c80a583c0375ed100d69e2b72e1453b591b1072ac402d24e011ffacfecd2c8fea1c2b1cf93a435996df42e1c8b19aaa3fb2","priv":"f490ea8e2e8011d7f9b9c57d9143606d470ff00bd51ca69a44c2107d7de7123a","pub":"03fe9d9451c9505075629309bca9b361edb59483e417f07a2759aad704143ad778","addr":"65b28d0f6e78c0743903e41e915de6231603eb5d"},{"mnemonic":"van lucky present hobby property front toy document report switch strong say","master":"5517d9a3e2996bdc9e317a447f0506c33dc20c3c36e6565dd8af76ac2a0158e0","seed":"779e44dd0d1401cdd9d84061044158fa4036d66192c5059bb7f33810e776de434e24518477bd4092a0c775bf7801887a72fd94f0d6bb46757ecc3764f8e17e93","priv":"bbb4c89a597315ac9524df42b17498d334d93b8d48f19188f5ed2327fc2800b5","pub":"022e2a217432ce25ef42196530550d177aff02cdf91332e4a86c8d1fc4f34b07e1","addr":"ad5ea6aa0d47a084f1d01c547165eb51d067871b"},{"mnemonic":"swing shell april silk tenant swim clown beyond under tool envelope private","master":"bee0c171d74d809a83d0a7f70ec1d8ef320efd80541127c9e3b2dca85e344ece","seed":"da69d4582287e64756d8bc49979952716991ebc878764f7c8f93649f5b721c35f5496e7e81f5f21cc987315f53a747911363a58790eade4c43c7c24911cf8b89","priv":"a6c35d6f727685419b4c3717f0dc31d33340536319963186c64f18932bb3d921","pub":"023465c95f48753fd4546f6be7b3c5959ac2de74445c2352e14d0c57b058ab0ae6","addr":"7959735517d011fc100b56f25b6115982d2299e3"},{"mnemonic":"carpet sketch depart tenant immense sock because caught close canoe insect crack","master":"ab35e8379ede1615b44bf8b1a8dbcc3ce88b6d6d0980cd63ea4f783340a1c372","seed":"379373dd202ad95fca8046f17a5f989268cbacd2697a02ee5efc2f022f9019580e7fc452c551d97c9aa2247c566313e454768e38d6585ad9561a09710a279ef2","priv":"a7165228a05945d4b01a1ad12911666504f8fea8c8819df414995bc1eaa9068f","pub":"025a7afe792c05bb3d94c7996bf5ce1fbb02bbf716593b2049f6e42a0328311f2b","addr":"1fe2d6a254c104cc38f1466355501890d370b30b"},{"mnemonic":"world sweet evolve club speed desk double verify gentle account youth column","master":"b2309b5c1e0a5c590859c5ec3bad4b94aaee3e2e7ef21080cfe0780617eff220","seed":"efa3dba671c0c4e35072d8958b4d7af280d8e20d3b6752b34a6b1e561d0f44bfa7829a5d540b52e02dc1b06735dfe18b2073a784aa307253dad71b9146024bda","priv":"a2a6288f9feff9b408fd6b056309dcde5cbc40489afb85413202443d7c283466","pub":"0307429d4171f929f79c8532cec5970c17d6f92ae014e14d99fb1f8fbc0637c9e5","addr":"1ae1b848027b0d1276a85ec2946bb7096755017a"},{"mnemonic":"patch cave blush omit calm habit autumn load focus tobacco barely switch","master":"972320ebeadc9ce9da0a447dd469c95bdcbbda09e6887f64dc9c6fcb8d6c91ac","seed":"dedd6610c32b2e5a3fb93de12f758d92041b0d1aee0bb2626dc0e6e8cebb8ecfdf87e25dcdc4f9646f2e37fcc071ff4137d914df7133a6e22fe8669ccfa7cbb7","priv":"17cfca7dd65152e0a3c77a2bf4a15b0a99b7e889dda49174acefc06d390bb255","pub":"0286d1e4ac0c7df1e1e6ebbe1b7aea5f0e0cef8ff3336a1c2f61c80d135a382234","addr":"b184ce8d18aa006e93ce901fbe879d3d8d6e6417"},{"mnemonic":"extend install wolf token genuine mother swift pencil scrub annual wealth hip","master":"4ef0a071d94253f9a60bffa7443918f43865f131a579ccf93d2ee16a518af2b8","seed":"f66926e6837305237316d7a69fbe18911f73a4f98278a2f6e6b1a8e06adfc1d189875ca401387b74c0198741619030187368c2a58e6b844aacd45fe89fcb6a93","priv":"f4c00a2ce7e9217e5e5e3f5398114cfde57f25833e920f14989e450645087bc1","pub":"02fb09ad3c161919060141c50b70c144cb991a553a57b25b2688e56ad163c3bcb1","addr":"556ed45bf7463ad502fc2fc07ac05fc073badbec"},{"mnemonic":"canal pink undo modify apart bachelor movie coach december exclude scale despair","master":"ebef42622df1bc744290f0c5d930aeefe2764dca7efba491b78ec958a5acc171","seed":"056347f396399c75761136da001671c6097fe21adcc920952db079afa5debb60d1c3612742d96af16de34a44c792da1ad995757e6a25e62953116d3016639c86","priv":"6a83065d2777eb4674e19f33a08b46c44753cce58902a41cdc3b8e3f0883050b","pub":"03a928c2c2aafeedb59d1588a86c42428b70171eed39b94f68f2097d9cdaa4c283","addr":"28053af43e4d7e35b32f9d174bd205206f94028a"},{"mnemonic":"brisk clip brass tunnel credit hip clock deputy dial hole song soda","master":"965fc6288cf02a8aa3081de292a513fd7b23fd010d373045e2a5cb37f38b2393","seed":"553cbc6a6599410913b6304461c1cc8b4a2c09c8bc1091c231d7167d27892ffb84b89c3c001ad40d4740d97224062c974ab01ea2dedfe1a3322f1a041964fb46","priv":"c9fe5b03317f7e7496f8824f24b782c09b5b801b3ba7a08d5bab508005f88aea","pub":"02ecf7641a4b3436c91ff3fe5b9f700cecf8cc3769945c665ff6129f6a60e77a7c","addr":"e578b715e9e84da6beac28486ed9492bea16435f"},{"mnemonic":"senior example flock banner pumpkin salt silk soda funny input puzzle ready","master":"7b0b3ad8cec24080ad6fcb9b1ba4b745820543666d362a188f4aafa52cddbfad","seed":"367a466ca4069c50df5571db657cf4394e843973e5801db4d7072c51453ce04b574b01e07ee8ef0836448f7fa220863e6cc7e6180618efaa3868e78b807b4b74","priv":"31f5e11528a372d7948cbdfb0519f974168d568128e441a5840a02c1ebc71f50","pub":"03b507120d46abde399656100fb664c736a2476a588f2c893d4be9a5f9acb0460a","addr":"941deb14e567c6d60446fe5767a0bb780be7fd0b"},{"mnemonic":"say leg next pelican brand topple blame plate snow month van cherry","master":"82a9d68ae21ace7c2e5d7d8ff58e4f0cc3c7e5db8031d4f83008d06088c477dc","seed":"69956cc226c79bca915b24c65112962205eeb161b79f66246b493d53eb7e1dc56f9dbe475d9650c0e72d7befc0b899f75f7bb3b3c100f7d6128b21cb4cd88396","priv":"cc512c35a0edcc0efc15ca9659bb536b3957420f00b32cd9e3a0d0e1cad5360a","pub":"03c4c82df36b093deca7eabe03ede5c5ed3639dd37ce8598ab8a6342b86142b07a","addr":"d0ae8f85e8c95b4906de99ed528331173f251e85"},{"mnemonic":"develop odor front thank mobile subject then cupboard human high crumble rabbit","master":"73704bde13f4867719c71fac5b37f16f30b69581a53e7f09118ed1368610b1c9","seed":"88f30341bc3ab214f1aaf379a8fbe498825029793d4ed2b50d12ef666fe45f06e39f68583c4cea8ca6a88e5ea62d8aacb499da4814fe346e020a78bc636a3cbb","priv":"53f91608a0b1825b05ae68992f97fbec8dd7adf877c085d1f30981d6f5262653","pub":"025f5e6339f5b651038512ddb5073eaf10c962f6e82bd2bd94c117cd4cf4de4fc6","addr":"d24cd460bc42f5222b18d5632d53163b648c982c"},{"mnemonic":"toward weasel copper blush mammal window weekend exhibit pizza element impulse valley","master":"3fba4e4716bc0b0f99f44a2bc7df34bdf60bbc5c1e2b76ff4295f21428465dd4","seed":"8051dd06bf13a9b79d82138ee3e5cd3e417c6d203ad0f6ceb81f38890d4c18b56d29c93ba76591c499c9cbcce1bdd205b26ab792d506d4903d90104a226422e2","priv":"0379555ca3e00311dc6949659afba1cf6019ab5690f14fe8368f0fd07b90a44d","pub":"032446f977ee3324c946b0d6409a4b7401becffbfcb868827e6639cb686bb2140f","addr":"87bf7d0cff36c282a9140657a4420f67b7b7433e"},{"mnemonic":"lift piece elevator remain horse virtual fragile dynamic whip lecture perfect fine","master":"bd16309fe9a58eb87ddf1b8338ad0ffe4b39706c4d568cfdf6f5ddb79064ecdf","seed":"8433dee7ff8aa73f785d23b09d8ce7f4e1e5cbcc7c20133d81f87c1d47b94f733631d5406c01f756ba7bbfbdca900eb2fa03f6b0a0bc1f06b9f3c3c9ea4d6d61","priv":"c4ce940b7e5cc0606f023daa3dd724d773e886d48af58c785fef7605b2524a16","pub":"03c89852febcb140ba3d5e9c95ba6ee843666ccaa69492ede61dec94e4e6f73949","addr":"3c04769875dca7cb3c6faddbf1960e1738118d7e"},{"mnemonic":"dash output lesson topic butter run ancient claw enlist approve chief observe","master":"8d37dc9da62db3dab7a0f209d8997dab75793704d6c18056f02b6768db414121","seed":"6ca57fc186a6eddbb0e8ac6dea4c1eb5d8361ca08d7b909a8e863284b38180cf8ddd2d9590f7611a5cb80bf1abcb679adde5646e69f62208557ab1a37e80394c","priv":"db5742d8734235964645a018fc4cead9402a113a60de0d7f55ab3816c9780e8e","pub":"03710b31603eef3e10abe51c57c62818ae65fc7f0aa4a91cba5f178a0cbdb313cb","addr":"742d17ad66f51524f28deadb3366859f14cf02ff"},{"mnemonic":"blouse maid inflict jungle yellow believe arrange cruise seat dust endless benefit","master":"d13daac6580c68186cb049fbb63c05bf2282919865c4018acd8446828dbf07fd","seed":"5b4132806e12b669813f1ab295ec58fc472fdb46769ea7181faf6e6b48f3cf4d8280e8ed5951306ed71b40d016afa3ecb71476a23f455ab6e41233ec2929ff0e","priv":"a8b701c1abda145e723d92fb246b692e44693704b52198ba33128267bba63155","pub":"032c532be31e8394d98571f3623372abafce8bdd0ef02c198544d0dc6a6fbc3cf4","addr":"4675d51ea6dddfd9b296532f3f2c101229cee094"},{"mnemonic":"only enlist indicate practice safe romance orient gallery cousin silk eager what","master":"2bee5e0de945af3aed16b2a06423d3447dc0c91af3ab8fb20b4fc0dfdd74bad6","seed":"92a6a62d9b145dfac6f66b7dbdc7bcd7b9ac10163541cb95e18e77742e3f2ce1773d74b0b290e40ecda2aff147bf81fa8997eb02668891a68912cf42cc666fc4","priv":"6a8e812a13716f00c5139220f1afc9a7ac584ed7553fbe8a13c50add54e5446c","pub":"0341a641547fc87d6a44abe879aef7b9f7c36e3491f221f667d10c568eee0fe99f","addr":"0fbd95b59a63b2a4238d6703ff49746a5950db8b"},{"mnemonic":"oppose fan kit prosper message pass fiction machine duty antenna planet ribbon","master":"6464d66007d3609d21971ad05877316fd8fc73a4b61d971676fcbdd32eec832f","seed":"36f65f329a478fc6cf1c9be171f9de9255affd1434ccc3420660a156b6cc0a85a10d5eb1547bdb5849325f5972b332afea7973449dee8a72db256479301337d4","priv":"94c741202799e22867b197c900c11e25855196e9e10e2f74f1939aefb7ddb233","pub":"020b86916271d84b2ea8f8b83ffded3b8f2bfbcb4ac17da7fd59c9ede27c00926a","addr":"d26eefcc75de9069e99c2e98699823b45effa9d9"},{"mnemonic":"acid summer coach step inform jewel secret tornado abuse kit shell guide","master":"4a10d5e6783e00d6f3453d8948dc5b39776de5690775aaa0a8429b2f11679ea0","seed":"46c698780417975feae4b6607e7728a00600e0e8e225d5d8f36ca076521238761c5b910759f70498e7dbda012d4325f3fe81011ca762c2eaa06649a18b79fc74","priv":"7d6a286693fdf1e51c26a64e5e5f8763b328934540b18001898537afa49e8b1c","pub":"0319013f6935be2eea7cdfe0544145708d24ffe9742a64b1a2d22f24bc5e380bf0","addr":"d53d22924ffcad0359a177345c32723e6260c7c4"},{"mnemonic":"general shed quick sea amused piece air infant jeans page eternal lens","master":"7b435a6cead581f339c1008061cadc687c40156312a8201c823158a6028cdb93","seed":"0843ac840c79c9c7dd85cadcea3496bc7a376592b07d233c35bdcfdd09725eff59f0ebc1d0cf255035ab5c7344adc3581dc543b134a5e70eca410b46596ee8c5","priv":"e61236f6e4557b45a6e39058b8606b7e3041de297cb0d39ad06c2e5414199d78","pub":"0241be261330b87c2388ab4077fbd4fab3a66e7d039d3ce4faad319c42b8e886e6","addr":"29777a50646b5f08eb7a428805a9778851d3116d"},{"mnemonic":"view hood trigger weapon dress roast load artefact dumb biology sadness receive","master":"a619455307c5edc87edfda01059cfdbb6c356e9f639b16b80b78e2421f1989c0","seed":"d89adefef230e418d7462194e5e1a817a0ade01435763ac5030ffe94fcf4b1f9d8a06090ff8a742d22d7a78e4a6392e35e8c318f5d0e495d0f8773ff126ab56c","priv":"1f9c2085c35b5fbf1a096174e7f11537b4f6d6327018dbf3b3311488865e5135","pub":"0208e02b8410833b43ab7674e25efd7081d6516aada029588f72a5478fa5c0aa20","addr":"cf4138b64094d8a9f58cb9068305a69ac50c4f0a"},{"mnemonic":"salon diary era brain chat panel design lawsuit behind practice please budget","master":"fce0a096c14774cc4bb44a4e9c65cf075a2ef5eebf96f08cb684455218f4dbe1","seed":"b154f70e78908ca26852b659a6f6252d83f3bbc4261cb1b9faa4ea80dbf1feb27958164163bf7ad82de0ff8b1af07c60f23b376910a24608c8af4b88aa0065ec","priv":"156d45c8db9bb83613334020e9b9486eafe16c1341aa05f4ed2095ff5a11dd66","pub":"0389bab1175f1cdd60a54828f8684c99c603d6b877597d1ab0349ce6a974fb9e68","addr":"f60cdc064ba139ed5ddcb6cfdf6c89ebdc378962"},{"mnemonic":"text horror panda eight mention victory wonder orange error few you illegal","master":"fd6c8375c6c3458be159f4c2fea8d25688163c7d306e17aa2dc32951eec2342d","seed":"ff314a8722d3291744c0ba07d569373771357795f72307366b0ee0c84b71ebd60a54d6f1c1c974bad1150e85415658f5d30fe76062d80468786fcc20ee8ee903","priv":"943fb32cbdd79c2e34ea72a9c31cddc3ebfb1a353808e471b77f54cd108f487c","pub":"02d17d74fcab59fac7d1cbea2838d5db3ecb1c24219b0b086ea1ea69559b8c2099","addr":"996916a8fe8dd544c1906a0afe4b48df43abb409"},{"mnemonic":"apart beach sibling debris chat hope toy happy bean same auction brother","master":"9eb93023f619ad35b6aba1051b791dbde9618bb74059632813b4e0f72b16c773","seed":"4fa270abbc1443fe7f593af42da0b40c17773eb7b9efc09c621b59424f84be65ed1ac755b88d71632a5a384c6dd679887c021dd91aa06fd9547f5c52bac8618f","priv":"3adc47b4297474a18744bf61f18e3030bbf58d68eccd4b0f9a207fc513edb851","pub":"037f6fe821009e2e043e66b167e7708d9534a543391b3ea17abf449f2807931462","addr":"6b9668671f23172dd08382e8db996dc9df687f80"},{"mnemonic":"tag bright bitter hedgehog stable level outside alter uncle hold have voice","master":"63157c3bb0a525d611de7539718f3b8de9f4f7a61bc9884d2f03ae0d30e7c5e7","seed":"e40b20a383e582f304c7feb315ae1bb405e9a5e12797706042d82918a19cada05fd28ca8615d929dfe7ea331d588ae3506cc3cae09f560bc13d544607e075ba9","priv":"8675ee046186c61b46576c02a8a7e5dea1d307667ceba7f6a56bca72fcd5452a","pub":"03654985961e5509210a31d1f54b15b37ff975717ef1f5ea7c2aafc76ced1b6326","addr":"972e9f2582e7ed35767b1b23ee73af4daeaf0b3e"},{"mnemonic":"wave fiction coral polar enough gauge whale magnet science second squirrel answer","master":"e2f288c51ea9bb3befc3245bc0739998db6199615869b4f27db9b613aa443549","seed":"2d9a178a3292c3f3987c35d44a3fdef2d849630ff49343bc5c3456a6701310c56cb0688d7a4bb7c3d58c40472d8a71121fb54f0108f6d682c648694f9ee85aa8","priv":"4a4d6db92c8cae67cb80b4f8fc7e63c94d3ce9ea67026c2544325c7c14c8318a","pub":"023cca73403af0fa0a0faba0545c21472996381917db6e481de9fc0de210dd4458","addr":"fdf8fbd1473714cc6dbac873822a7e0c7ffee153"},{"mnemonic":"process visa stuff pulse shop ability test aspect royal pipe protect fiscal","master":"742d13461d14c18707e2828f69b8deae3e13a9d6c90895993a788bf51f5f8eff","seed":"fc0ffaec77037a17923401aea05d7e37f09d2e7d35e9ad26a5dfa3de6e5da7c4b8c1d16e5ff6ca18570b069e1e8e49ef9ef475665e00cf189eef652e40d3553c","priv":"ef5da20d14c6d948536faf4ebfec5f11e430795986086371afb5a239befc3410","pub":"03a03b2dfd694a9d95ce1fd0f9c97f3db35c02aa001d26dc313c269f8a97bc1688","addr":"0d76c54b8af88721dcc4968dbe47607d7040d3cf"},{"mnemonic":"jar draft slab quarter during hawk grass monkey mandate prosper hour fortune","master":"98e2ccbe3470de355e090d69247d6506ee9bf82473d83fb98c20506543dc4fa7","seed":"e6bae0e46c8e66bbaedd465ed2669f9ca5b2bb68d829d237a1846763129932588a1aa4e69979a4eb3f73010d7c093b20a542efa2fddeaa00032abb847cc7bffd","priv":"9d1e402404867001cb24a3f501b676effb69865045e6ac2b0fcfdc34f9df494e","pub":"03f0bc42295a11b4ccf18b44659cb6d0e0eca3d2034c98f485f5ae43e07a82d90d","addr":"e1c21227bfe3c09188066ae189c7d499d855a600"},{"mnemonic":"camp vocal absent ostrich sleep version puzzle afraid execute clog eyebrow tissue","master":"fdabda4c563e3d7caec47b62f4f06ca53015f98b498676116e7b3df18a4b4412","seed":"b752500a4695f6cd66edb640021b2f590e85f4df2af298388f042cf7b665f0d6e643827bf705d3d1d9786e64bb5e184fb16e270ebffe0ce4ff7f37c285d28db0","priv":"32ade388afcf551e5b9195941ee3d290a39ab041dc9a2b748cc36c53cd43061e","pub":"0346e927eeb5549f8f38fa6280c0932947ef78f63b55410e872e0bf6988e64d03a","addr":"462344dcf5eb679f62d6470927d227365b208524"},{"mnemonic":"kite slogan all win burden staff actual oak cave bamboo advance uniform","master":"43888096d253b010da1f0369f75bc0d6a3b5f14dfbe5bccf7c8fe9bd78242205","seed":"b770074f2868e3aa42bfb76b444f782e4a109f2ed51677a79a69bda83dbdbff3a64b9ee163c57859f143a726d10aa73b223f0cdcdde6497fb95e0fc4a810f583","priv":"26533617dd8d7399f399d59f0f8a50c798668f04f44b52bf50728f20959c68e1","pub":"035ce21f82a71a8580d4bff49e520ab9815ac4d5b6cdcf6eaafefa4457dd9dea27","addr":"178918f829f9cd67d701c9a64b5bfba373a7c820"},{"mnemonic":"bind fire final soon dilemma analyst train ecology say drive slot bacon","master":"9aaeaa7f7a7deb8a976783f523695466b78117462804405e200ad1677e547125","seed":"155349996ca5a6fadb151c9ec425ca1e39df10509a8577f6e63096681c13b3980285777e515176feb7e4aba096b4d9d81a26b4d3477409432629a862669bef40","priv":"a890f151c33c87340a9021d3186c4df062822a3088fb7447bb419bbe5dbeb53f","pub":"0253d42cb2ab28f7fcdb2011e547dc88902e1e4d588e9261aff0869b118bcd4dc1","addr":"19b05c71780f27ec2e44ecab4c426108ea5a0f6c"},{"mnemonic":"image wool rug little visa embark poverty shop shield parent odor farm","master":"c68aae9896977ce21f5f547a4d0ea9995c9641c2a5f2cf89fd5a804485ec0e23","seed":"5c6885f90dfc1286f17b0079ed90dfc3974ce6b60d4193784b9668ec93725328ee5c0d027df1d551541a62fe2d87cc19cbdeed9a235a4510b738930dd3eb4eaf","priv":"d807cdd58fa84e4bda7fa998c8bbea12b7ecb5147c5edf841dcbce2c8663be43","pub":"0259b24a008d6ff4ce4d589e081ff100c28c3f8eb5440c8643257881f10da3658b","addr":"a20d7d609e6b2c855b9da18dea5f7ab3d091aee8"},{"mnemonic":"enrich soup all neither easily combine police ordinary review room keep swarm","master":"8265329602cac11df40567d54c8d4759bd9013c7a325c3d628b81640e95af3ce","seed":"3998bb700715a777bab05afae33a6e6553af17bf8c35eb67c7d4afcc38d6f35875c12f8602f381f797157102334f9c01c483f8fb41abb5f439ebefb76fe260c7","priv":"8956ffbb87e45ba0ac8f4142e179e6f934ca9b88d754fd5347c340a598878088","pub":"02af92f546047de11b15fb4a4c13c77ec6034248b84835f421826a44a68477fec6","addr":"7a6dbb8c88319d3076eb0b387dd2a9e4209b3229"},{"mnemonic":"tribe unfair track nephew erosion spike machine exist wine banner horn document","master":"c8e67f2accc6f9d543e1619dfda891664d349f11eae5617d32a9132c015b964a","seed":"ee1bddbc1eded07dbaf52feac014380400de9e006bbbb74f0c12095b381ba01a696ee3c3f62eaf4324e49b397755cef44667762ec46321f5762ef0e269dc9cc2","priv":"4caaf1ce46e2a6bf8e058fbf063da8683aaea07af831456522ae501d4d09d517","pub":"03df708621a45e5d5fa1108caebb51c513ed1616529aa6f89e3442a840aa37d73a","addr":"4d5e8ec1737a693fb2820994f4dd69291c5224d9"},{"mnemonic":"assume wet effort damp similar original salon aunt grant peasant fatal toast","master":"ea31d3203ecc33935024caac7c319223ff0f4b694cf011538521b318716cbdb3","seed":"11b227c8cf099bde463f72b505add695254eb9fc4714231e09e337f1499791ee2441bd5a148862265b6b5414d47f767398fa97a392a82a0c70648b4a52c1c2a7","priv":"f96a9c148945df0490611dfd06ca16f485a153e96857d746de0f2817cd2412c9","pub":"02b7b1c5e504b37104fd92465cdfda7261a60aad61b7b19b040d074fd07ec8ea39","addr":"036687e670428aab8b8057483c02ca0ea8dcc8eb"},{"mnemonic":"celery inspire ritual apart bring pause sugar monkey leaf tunnel minute alarm","master":"fd42c88307af74bce721f71af73cdc15eba0a186923fb9ff122d86597c1578ee","seed":"46042a350e5932c11cf735b60382d9a331a21f199cc484cdb9df4d8b9be0400c94d58ba1bc4d41826e605c625c7301bbc61e71f3da650d2928e83e07de6a9097","priv":"23c351e14d35d01f62da3cab73dacdc1c0ca052a76a41b58ae9d5c0a242e5fed","pub":"027ef3a78f366db4396cf1da6d124e31b254e90ad0c517267fb5a20a0f4034fc93","addr":"64a202ed14304b5f143d5d10a08167decc68fc53"},{"mnemonic":"text blanket lake damp doll guilt select torch midnight tumble toast dove","master":"c9653205120cceaf6cc768674a6389ee961403a4364e96220134acceed105299","seed":"79d5619f5dfeedd623bfdcd7d201f58ba55a2fbfd0424f32b9a220b4a39cd048e5cc82686e578b420cc35924e8fa31f1a4a29307dcedb35a4c69567da300b07f","priv":"7a7205d096a658f41be1d4d6b8a8644bf370c34a10a55f4a63ce1117d71715e6","pub":"029b2f32b98281d644232c4d603aaf89a98083edbc75b61f8aa5ad2c7ca910079d","addr":"ee416c1d1471a6d06b755fc92535f0bf1a2e3f4b"},{"mnemonic":"crime level shadow chronic rotate era reunion fossil boat shrug patient artefact","master":"fe8df8e3413387b50476e0ae97fe9f3851d5645f90b0bcf0b47b18d16387c057","seed":"0be8bda7509b72cc2d39c38609510fee439dc03600883e39f596cfc30cc2f48dbf14860ca33b7b7dd6f5f41f3d2fa71d20fe3995a698599605c5ea23b95917ce","priv":"4462e7a144223c97450b5d6728c6d017ed953490f7e762563993fa309152ddb0","pub":"0278a9fcb45bb02944c9cff032c013168943c6e0193c6ba6299af4397e8113a340","addr":"a925672e895976c8783d48180cedd09b2edd6108"},{"mnemonic":"chest flat tissue cousin defense ramp burst once rocket time super retreat","master":"7a8c847ca8357ab65fe99b5cca5d0b70bc8da05adc747c4c2f201fa1e22d753b","seed":"96003a7547f32ae6d8e5ce1bfbd5e580cc8c81d3eca4397e5e1453824b672a6d966d97fdd462ee8c0553d832c28c42fe61e78f01d056b2952a6589273ad57514","priv":"e4847fb09c9438d765da59b51c3dd825726ade929294007f9ccab300c100a2a6","pub":"032ebdaeaa817d8b8bd206839e18d17a85bc44ff4d7f0a5367c4f48098b511b43d","addr":"449402b089274c0b78b40e6f45e8297badfc1bc1"},{"mnemonic":"elegant dune all subject country diet flag universe gap ability hello torch","master":"fba87eced090b1d991c077467db81d22e2691f9b15ea2e8ccf03a51a556ee13e","seed":"1f1cd5b090411b96728a6959a4639e3b2bd68d4ea5c6ceb801a5849af109650237d2a6727ac80e7b317c625faa593d7a8caefae3ffbb55f110bd66672cf516e5","priv":"31cf4c4c7e75e35e16e01071e2db66a51758c8cc2b5df3377462046e4d87f3d2","pub":"03722bc559c95cdd7baf08a6965a47a7762fb974a854d290295bd853f6be0a83cb","addr":"b7f0dfb1c5136bd9bc267e9c7b33c047d6a1429e"},{"mnemonic":"give citizen chief eagle horse alien below flip vanish eye sniff bus","master":"c3dc631ea1b0226bfa3572fe9b95d72d08bd160cdd5fbc2fc96866adaa49a431","seed":"196d5c0aa7839623842c51f2e5593695ddb596bcd839c70af2940e8d00f31dd68b45876ae7aeefc6032e8b939b4feb8114ce9c403e4b83e28a49ea69a97360ca","priv":"9fbb966c19808bb2b7d07c420f4aa59f7a41cce08499c4da2bc216d857ce86d0","pub":"02650905aba484a16f7c1a2b1bcd0ed4f16f45d1770cce32ed127bc046d5f2c3e0","addr":"1441b38310ffb1135c2c48269746894accf627a0"},{"mnemonic":"gym term crawl benefit kite various pepper noble into slim try then","master":"e5826174e32bce315c7baa21ca97c613b4eb095d74651867671afd3848343668","seed":"198b6d6de96c726477cf8cdde784fc43a89dd46ee8fea27933ab8daf09826ad0d7bdaa0c50f8d5c574f6f2e6ef7adabd9c2382feaae061c9cb10a3ba22c5dcac","priv":"ec23afe15c13d5f0c86a47b18ca81761976442cd7c07975c88d6ad475771694f","pub":"0331ddb4db50ff58ac1709986111cbacada08344bab6210da4a2f23b0c3208e100","addr":"625e5b098af6c98677a9a2cba960e84c11dfcee1"},{"mnemonic":"pause web there legal eight plug wheat convince adapt radar rely inquiry","master":"b13d46f4a0c6ef2cac56cb9c522dc35b8d02f4ed4f09f524d206e9ea6e6e6082","seed":"5f34196fb26a7bf0a9063284f702d934c03eb2ac10f3dc230a999e9566d3561b9dc0a61d199e7d9642b06474c08f9e12e618ac5cc1d805ec9cb9489d460f377f","priv":"b410cd330abf2a25f36b24fcbf72f73e5c62786cb5c0c24fdbc3cdf6ceb892f6","pub":"03755fa255c3f111f778c270f991a5cc0fc24c0068d78355ce340258aa7a3b81ce","addr":"170438465b203b844f98cf54b49cdf17094afd80"},{"mnemonic":"thought morning dad seat payment ball club goat man urge forget remain","master":"af52a1f224909be5cd5e7be0b960a995c1d25652cc0c6791060b98e1aab4ca9e","seed":"1e9bd47b5411fcdb8145b9eb1e7092eb218774c85da6efa3756e9a55e5ddc2153eeb568139c638af44cfe6cdc2a570451ed68c801dc2ff726b45ed43e8fd0691","priv":"5e42b1c08965620e1e647e89fe87c9079060121f5a0b65a5ca8cc462fdd13b20","pub":"03a7ca8e9445a67a6884f58e0e79b1571b34b90dad6df4c0b8dfd103e500bcb20d","addr":"f44393294c3f1369012836ab432386f1af2cce44"},{"mnemonic":"twenty memory ten own runway grocery polar dog curious program gap country","master":"f08104e81f54a7bdb17ee647c06009667d4d1ac6efe286495bcf2327c229adcd","seed":"10d3111f871ce9bda4a790e148657f6dae8586d0d80379d40e56cbf180876ef7ea5f2a66f006a8a8a46c7de99a4e4f8f5fa4cd1a3756a38a71971298af917d21","priv":"db3cc8657599d42858ee1f1a7480e68ee8cfecc0fbcca01556c1fe5e8f3a0025","pub":"02add58efeceddf43db9f3d12b54dcc1f1369f152d427a7ad5e3c8de5de23a16e3","addr":"eb30fff2557ca87addcffc02d3a237fd28511799"},{"mnemonic":"elevator sock worry budget skull bitter faith taste skill physical mass heavy","master":"bb2b406a20bc8b38709251d1cabf4631428e2ac053154db69e2f1c6d236c4716","seed":"71fd4f050ec95c4147aed32ea34bc065e67635315b1077a0e9453d883b0a4519015ebd5de2ad0f2a628c20881567532f3b679541e23892eca14d5ebf4456a8b0","priv":"ae56d8b12dd0cc788ec4d5eed7153b108aad7606d2f3653ba5c61bae06dd1cf2","pub":"0347f3d0ed7552ac8d667036f4403911b7a98f71cc1730223e74fee4194d0aeebf","addr":"98198786f5e46f72ac47e88168ede1378404ee70"},{"mnemonic":"message power uncle glimpse repair coin wasp flower alpha claim federal tourist","master":"28f596f188bfd9a0f1ba2729260fc20ecc1c1b67a20bc8a4f7bc0e810a625ec5","seed":"5a23114eb877a016fcbc82146957d2b9880ac79582776fecad126fd6b5aa81343cdc69c46f29ad17e19411f0f4e78817338a9fd39a72efcbad31ab965f8782ea","priv":"1376caa21630e355fe38924afbacded452c9552eafbd5b60dbf090fedae3d793","pub":"02713f022ea80f4807af048cd254ed4dc5a1276c21e4a7436306f83731843a5402","addr":"8a1cdab91bb44b089a51f0a736e914a37cdf20e0"},{"mnemonic":"infant walk right wave helmet punch alone path since output fashion isolate","master":"0de852a741c097122fccfc397d9ec55223ec1a6ef395c1848097a45aa6a4f0c5","seed":"d1fbf777f64ac5ab0375876dab5e934794782c73e84dfcb19a291a6a083d6aa6d0d3de7e8c804a8c02875ea5fa54a06159538f98f9174bc6cf69ec94e3bc682c","priv":"0fa223b1f217baf7a296e483ded5e6ee97facd5841fb85c78b5ecc4db7681838","pub":"0276da67ef9f098a2ee3a3a18d4ca17705448694f895c6ffc97959fd6507e904cc","addr":"02aacee8fb5e56f4b39fcbf7253b7a1302b0d8d6"},{"mnemonic":"type squeeze vocal monkey baby scale behind knife cherry luggage struggle what","master":"1e156273aae1d8c0b58558726d2f19924b1d06659adbe3539134f58a8a1ff82a","seed":"333847666190d4b5c9535920c47a6f68c586aa3f587cb7349542c0a30950f7208b3467ed437cd815007b11a4326f20b34f45335ba64cf9bcf17ef71aa10b9b86","priv":"c307afbc58b3561c7d276502e1b81de8b01c196bbdc1ccbde5855e00707f58ca","pub":"031a16f0dfd054f5d97233ce07cf647ad598a84177baa82d2f89a7f23cd0f2a0d7","addr":"3b1d109cab9545dbbe82631dd4f903b43cd79bcd"},{"mnemonic":"elder shallow catch anchor slice hundred kangaroo stereo myth proud clarify open","master":"babfd17c1c9647175a7b2739eb700c3385be4948f97d1dcd50cd17fbd605d6d2","seed":"eeb063599bfcd2520f7f07b3eb885cb83953ef9931926db8d1e76b689954ca902c6edb785af6d579ffe89f9253f5864cf21d3f7373986a6c1259e4bd0bd16437","priv":"652f38771bbddf64d2040c1300c317c42739f50839b604cc8f34e050b4590a95","pub":"02608acfabfda5579dae5d9efd4a191925864aa656e55b039da9736a874d46b8cc","addr":"f14a9e2a34c1cd6b95fdd473ddd799429fc03def"},{"mnemonic":"screen slim squirrel fox stairs still close club day satisfy either sentence","master":"a0101753f4e05c8ab9bfb6224120ef9c1f99ebaebc31c5aae114f68387676f5a","seed":"c1ec85f49b1928ed7ac6dc781703a66ef39692ba39f5296d9da33f93fd68cd85b0eb57cfb6ea115ceba67df15e4d835d813e3bbeea0363ef513220b98768316e","priv":"91af59d9bb62c2a2f0bf1b5c8729f2be88cc82e141fa045e59748f2b156b9a03","pub":"03a76d83455b42964c021906265a4e006d2c81555c8591a641ac0c495cd0d05cdf","addr":"093ad2a9be7153222002d94eefadef04ca7ea811"},{"mnemonic":"insect deer physical dog aunt metal super soda antenna broken undo athlete","master":"d3a4a655aafd0dd18e196b2f4e57bd4b1d27fe521f9312104ab75ac92ad92e62","seed":"9975a73239f3e2543108bec6d75c5c9a24261c9b2ffd0e088f6bc8369804b70ce99ddbced3c4cc2e1cd955be824f5d881af09e5ed403d7da2a533c73d9d82df8","priv":"0a313ab091f7fda44e92ba2482b8fe1294646bc9d27865bfb34ccd702376328e","pub":"02ff6999ead46c520026b1faa27004851fe1b2295e5f8b79ee1e87b330c45216d5","addr":"e3ba9de7fc81b75eaf4c6ff126b434dfda0a5008"},{"mnemonic":"layer embody trade slice odor deny please small clerk device ceiling right","master":"2b39b4a5aa164609c2734c00c1029534c5d7f3bc6b94268758acb506bb139608","seed":"1bd10cd1d50db3dd8f9e76ecf39b846d3a2aa44be383868921b155c03ed3485d52236c49783f5334c60e473458be3b3f588b9ac3e814d144128d96fbc002393a","priv":"5953e09dbaa56a12eb5e69231835924c0e38d5c322a43c354152a0333f26756a","pub":"02254c4d6976965f7c6122efdd52f65ee9e25b87549789499b72bf5d7213829d04","addr":"603d5b893cc41223eff641fc1a374a3ce97138a7"},{"mnemonic":"token heavy lazy little dry glass riot hobby keen blur wise okay","master":"7d84cf25bd5f7dabbdb7beae83d1fd128390b3a0fbf2d56b44fd34a7e0d11539","seed":"8f144bce2e5c73f44e5dd62ef4695c6e3457ddc37f64d1552e5b46a771120ccac23cd592b27a135c3593f8f21eff22625ca7bae8581f4f8ed223e813f5d98a6d","priv":"37d2c3993b275606241307c7b2339e304180555df260f18f524abcc75abfb0f3","pub":"02aa996bf4d889c9b37aacbd07d8ac3ea69e535c065a4b4258844b10c2a08eab8d","addr":"4a3860dc280c75a00382f3d8f11cfa01fda90188"},{"mnemonic":"tray drink color across armor spawn vast skin debate huge surround play","master":"e0cb1eb09b82bcd37fa63260e49222cf13b0b07cc1568aeb8849b538bda65a1f","seed":"faab52fca3060d1903e861706b57ca50ca71befd2d5363031128235cbb80e53ec943362f2288fcd1c850e94cf4e7c38029dff1880dc3f8c8bd440b14ed15fd01","priv":"747aaf84f110aefb34026ca0492894ccb8e0d1b34c5b0f9a9027320289914b52","pub":"022d3e35a5f51a6be1d0aff686e66e2fe282e42a51044ddca65b8a7659b6386f3c","addr":"43057d3d99231163cca42fe248b9d350ad7ae146"},{"mnemonic":"ring act drill burden sunny someone riot spawn uncover sauce today jeans","master":"676a5a20f35054b4f7ceb22d38226df0b2fa192b6bbdce9a96fba2b51845322d","seed":"979a3caac9130fab128a59243447f5add05251ad385f0c0ecca60920cc954ec516479aaf4def728770606db840088242a8bd5c3758f1ecfa7d3f8d54beb5cd6e","priv":"0e3f2306a70147cb332877343ff260e18c37d807d1ada3db3545dc21cb7adf71","pub":"03374f7d18335d1677902e2fb7c7afb6c3646ab18bc76d12793b86e0097d2b79fe","addr":"4f65a8364edc65cc430f4916af41cbf339c34a4f"},{"mnemonic":"title reopen welcome pottery stand safe scrap little razor rate oval rabbit","master":"600c330dca29a426ecae0e5e6dfcb13e004efcfcab0fcecab676e42462caded3","seed":"7554d02d091605c47acf117773dfb96821e28c551c2c5e855803f79f7ec9b9e5a4a7273c605c2a53771e045bcada466d3b4a88d03a7fcc1644d990a8dcb21ff8","priv":"79621755dac86e6026853bcd0d4c032b48b7c5eabf81cbf8ca4e9d056fcec5a8","pub":"03f63693949fdc2b62cabc47059e8b1d9ba748800bf08a30001e19aee33627d189","addr":"ae0c6ad31b94b29d502a846e1e371356a96a4f2d"},{"mnemonic":"hat stereo gold maple advance wreck poet dawn excite midnight kind type","master":"661d8b63856089b6f3d6bb37558d4deba395c7ea7797d022db398c3224696316","seed":"b13cc53d42e9726cdd9fda4279a660d987dc3d302409a0ccc844731ae1b138495200bd1ddee3912124dbe826e62567a9b9fb57a33b638cbc4a56f8b55df3182f","priv":"548da8b9469029522189b9d4e30f6b58c75f234f18b99d4f4dffd027b6e022ed","pub":"032df4ae6e9e3ed444bc1fe3eba670f2d877de7e579309fe3e7a8ea3b5176999e1","addr":"f94c66a0851fbdb52cb7b6774c736cfe4f99edae"},{"mnemonic":"image wolf among domain where post bicycle perfect cloth october bonus plug","master":"1751c464935d8be5b1f43188a61f14d0f509cbe289d5e586f1c5057299c05d56","seed":"80bc37cd3dacb7020735655be8a001ea26bd8a5a74d950a5ba3f31603bd929531d6da39d06499927e5acaaef4845b3403e73e3bbc7a43434242dd2b432f17529","priv":"38db8c107323379d07ec59fa7b76ceb436a5430468562fbabdecf4bd0a06d58a","pub":"02c5e7d3d224db89285ff2f71c27a68b267f9fd799f05ee334084edd4b91d4071c","addr":"40551f9071d46824a15fba194d98425698145795"},{"mnemonic":"squirrel grit cross witness wagon defense marriage tonight absurd organ load sing","master":"d5739288f3d99e1759690e2d68e5ba543151cd58a0d55d0be52f0a4cfcdc2a3d","seed":"a3e09aa4755d4a4c48f4611a7a8c22040feca1694415b2a6976d2ce161102557f5e855d5195b0132c9e7f23e01b825465eaa10b19ed323647ea5beac8a635e75","priv":"055f00180e4bf6548ba7b525236f63444808c0052fabc4eb14cdad2debf499a7","pub":"03f9831a1213aedf436bdd9e898f1d571ed6a7858f0168d60afce7ac389dc27d86","addr":"8a1289c49f8d83275e4c2201c87ded060ab38a36"},{"mnemonic":"cloth diamond test stay also risk music unit beauty escape trip draw","master":"6d16a7ccf9577b8948afab2ac83cb12ea124e9cf86506e6d08f3fd685ba97a71","seed":"d67dbc3d1e00b7703a7a44b91ddb891d89128f59d2f298b2a48f464aaea9852b97fd3002569d9e4b8a1cebf0d7eef3b708a944b1cb745844fc01b71829bbb2ac","priv":"d52b78224b5e2b9d074b4141dba1956b33f66ec7e8e271a20786d04136d1755a","pub":"020fd792486b8d8777b9910bcb1c28c52fdbaf239e07885b94ebf85edca05f3609","addr":"f571651ea3de2e84b53da4af619b1c51acdf9c13"},{"mnemonic":"vanish slush budget question demise bargain inner push weasel clay project project","master":"11828853c3e89d3515ac8c838d2a5107079c93695c430e2d5383fff8a0a98de2","seed":"9f838e1b4140cefd6857ecda55690fdf36bf4bf0247833801a481130844a89d0483b05e9cd1042a855714f67298a3f9d8cc093e6bf9e86b4c7bf16223f4f89d8","priv":"2e5945a384de4ed1030a299e8dddd2c9ca20aff939641e3cdbb00f5619b186f0","pub":"03a52a0f153c92a5fcde0f004c4ab3166f040b6e7e609afee6c2d0e494c18e7a75","addr":"09e3386e3636e365d8bfd15e822b0cb50136b5ba"},{"mnemonic":"blind desk mobile debate orchard nerve crack tower little scrub twist fantasy","master":"4d677a558cc1d0911ccea1c14c817b8fea57668f9a81af43ed036a1bbbd8b6ba","seed":"eb67d96512b6136ce060c7b7800fe48a8fc2ebf50a6051f4be4255a5e974fa0443f0c5ce1efb0b0a87f227b0da5d740452313d86561a42262e5681864b529054","priv":"d54dea50a4dbc94530ed3c04771c6f4c71487cf3562e89b79684fd6ab7843846","pub":"032622eaf55666e30dc53d73a88517f24a08f6ad703f02db30e87368c5344cbb17","addr":"eaf15d884294d6b72b618c55206db3685e1b0532"},{"mnemonic":"thumb nurse there alcohol legal agent abandon sight pill street speed catalog","master":"1a041414d1258b30a589e61e6d8ba19a34ca2b2e8bca68962c0c9dad5863f5a4","seed":"1b539679974f7355ee02c9d6609640acdae476ea23bc7d5982604e20009bf3ec153f9ec82fcae5de92570d2bf94672047557a36b3ad3f3ec03b910038658b816","priv":"5ee3c0258920c32da893a0fa051593544fd3547c6e37123ef9d6edaea940dfc3","pub":"03e8714f4d3e9c3e342dae646deb62c31cf3a4bda119a820b0ff6810b8e3d85383","addr":"a3eeef1bfc965df2fe15abf7cbf19b381a458478"},{"mnemonic":"crew venture wall front gesture jaguar often arm fly scare lunar guide","master":"656a72d27ab1a5fb50e27fb598037dc2ebf60b1b9f0bf7612a8490c1efed6b39","seed":"1cd2a5e644dfe51e367da6784848ec64ab3c4965818dd3529f00efdc102388b02dedb2207052bfaabb32a4039f76594b006aec871dbe9856f2b71fe6f426d75b","priv":"67cc3ba8f7d83c6d08737e1b56dfe469c21500f20fac09e8bc096a091682ae73","pub":"03ca0d6eac7a2663451d29012c25bcf469d12c556f30a57a34fe6d66d27d506db4","addr":"5acc54542938330e6961c6ee770760c135ede717"},{"mnemonic":"survey never crew section reward cotton praise ketchup treat suit knock text","master":"7175659726fd0ffbbd37fd2c7e309589d32b271672ca5459b7e1daf5f2daa105","seed":"a5a37f251e3c745169bed474c8ae6599da847ea473da32b8ff922f2c710a3c31034dfc45dee514af90246bbb1317e21669ccaa0666d3c88c8f729fddfb95d240","priv":"fdd98704f53d7ad0e43ae71437626048fe23f71c24a67f31b9491b60c4db3c9e","pub":"026936de280e31c060bcbc777bf28ed1ccd0128be0c25f9d074378f72db1de0f4a","addr":"997434efd190bbf98541832fc48283ff736a067e"},{"mnemonic":"lonely physical plastic final cool beef cloth chaos dizzy enough whale farm","master":"79842f02a7d39d8f19373fb1ca3c73f1961c916628279a00c96a980cdeade871","seed":"f957d8197386bd4ed6c5000bbbd02f70d6b4b76953dc6a3e36f021d488cec54293198f64fe6d46c52041bd34efbceb1e6cce3184a42c8fd37903b924112ba2f6","priv":"d58df19dab225b29ea77bfbcda84c2f1982ccb6e1eb79011bde7adcc03b95050","pub":"024ed971b9763ad9aa8be27d9b75d9ff2f443594da5e3e0b7a598c71f6c2e0d759","addr":"f4d72185f769724b50be932caf960a1a3951ea84"},{"mnemonic":"can three trend breeze spatial puzzle stool cherry raccoon sauce bounce balcony","master":"e76d9d768fe3ead9a6c1b561649b292d8659a6778442f9451a8fdd52e35637d7","seed":"85aae0e7a3e2efd67741cb0d752a078b250deb53927bea3f384d72661889409389188f267d7be61629c6a85aa7dc5b2607a066f32ac39a2c5efc4720b4a72e7e","priv":"57a934f4fdbb619a40394cda13acd1fc61ed9f17e4b4fcbcac2248b5703eb71e","pub":"02004c3736772a2cb507231b7ab75bfc7c1d35ca9e49523f1076e7d0925acce8ce","addr":"859915a9f70f142a41b0d169e7ec342061fbebdf"},{"mnemonic":"gaze example quote much tourist pitch victory common lazy message random glad","master":"6fdb41e8f54d6f123c75856c1c13caccb01bbd7e84b1c3385fb5fdb885f72f09","seed":"bdb5196003c1d1d272367b12affaa4d0cb37fb3aeea88bde6992dfd3519af34e94729ebc9e8057b9e462c064292a7cac18eeb838ec0f71b082cfd66bece3c5e4","priv":"1f264f1e86de3b28ea8f4827dee679787e60e34e81271139a8e74870518bce27","pub":"035e75a0beff3188c9d5aea7a760b879413ef712d98354b702aedc3385d58c903d","addr":"67c21921fa2c47c5657ae2434c29f447511fbab2"},{"mnemonic":"taste panda wreck guard trend blush armor giant innocent palm trouble silly","master":"8f3c32829998fdb3355b3a88caf484eaf7d67122c991c2402d77eb3e5e4f8416","seed":"fcf9f308ac99d81e74329f60787fd311848a2e56384202c37c025bafeb7022e4b47ca24a680d07d073566c487f39c8c0dc4bf43569b73f30ba4a2c260ce98e28","priv":"463194496ba851f6455e8298a0d4c118341bb0183c73c2d7739ef2c5bee38e0e","pub":"034a87ade739d3da37c8f15928db9b064bd1d1af0c10ffbb9f2027f42061c9bdf2","addr":"b0afd62cbf962672d092732872a6ab2795c9132c"},{"mnemonic":"tragic enter actress believe nominee floor vehicle dinner bulb useful case bamboo","master":"66f8cb0425dd278236de1352e9b2e47fbb8662d1de9d31227c4f18873b6aaf4d","seed":"5f0f5113b93be9036f009972fc49d9fa444c0dc4f89ad2e5d590f33b2aee250194494bfff047f8c9cc0261208d0d842f4c8a320d68f852c0938b6dd472a9c819","priv":"3fcea63ea530b9539af1ea66f5ceca1acc508fcf21a0d5ac21a378af5aabfb37","pub":"0256ac4246f19dbd12af232b2fe00efd158624ea48728b3a647c8237b7b9c1fe56","addr":"13804f3f5f0ba3c8f769b2e3428962f4ae88e4b0"},{"mnemonic":"between grocery tool polar already roast cash budget fatigue museum obvious notable","master":"c13b5bb1840f804c9b1da51fdb788f9262fad64b4c576370ede2d9c4001de2fe","seed":"1e5a866e10ee3ed7e727f59673328eae03808cfdb1bd3c9f155a1ce8f7c9bee61fd8d68d6b995588c0264400780467313ba92a9c359edc48ca59dcfff62567c4","priv":"08d7d4fa44f89fddc836ea265b71e9985363cf4e9ba0cb5b1ef0bfcbd00e0aa4","pub":"03514e8e0c990a6a60b1138351255827c7c46e15c3bc25f55946276b5fc56d9068","addr":"0c759c31f5f142dac57e712c7a09c99a3a0875ba"},{"mnemonic":"combine unique pig mind pair area chase idea abstract grow into result","master":"e7d06819461fbfccd1e05b6d63507b179854fd75fe7fcce2cd04ad6eb89fd11d","seed":"a1863842b2a6d82dca20ece807c12c58f6c4d2d1fcfc2577baa368a3a45a7ccb0650009ab558bc8350b77f9a03f6155e8c35f76ebf9b30133dc732ef5abe69cb","priv":"a545f01810112491c613a35c829157cc6a3dbd30b4b51f1d1eaa53fefb61e09b","pub":"02008752e98ab20e0fc8c9859884f97423c2315f5f35d1d757907b0affda7da9de","addr":"353ac98ae22d3161ce81bed93d7a0d77abd9e11a"},{"mnemonic":"bonus voyage inject they glory wreck soldier anchor also job cattle random","master":"cc5593732d2681a1aed33672cfe74f24238443d1b118235550834e14bc720235","seed":"ae6175dae17f8ab7481092eac1ee7d4c08d9ffeb69850745a1507c63426aaee1ef3bc6ae7fad3152d9bcb58e77a14a9570a4c550078c963991b215db64a2e9eb","priv":"45118b84fd5c7802b71fead3d78e5953e1841ccb4d4cddc20aa154e9fbfcf467","pub":"02a0378a67714f50eb383b47f7ab67b32c2adc2b8376b12da9e656ef11da9172c7","addr":"aa4e5ff5d78486413eef80525d20fc0a46befd5c"},{"mnemonic":"axis grace advance retreat fence prison traffic shield visual evoke upper they","master":"b0f1e554c9c4c38355939ec8641548df255dc8260ee2beb02eea8436359731fe","seed":"42d47d86e0eba00ac90f92e464cb034b25e3e261618ccb7893524e6103b8ab8edac9262e7417ca55cec0e5b90f0405d6b43b920317597d8b67c34f909b308ad9","priv":"0e986b99de5e1403218a3d6e64eda2c6e980002fc9345795464c6e100c4d214f","pub":"028193d72358fde04b71d553794171a3f6800d2d20d1d4821c2d411d9dcab044f0","addr":"68ef0232b6199e173a31b522f73b8740807e7991"},{"mnemonic":"speed advice script dynamic company foam mimic conduct wasp soft stick insane","master":"b0f61b56e248b14dc116231490779949a829920a9caf582fe25df4459e65108d","seed":"7b8b72a1bff2551f2e704e68f364b8d578e24bd6c51fead9805c2c33bf463dd462c793f73b88ca6353e8385a5baeba2c91e4efd6ccc2b80351cfed9d9a6d7738","priv":"32e5a08edf79a3192b221f978e209fee7f7d64f83c28ff57f47ff5757b727b14","pub":"02fa4ba71ba618ce2f1508b0386ceb0e09e202722353d9724a597cd680130c53e3","addr":"713ae3fbba6df605c843147183dfbf3a3fdd86c4"},{"mnemonic":"punch fame nasty actual betray melt find wink cross hobby double there","master":"a7bb2a4a7cc93d7dc12efe29071329febba1c999c4e7766172d9e53fe29cb0c8","seed":"6876d29989880fd1bae26463cd01cb148c68ea842603822657d0bdc708a8987cd33453087febfeda2f3ea53f2fcd65ee1c5f89b0cfd8aefefee2c81ed32c91e0","priv":"731b30c783b7cfeb7458db1e0c0db2586216b6ba661f1adff761977c782d24ef","pub":"03ee75f400c95ecc4b852cd1ea2b434f5cbdd2f6eb8a881f0f24a3d1098a6ce778","addr":"96ce0c791931f867dc4fddd2f091a552f1e57d26"},{"mnemonic":"feed session repair glad envelope pepper faculty earn hour slender cost boat","master":"d8507e0bbacaa494dd65a38d82c02f00d168ec8bdff9991f78ed5fc13ba81d38","seed":"aa9ac398fd8c94bef20e9b9a94bdb81fcafaec2453efaa2929730145528495515d7632de9cf558313a35d50c0428a15f01efc831379a696f632705bba7394ce8","priv":"ef95d3d563a0e774c8d486adeb2d22f4fcf4cddd80cd2a05471b691c12cfe0fd","pub":"026b711c8ed8ea414276c9d7c7a92739a350cbf01372d41c2160c046e1459223be","addr":"72da6e869b7d435ff2507e658acb26e0a50e6303"},{"mnemonic":"person affair gesture cherry intact day wrestle crew okay express throw large","master":"84a10e3f12a6d24e76cd66e934116f9478d8b1bf912fc61c9e00058f7c489f6a","seed":"5dbd3c2fe715a4dd9ca5129df8fddac1f699429636a58bcc2379791af11dcd77bd9b84f3d62539bf5eb41eb8fc966304cf334cc46133b7e42104a18733514777","priv":"337a826c33caf41a74b465c6981986d629c13a71aeef4c0e7c2b78fc3dff613b","pub":"03edadf784d13c4e22b33b61222e20348cc68e245d8b143dde09d37963e9e01eef","addr":"916fd4d732155d78fd412b4cd78abb49bac56c19"},{"mnemonic":"nose talent woman drip regular endless bar resemble friend mean frog cage","master":"1beb38f144a90141600a34813e98ac3cca43009e23c542b3009f3e22988b9705","seed":"aa324508ec3951c30fa4b32ca7a4ea48773c572652076a2a7e6aadec3faee23c3388663002b086483f39a1b08fd50ff233ddefded05f583211686d0323dd4d64","priv":"67109cb296022e46fbd12569cbbaeecec1843479bc716f7ed07ff996561f8196","pub":"03239409138ec1b5a60e5d72f894e95d599be18978d9f43bf201c85bc20210b473","addr":"580cdfe5a38f37a644204cd1d4b0094dffb982d6"},{"mnemonic":"undo thrive relax ancient menu milk sand race bargain evidence steak tomorrow","master":"1db1b33c9f26783cf9743ec719022a1280c8257ba11b2b03f35455cdfeb10ddb","seed":"b9905331927ef09ae2dbf5bec382cf3f18bd9cc03bbd4d21e8f63cbde32cd22abf07bdea578a201558f2a1f09f2fec8e3c7557f731a57439f1e348bd7530d9f3","priv":"c91c34d1a5218ecbfb63990b636d8bcbf6d7ba4723b70c960597f1b4ffb2854b","pub":"03c7d4b726c2ef316d8e60f0941e2af09c0cc1a9967aed825c322b629f74ebbab0","addr":"cbc5acf5001cb4d88fe88404cf3d1a919b127aa5"},{"mnemonic":"relax owner update nice speak office assault pottery uphold clump since ball","master":"5540b4c874952470d93f8a94689bd58c03c8bff373c74890e70b63caf9b5fe48","seed":"c3e8c04ce0d472761c468cdc13d04cd8fee5333a806259657923aad79d9bab8333329353e69cd3fc67833a7041a2c49f3c2b0654a4d243415f3f2761a4f7fa29","priv":"882ea08c9157b6bbfd686007ad668de373f34dbeb08e5d983a447a12c9efad3e","pub":"022f8b50589f2413d294e33de8fcac751c4c6ae54b359ba428c4a1ae28cd2ff57f","addr":"6ec1ae2736cb2a9e1dae6b5d5c7d408347db2dce"},{"mnemonic":"immune find story sadness depend debris popular swallow egg gauge firm drop","master":"fa46f28a8f32770393d3a3fd934141823d48ae561d8952ef3ac87839867840c7","seed":"6b5234df2c1b9ecb85d8493849e66186f98a828287e133cffc210140d63bee412ec58ede1968c2999485ef80710a83a99e7ffe205c404c5bda7346369c16f6fa","priv":"77cc4d765ee74267ea50ce3637ff9916370802a4940bffc8f7b76aac869ef80d","pub":"037d1e64685d2229c9b49baf2245511b3dc26733e1275c36f60555e2eeee32aead","addr":"80d9e410145ca65c65f143804e7e13f0572693af"},{"mnemonic":"airport refuse lake shuffle borrow depend agree oven huge hen brand reward","master":"b21a47b26023f1ed1963f81a2ec424c88520055cb2d69c329c76e6a354cccf91","seed":"7ae802a81c37abaf146f9c7606409640c53a3502da921347dbc260fc4fa5a164ec458480038ac10a3dc2c5ec15c600e72e011392413e13b9daeea82c2e9ef611","priv":"748f3e6cb6caafe5a188d528557ec1c1e817f990394bea8a011e3cbf6d00a3ec","pub":"029f0f4e5bf957c569e9cbb814295acaa1bb8bbdd549844246f86656ab700cd35f","addr":"005b3c2696248d3e45b43c88e258b2dee69ae542"},{"mnemonic":"slim trap alone fetch people skate middle since yard frown during smile","master":"1db54486ad20e5fd82e7c5bcab652cd01632014d66ccf0f7d6c39bc0a337fd77","seed":"30c3948e518b8ca06625fd7a1318984997ff587aa865207b54d5c9c469386e66e06656fe020665501a1f0a07636a250ddf5c127d5bd9ec497052b9e4ff2dc37d","priv":"0ce3645a3f7a1ae02535852fbfee9c59609eeb226a975ae24c94b7a13acb4d85","pub":"03b3f40812780bd4f8a596c0131ced87b9b981e4950f5217f44de7f777b4d29b35","addr":"7777090b6e5ae18d4a146a0c9c17a1a34cde74da"},{"mnemonic":"vague melody fine buffalo spread nation reduce spirit humor fruit spin diary","master":"7a5951d167793eb5d42307c68a3997fec7c34d56562dcab752c2559b97507e3c","seed":"aeb4a2ee7a25712bb76b26c654f5a79b4e92c25689799de2a11283a668aabc3d967d111e2bd98691dc2b72adb66188888999e0ce03ab2bf1b18e8d5d7f8c528d","priv":"d2dd273a93786422dc68e61e67dc0c48402af5964f85d5d785476bbcc68e99c5","pub":"0347a23bf9c802d6d826367a34219ff155a720b068bb0cc4f9c679d350f35a978a","addr":"88679cd2c43e562c21738ba5ffc8bff82575bc6d"},{"mnemonic":"ahead glad fame hip era kite pyramid endless sponsor tissue winner kite","master":"eafe3d2af7a63b644668dfd23b7f0868a1d6527b630860f79838fc520896e64e","seed":"91f06eed5517fa2367c272a18362085775cc9d8f13b2358ab32d0c626abd87aefb8ffdd1f37712d4c39fb625ff4aa56cfe06a3054e162bb62fb03755a19f970a","priv":"c8d580087355904e691ad5292775989853e59ce1d41d224f97d2d4b96f8514d1","pub":"0342c4be0ea075609aa181fb83ffa189ec9744c2a7c54f7d3fa2273ba01ae127e8","addr":"ebd946e96a89c8932ec788d66f3fe8c482622831"},{"mnemonic":"clump earth diary ostrich section column practice rapid hotel mom client adjust","master":"c6be4ea8b2810f07731b7258f2a2cf4a4bd0722e43081957bd74ccb5955bed55","seed":"04c2178510fe5f7afe60cf8718bc5240da95cc2a79d28fb2bce756a2fb0995f25c5921addae1932dcc4b62ee68b330d3abfe190f212f809816ee7c6d5b816095","priv":"d2ecfc9fffd24c8299647fc2f23a16a2e5b35ec6092563ae731d4737159ce03d","pub":"027c615b33b69f5599cb800a85073582bb2180f20bedd1bb3e8384bada13ab8f92","addr":"df913518315ba257805f9ea9f78c859428d101d9"},{"mnemonic":"teach salt dinner dinner escape cheap gate major bind armor dash gallery","master":"954d52c8574645c888e4eea6ca661fd1ca4764ca9e4243bc75610571a24ec5ac","seed":"7c3753fb498e2a48af89e5a39153382eb9591eb8a5bb2cc5b8bf690bb6d1365162bccfbc9d5e3688f48352f1f8915c376dfacc3c3cad9315fa60cb303161ac77","priv":"c3a850ce632a7ab061e378596cb4c66a6880d41f6b09b0868d8c7e96bde490fe","pub":"02a615c68dd2bb66d3cc9d7e46a0fa00510542471a19b1d48fe05355acf38903b6","addr":"db50721f5b6e0907490990182793ae796756bc7b"},{"mnemonic":"cement casino erupt clever gasp benefit response invest diet banner month hill","master":"97c777e73bebf40d39c4efe8fb74db3cedcf2e1ebd366520515ee2823a9c4d28","seed":"9344a709e0d53322b928e3128d1bc707216eb0e1ebb137f74fbde6cd066f88b86088793a5794df8cfbd6efb12c843399e8ccb958446fa558573b013d33236436","priv":"96464373c492c388bc4a2c421ed0f5017fb426ac95e55f0f322703b28012cf90","pub":"03e71c89b2629c032b6c9a35b46d572dd0db3dde47bd5919bed8457885553148b1","addr":"493af641ce946561f6cb3116a135fe6e6b1b0f13"},{"mnemonic":"supreme news pyramid sheriff attract volume zone innocent hat grunt gorilla mango","master":"2ba0cd68329e2b19d5c24c1d3fca44513151fc4a634e52756290967989883b52","seed":"efbf7e16af697b4dd62a876f62f08698e29531c05018bb6da7ce441340b0278353d5d08a88cb93c4fd9bdb14fb85ab857ea3e8ef13b49dabb20beae2f13af3fa","priv":"15b89635f69b28cee0aa00d0609b99f1a1dd3c83e3bd57032987146cd47cebb8","pub":"021ae715a05c4849519acbe8dbf7ff4031d18f57de1bcf9cb1a06d50e5ebdbf661","addr":"e3087b309db8490b23629cbe4d113c1ea5bb525e"},{"mnemonic":"way chat van put negative minute tail dress spawn crunch beef moment","master":"e0dff85e10808c3ac560957a46f5f86abbfc62251c8fd4c61cb5e089a0841e7a","seed":"eb14b38f90886c1a1d47ac42205b564a649a0cf6edbd88cda1c488ee700aae8b735d7e947efc5711e2cc02b2254690ff4a69d149d2e13affd6d9a3915ac9dceb","priv":"7fb5464c8bc2e1583105d34c6850fb332a578fea35dff9528422c8b7f3156242","pub":"02745f0fbe0b23688e9691f9c4a088bf1342100fe3b9f7e405df79bddd57f8e6e1","addr":"66d90273421fadbab93fb9b05ea6e572f8af7050"},{"mnemonic":"tattoo strong tool weapon blue cricket kick holiday medal club stage reason","master":"bc82d196675dbad1c24d78f4e400a8956297c6113d4004356963ca88617597b3","seed":"9cf6193178f1a6391105c79cc6d3d2e2a4fe97f44738f8f716fb5b17a3eacd4061f9bb7f0411b08d77dc10b16b9599e45e8ffa55ff7f8e5c9274bab71bfe120f","priv":"5925547ee089b4638743f0fabe33f925780772a65b87b8315acf7f523d044482","pub":"03bba775f325b1ad28ec0adf66c8e15f90d70368fa021be5db199a5188c0621eb4","addr":"1f63ff4af01b5b5f33e60b82646a39917b6a7305"},{"mnemonic":"rug diagram spend zebra occur neglect choose relax face when spell stem","master":"d7932ffb8f6b751543caed7158318a05f4686646e636b5725b9b0419fb66912b","seed":"b73957a412d9e4c677edef4cb3a376c7355f78bba347a61f44c85f76b2c8a3d8ac2bd6c3b70643bf19b8487dcdce3055aaf86921e29e5e6f89700e0e2bf00546","priv":"c827dfe5f1880d9c462985b915ff78a1ab615ff0840f3f125f618cef25e14a5c","pub":"031bfd2158660168795f38f980951921f6fa1d522ad460ac5f93dfc4a2eac91f7d","addr":"b866f1e9b5b7b00fbb6076915a0a2931cba6e029"},{"mnemonic":"faith bless there mountain stand cannon sick abstract fiscal theory begin easy","master":"9af948584294b3951e6c664423a12fdfe29a31d41546b911f3fcdf664399aa48","seed":"17b6451f4b9765fdc3ed280fb5a6141b8003c8c9d8c73afce3192e15012fd18431850ebcaa07fa08da2c648f0f97f45e33ebdea6c99f2f23a9e244a297596499","priv":"e759b35d18e8b60726e882a11ea830e30ddff6752a19bec6983fdecf655726b0","pub":"03151da31179657f296184543a1360bcb92983a12788b268db0c20d895e6c449b1","addr":"54ec389ea177e1a4fe2f98cd83f27cce218b9081"},{"mnemonic":"combine fine crowd enter check mule toward damage fortune bless topple source","master":"b831b7a1b85edf1945c892dd332419e7f3a5125229cdfe1c73cc0e964abb4b5c","seed":"d9456b80f01787607d9c3adecdd6fa299132d748ae4fab843b3802c798ea1bc0395f9a1dc29e1badccc742f3c4fa081bdd7b6f9ca8980009b75c892438020b9f","priv":"d9d037b9baf0796d8a151935c172b1f775c1875b3811bcfd6c3f477e74c5c54e","pub":"03c720f00c921ab13307d3790f742f0a40436fad9d999087c267107ce50f8fe2b9","addr":"4b5a1c53f8442c375e9af35937ff0471155c0bee"},{"mnemonic":"shift nut floor scorpion property sun either total follow glide special apology","master":"1a4520e80df55ad59d95fca8dfab5f09753f6e26f7f38f654f32e4fa6f3ff963","seed":"a9df829ec832270d1ef0b0b04542e351ab9145baf086231fbe9636120c18c8d545ed138c37c0612d296c915340f982b1d83bd408301de79c08e4580ce0ce8fdd","priv":"27b1742305c3921c0cc041dc79d6e3c83112828f3fd49e18f31cb0b422bc1c80","pub":"032b322eedf502edf5e6c24ad80ad4bde37e04de012b9bf9c8caa41151a9ccf74f","addr":"2ce4a3aeb7e0fc52c31121651346959d1cfcc1be"}] From 49569ac244c6103e190f13d626d9ef2069f8f2d2 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sun, 19 Mar 2017 17:56:33 +0100 Subject: [PATCH 050/273] Wrap constructor to create xxxS structs and avoid recursion --- priv_key.go | 7 +++++++ pub_key.go | 7 +++++++ signature.go | 7 +++++++ signature_test.go | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+) diff --git a/priv_key.go b/priv_key.go index f2d108ee5..7c2543abe 100644 --- a/priv_key.go +++ b/priv_key.go @@ -41,6 +41,13 @@ type PrivKeyS struct { PrivKey } +func WrapPrivKey(pk PrivKey) PrivKeyS { + for ppk, ok := pk.(PrivKeyS); ok; ppk, ok = pk.(PrivKeyS) { + pk = ppk.PrivKey + } + return PrivKeyS{pk} +} + func (p PrivKeyS) MarshalJSON() ([]byte, error) { return privKeyMapper.ToJSON(p.PrivKey) } diff --git a/pub_key.go b/pub_key.go index 45a4db92c..ad7a54005 100644 --- a/pub_key.go +++ b/pub_key.go @@ -36,6 +36,13 @@ type PubKeyS struct { PubKey } +func WrapPubKey(pk PubKey) PubKeyS { + for ppk, ok := pk.(PubKeyS); ok; ppk, ok = pk.(PubKeyS) { + pk = ppk.PubKey + } + return PubKeyS{pk} +} + func (p PubKeyS) MarshalJSON() ([]byte, error) { return pubKeyMapper.ToJSON(p.PubKey) } diff --git a/signature.go b/signature.go index b5fc36bf3..7a03dc6d3 100644 --- a/signature.go +++ b/signature.go @@ -31,6 +31,13 @@ type SignatureS struct { Signature } +func WrapSignature(sig Signature) SignatureS { + for ssig, ok := sig.(SignatureS); ok; ssig, ok = sig.(SignatureS) { + sig = ssig.Signature + } + return SignatureS{sig} +} + func (p SignatureS) MarshalJSON() ([]byte, error) { return sigMapper.ToJSON(p.Signature) } diff --git a/signature_test.go b/signature_test.go index f6c8c37be..f04262b77 100644 --- a/signature_test.go +++ b/signature_test.go @@ -107,3 +107,37 @@ func TestSignatureEncodings(t *testing.T) { assert.True(t, strings.HasPrefix(text, tc.sigName)) } } + +func TestWrapping(t *testing.T) { + assert := assert.New(t) + + // construct some basic constructs + msg := CRandBytes(128) + priv := GenPrivKeyEd25519() + pub := priv.PubKey() + sig := priv.Sign(msg) + + // do some wrapping + pubs := []PubKeyS{ + WrapPubKey(nil), + WrapPubKey(pub), + WrapPubKey(WrapPubKey(WrapPubKey(WrapPubKey(pub)))), + WrapPubKey(PubKeyS{PubKeyS{PubKeyS{pub}}}), + } + for _, p := range pubs { + _, ok := p.PubKey.(PubKeyS) + assert.False(ok) + } + + sigs := []SignatureS{ + WrapSignature(nil), + WrapSignature(sig), + WrapSignature(WrapSignature(WrapSignature(WrapSignature(sig)))), + WrapSignature(SignatureS{SignatureS{SignatureS{sig}}}), + } + for _, s := range sigs { + _, ok := s.Signature.(SignatureS) + assert.False(ok) + } + +} From 750b25c47a5782f5f2b773ed9e706cb82b3ccef4 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 21 Mar 2017 21:13:50 +0100 Subject: [PATCH 051/273] Update go-data, test embedding strategies --- embed_test.go | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++ priv_key.go | 4 +- pub_key.go | 4 +- signature.go | 4 +- 4 files changed, 132 insertions(+), 6 deletions(-) create mode 100644 embed_test.go diff --git a/embed_test.go b/embed_test.go new file mode 100644 index 000000000..71852848e --- /dev/null +++ b/embed_test.go @@ -0,0 +1,126 @@ +package crypto_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + data "github.com/tendermint/go-data" +) + +type Foo struct { + Name string +} + +func (f Foo) Greet() string { + return "Foo: " + f.Name +} + +type Bar struct { + Age int +} + +func (b Bar) Greet() string { + return fmt.Sprintf("Bar #%d", b.Age) +} + +type PubNameInner interface { + Greet() string +} + +type privNameInner interface { + Greet() string +} + +type Greeter interface { + Greet() string +} + +var ( + pubNameMapper, privNameMapper data.Mapper +) + +// register both public key types with go-data (and thus go-wire) +func init() { + pubNameMapper = data.NewMapper(PubName{}). + RegisterImplementation(Foo{}, "foo", 1). + RegisterImplementation(Bar{}, "bar", 2) + privNameMapper = data.NewMapper(PrivName{}). + RegisterImplementation(Foo{}, "foo", 1). + RegisterImplementation(Bar{}, "bar", 2) +} + +type PubName struct { + PubNameInner +} + +func (p PubName) MarshalJSON() ([]byte, error) { + return pubNameMapper.ToJSON(p.PubNameInner) +} + +func (p *PubName) UnmarshalJSON(data []byte) error { + parsed, err := pubNameMapper.FromJSON(data) + if err == nil && parsed != nil { + p.PubNameInner = parsed.(PubNameInner) + } + return err +} + +type PrivName struct { + privNameInner +} + +func (p PrivName) MarshalJSON() ([]byte, error) { + return privNameMapper.ToJSON(p.privNameInner) +} + +func (p *PrivName) UnmarshalJSON(data []byte) error { + parsed, err := privNameMapper.FromJSON(data) + if err == nil && parsed != nil { + p.privNameInner = parsed.(privNameInner) + } + return err +} + +// TestEncodeDemo tries the various strategies to encode the objects +func TestEncodeDemo(t *testing.T) { + assert, require := assert.New(t), require.New(t) + // assert := assert.New(t) + // require := require.New(t) + + cases := []struct { + in, out Greeter + expected string + }{ + {PubName{Foo{"pub-foo"}}, &PubName{}, "Foo: pub-foo"}, + {PubName{Bar{7}}, &PubName{}, "Bar #7"}, + // Note these fail - if you can figure a solution here, I'll buy you a beer :) + // {PrivName{Foo{"priv-foo"}}, &PrivName{}, "Foo: priv-foo"}, + // {PrivName{Bar{9}}, &PrivName{}, "Bar #9"}, + } + + for i, tc := range cases { + // make sure it is proper to start + require.Equal(tc.expected, tc.in.Greet()) + fmt.Println(tc.expected) + + // now, try to encode as binary + b, err := data.ToWire(tc.in) + if assert.Nil(err, "%d: %#v", i, tc.in) { + err := data.FromWire(b, tc.out) + if assert.Nil(err) { + assert.Equal(tc.expected, tc.out.Greet()) + } + } + + // try to encode it as json + j, err := data.ToJSON(tc.in) + if assert.Nil(err, "%d: %#v", i, tc.in) { + err := data.FromJSON(j, tc.out) + if assert.Nil(err) { + assert.Equal(tc.expected, tc.out.Greet()) + } + } + } +} diff --git a/priv_key.go b/priv_key.go index 7c2543abe..3a9a5f69b 100644 --- a/priv_key.go +++ b/priv_key.go @@ -32,8 +32,8 @@ var privKeyMapper data.Mapper // register both private key types with go-data (and thus go-wire) func init() { privKeyMapper = data.NewMapper(PrivKeyS{}). - RegisterInterface(PrivKeyEd25519{}, NameEd25519, TypeEd25519). - RegisterInterface(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) + RegisterImplementation(PrivKeyEd25519{}, NameEd25519, TypeEd25519). + RegisterImplementation(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } // PrivKeyS add json serialization to PrivKey diff --git a/pub_key.go b/pub_key.go index ad7a54005..a047edb2f 100644 --- a/pub_key.go +++ b/pub_key.go @@ -27,8 +27,8 @@ var pubKeyMapper data.Mapper // register both public key types with go-data (and thus go-wire) func init() { pubKeyMapper = data.NewMapper(PubKeyS{}). - RegisterInterface(PubKeyEd25519{}, NameEd25519, TypeEd25519). - RegisterInterface(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) + RegisterImplementation(PubKeyEd25519{}, NameEd25519, TypeEd25519). + RegisterImplementation(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } // PubKeyS add json serialization to PubKey diff --git a/signature.go b/signature.go index 7a03dc6d3..bb9d82009 100644 --- a/signature.go +++ b/signature.go @@ -22,8 +22,8 @@ var sigMapper data.Mapper // register both public key types with go-data (and thus go-wire) func init() { sigMapper = data.NewMapper(SignatureS{}). - RegisterInterface(SignatureEd25519{}, NameEd25519, TypeEd25519). - RegisterInterface(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1) + RegisterImplementation(SignatureEd25519{}, NameEd25519, TypeEd25519). + RegisterImplementation(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1) } // SignatureS add json serialization to Signature From 66ecd7705fa16cb786cbcfc00513aa88b8251230 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 21 Mar 2017 21:44:24 +0100 Subject: [PATCH 052/273] Use new naming scheme PubKey{PubKeyInner} --- embed_test.go | 1 - encode_test.go | 22 ++++++++--------- priv_key.go | 57 +++++++++++++++++++++++++------------------ pub_key.go | 62 +++++++++++++++++++++++------------------------ pub_key_test.go | 2 +- signature.go | 49 ++++++++++++++++++++++--------------- signature_test.go | 38 ++++++++++++++--------------- 7 files changed, 124 insertions(+), 107 deletions(-) diff --git a/embed_test.go b/embed_test.go index 71852848e..77b821f03 100644 --- a/embed_test.go +++ b/embed_test.go @@ -103,7 +103,6 @@ func TestEncodeDemo(t *testing.T) { for i, tc := range cases { // make sure it is proper to start require.Equal(tc.expected, tc.in.Greet()) - fmt.Println(tc.expected) // now, try to encode as binary b, err := data.ToWire(tc.in) diff --git a/encode_test.go b/encode_test.go index 977cc64cf..667132a6f 100644 --- a/encode_test.go +++ b/encode_test.go @@ -50,17 +50,17 @@ func checkJSON(t *testing.T, in interface{}, reader interface{}, typ string) { func TestKeyEncodings(t *testing.T) { cases := []struct { - privKey PrivKeyS + privKey PrivKey keyType byte keyName string }{ { - privKey: PrivKeyS{GenPrivKeyEd25519()}, + privKey: WrapPrivKey(GenPrivKeyEd25519()), keyType: TypeEd25519, keyName: NameEd25519, }, { - privKey: PrivKeyS{GenPrivKeySecp256k1()}, + privKey: WrapPrivKey(GenPrivKeySecp256k1()), keyType: TypeSecp256k1, keyName: NameSecp256k1, }, @@ -68,19 +68,19 @@ func TestKeyEncodings(t *testing.T) { for _, tc := range cases { // check (de/en)codings of private key - priv2 := PrivKeyS{} + priv2 := PrivKey{} checkWire(t, tc.privKey, &priv2, tc.keyType) assert.EqualValues(t, tc.privKey, priv2) - priv3 := PrivKeyS{} + priv3 := PrivKey{} checkJSON(t, tc.privKey, &priv3, tc.keyName) assert.EqualValues(t, tc.privKey, priv3) // check (de/en)codings of public key - pubKey := PubKeyS{tc.privKey.PubKey()} - pub2 := PubKeyS{} + pubKey := tc.privKey.PubKey() + pub2 := PubKey{} checkWire(t, pubKey, &pub2, tc.keyType) assert.EqualValues(t, pubKey, pub2) - pub3 := PubKeyS{} + pub3 := PubKey{} checkJSON(t, pubKey, &pub3, tc.keyName) assert.EqualValues(t, pubKey, pub3) } @@ -95,17 +95,17 @@ func toFromJSON(t *testing.T, in interface{}, recvr interface{}) { func TestNilEncodings(t *testing.T) { // make sure sigs are okay with nil - a, b := SignatureS{}, SignatureS{} + a, b := Signature{}, Signature{} toFromJSON(t, a, &b) assert.EqualValues(t, a, b) // make sure sigs are okay with nil - c, d := PubKeyS{}, PubKeyS{} + c, d := PubKey{}, PubKey{} toFromJSON(t, c, &d) assert.EqualValues(t, c, d) // make sure sigs are okay with nil - e, f := PrivKeyS{}, PrivKeyS{} + e, f := PrivKey{}, PrivKey{} toFromJSON(t, e, &f) assert.EqualValues(t, e, f) diff --git a/priv_key.go b/priv_key.go index 3a9a5f69b..f00a762d8 100644 --- a/priv_key.go +++ b/priv_key.go @@ -11,8 +11,8 @@ import ( "github.com/tendermint/go-wire" ) -// PrivKey is part of PrivAccount and state.PrivValidator. -type PrivKey interface { +// PrivKeyInner is now the interface itself, use PrivKey in all code +type PrivKeyInner interface { Bytes() []byte Sign(msg []byte) Signature PubKey() PubKey @@ -31,37 +31,45 @@ var privKeyMapper data.Mapper // register both private key types with go-data (and thus go-wire) func init() { - privKeyMapper = data.NewMapper(PrivKeyS{}). + privKeyMapper = data.NewMapper(PrivKey{}). RegisterImplementation(PrivKeyEd25519{}, NameEd25519, TypeEd25519). RegisterImplementation(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } -// PrivKeyS add json serialization to PrivKey -type PrivKeyS struct { - PrivKey +// PrivKey handles all encoding and exposes methods +type PrivKey struct { + PrivKeyInner } -func WrapPrivKey(pk PrivKey) PrivKeyS { - for ppk, ok := pk.(PrivKeyS); ok; ppk, ok = pk.(PrivKeyS) { - pk = ppk.PrivKey +func WrapPrivKey(pk PrivKeyInner) PrivKey { + if wrap, ok := pk.(PrivKey); ok { + pk = wrap.Unwrap() } - return PrivKeyS{pk} + return PrivKey{pk} } -func (p PrivKeyS) MarshalJSON() ([]byte, error) { - return privKeyMapper.ToJSON(p.PrivKey) +func (p PrivKey) Unwrap() PrivKeyInner { + pk := p.PrivKeyInner + for wrap, ok := pk.(PrivKey); ok; wrap, ok = pk.(PrivKey) { + pk = wrap.PrivKeyInner + } + return pk +} + +func (p PrivKey) MarshalJSON() ([]byte, error) { + return privKeyMapper.ToJSON(p.PrivKeyInner) } -func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error) { +func (p *PrivKey) UnmarshalJSON(data []byte) (err error) { parsed, err := privKeyMapper.FromJSON(data) if err == nil && parsed != nil { - p.PrivKey = parsed.(PrivKey) + p.PrivKeyInner = parsed.(PrivKeyInner) } return } -func (p PrivKeyS) Empty() bool { - return p.PrivKey == nil +func (p PrivKey) Empty() bool { + return p.PrivKeyInner == nil } func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { @@ -75,22 +83,23 @@ func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { type PrivKeyEd25519 [64]byte func (privKey PrivKeyEd25519) Bytes() []byte { - return wire.BinaryBytes(struct{ PrivKey }{privKey}) + return wire.BinaryBytes(PrivKey{privKey}) } func (privKey PrivKeyEd25519) Sign(msg []byte) Signature { privKeyBytes := [64]byte(privKey) signatureBytes := ed25519.Sign(&privKeyBytes, msg) - return SignatureEd25519(*signatureBytes) + return WrapSignature(SignatureEd25519(*signatureBytes)) } func (privKey PrivKeyEd25519) PubKey() PubKey { privKeyBytes := [64]byte(privKey) - return PubKeyEd25519(*ed25519.MakePublicKey(&privKeyBytes)) + pubBytes := *ed25519.MakePublicKey(&privKeyBytes) + return WrapPubKey(PubKeyEd25519(pubBytes)) } func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { - if otherEd, ok := other.(PrivKeyEd25519); ok { + if otherEd, ok := other.Unwrap().(PrivKeyEd25519); ok { return bytes.Equal(privKey[:], otherEd[:]) } else { return false @@ -153,7 +162,7 @@ func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 { type PrivKeySecp256k1 [32]byte func (privKey PrivKeySecp256k1) Bytes() []byte { - return wire.BinaryBytes(struct{ PrivKey }{privKey}) + return wire.BinaryBytes(PrivKey{privKey}) } func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature { @@ -162,18 +171,18 @@ func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature { if err != nil { PanicSanity(err) } - return SignatureSecp256k1(sig__.Serialize()) + return WrapSignature(SignatureSecp256k1(sig__.Serialize())) } func (privKey PrivKeySecp256k1) PubKey() PubKey { _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) var pub PubKeySecp256k1 copy(pub[:], pub__.SerializeCompressed()) - return pub + return WrapPubKey(pub) } func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { - if otherSecp, ok := other.(PrivKeySecp256k1); ok { + if otherSecp, ok := other.Unwrap().(PrivKeySecp256k1); ok { return bytes.Equal(privKey[:], otherSecp[:]) } else { return false diff --git a/pub_key.go b/pub_key.go index a047edb2f..fa91b12f4 100644 --- a/pub_key.go +++ b/pub_key.go @@ -13,8 +13,8 @@ import ( "golang.org/x/crypto/ripemd160" ) -// PubKey is part of Account and Validator. -type PubKey interface { +// PubKeyInner is now the interface itself, use PubKey struct in all code +type PubKeyInner interface { Address() []byte Bytes() []byte KeyString() string @@ -26,37 +26,45 @@ var pubKeyMapper data.Mapper // register both public key types with go-data (and thus go-wire) func init() { - pubKeyMapper = data.NewMapper(PubKeyS{}). + pubKeyMapper = data.NewMapper(PubKey{}). RegisterImplementation(PubKeyEd25519{}, NameEd25519, TypeEd25519). RegisterImplementation(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } -// PubKeyS add json serialization to PubKey -type PubKeyS struct { - PubKey +// PubKey add json serialization to PubKeyInner +type PubKey struct { + PubKeyInner } -func WrapPubKey(pk PubKey) PubKeyS { - for ppk, ok := pk.(PubKeyS); ok; ppk, ok = pk.(PubKeyS) { - pk = ppk.PubKey +func WrapPubKey(pk PubKeyInner) PubKey { + if wrap, ok := pk.(PubKey); ok { + pk = wrap.Unwrap() } - return PubKeyS{pk} + return PubKey{pk} } -func (p PubKeyS) MarshalJSON() ([]byte, error) { - return pubKeyMapper.ToJSON(p.PubKey) +func (p PubKey) Unwrap() PubKeyInner { + pk := p.PubKeyInner + for wrap, ok := pk.(PubKey); ok; wrap, ok = pk.(PubKey) { + pk = wrap.PubKeyInner + } + return pk +} + +func (p PubKey) MarshalJSON() ([]byte, error) { + return pubKeyMapper.ToJSON(p.PubKeyInner) } -func (p *PubKeyS) UnmarshalJSON(data []byte) (err error) { +func (p *PubKey) UnmarshalJSON(data []byte) (err error) { parsed, err := pubKeyMapper.FromJSON(data) if err == nil && parsed != nil { - p.PubKey = parsed.(PubKey) + p.PubKeyInner = parsed.(PubKeyInner) } return } -func (p PubKeyS) Empty() bool { - return p.PubKey == nil +func (p PubKey) Empty() bool { + return p.PubKeyInner == nil } func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { @@ -66,7 +74,7 @@ func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { //------------------------------------- -// Implements PubKey +// Implements PubKeyInner type PubKeyEd25519 [32]byte func (pubKey PubKeyEd25519) Address() []byte { @@ -83,16 +91,12 @@ func (pubKey PubKeyEd25519) Address() []byte { } func (pubKey PubKeyEd25519) Bytes() []byte { - return wire.BinaryBytes(struct{ PubKey }{pubKey}) + return wire.BinaryBytes(PubKey{pubKey}) } func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { - // unwrap if needed - if wrap, ok := sig_.(SignatureS); ok { - sig_ = wrap.Signature - } // make sure we use the same algorithm to sign - sig, ok := sig_.(SignatureEd25519) + sig, ok := sig_.Unwrap().(SignatureEd25519) if !ok { return false } @@ -134,7 +138,7 @@ func (pubKey PubKeyEd25519) KeyString() string { } func (pubKey PubKeyEd25519) Equals(other PubKey) bool { - if otherEd, ok := other.(PubKeyEd25519); ok { + if otherEd, ok := other.Unwrap().(PubKeyEd25519); ok { return bytes.Equal(pubKey[:], otherEd[:]) } else { return false @@ -160,16 +164,12 @@ func (pubKey PubKeySecp256k1) Address() []byte { } func (pubKey PubKeySecp256k1) Bytes() []byte { - return wire.BinaryBytes(struct{ PubKey }{pubKey}) + return wire.BinaryBytes(PubKey{pubKey}) } func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { - // unwrap if needed - if wrap, ok := sig_.(SignatureS); ok { - sig_ = wrap.Signature - } // and assert same algorithm to sign and verify - sig, ok := sig_.(SignatureSecp256k1) + sig, ok := sig_.Unwrap().(SignatureSecp256k1) if !ok { return false } @@ -207,7 +207,7 @@ func (pubKey PubKeySecp256k1) KeyString() string { } func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { - if otherSecp, ok := other.(PubKeySecp256k1); ok { + if otherSecp, ok := other.Unwrap().(PubKeySecp256k1); ok { return bytes.Equal(pubKey[:], otherSecp[:]) } else { return false diff --git a/pub_key_test.go b/pub_key_test.go index 0616f5546..31642233c 100644 --- a/pub_key_test.go +++ b/pub_key_test.go @@ -31,7 +31,7 @@ func TestPubKeySecp256k1Address(t *testing.T) { var priv PrivKeySecp256k1 copy(priv[:], privB) - pubT := priv.PubKey().(PubKeySecp256k1) + pubT := priv.PubKey().Unwrap().(PubKeySecp256k1) pub := pubT[:] addr := priv.PubKey().Address() diff --git a/signature.go b/signature.go index bb9d82009..e7b6b1745 100644 --- a/signature.go +++ b/signature.go @@ -9,8 +9,9 @@ import ( "github.com/tendermint/go-wire" ) -// Signature is a part of Txs and consensus Votes. -type Signature interface { +// SignatureInner is now the interface itself. +// Use Signature in all code +type SignatureInner interface { Bytes() []byte IsZero() bool String() string @@ -21,37 +22,45 @@ var sigMapper data.Mapper // register both public key types with go-data (and thus go-wire) func init() { - sigMapper = data.NewMapper(SignatureS{}). + sigMapper = data.NewMapper(Signature{}). RegisterImplementation(SignatureEd25519{}, NameEd25519, TypeEd25519). RegisterImplementation(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1) } -// SignatureS add json serialization to Signature -type SignatureS struct { - Signature +// Signature add json serialization to Signature +type Signature struct { + SignatureInner } -func WrapSignature(sig Signature) SignatureS { - for ssig, ok := sig.(SignatureS); ok; ssig, ok = sig.(SignatureS) { - sig = ssig.Signature +func WrapSignature(pk SignatureInner) Signature { + if wrap, ok := pk.(Signature); ok { + pk = wrap.Unwrap() } - return SignatureS{sig} + return Signature{pk} } -func (p SignatureS) MarshalJSON() ([]byte, error) { - return sigMapper.ToJSON(p.Signature) +func (p Signature) Unwrap() SignatureInner { + pk := p.SignatureInner + for wrap, ok := pk.(Signature); ok; wrap, ok = pk.(Signature) { + pk = wrap.SignatureInner + } + return pk +} + +func (p Signature) MarshalJSON() ([]byte, error) { + return sigMapper.ToJSON(p.SignatureInner) } -func (p *SignatureS) UnmarshalJSON(data []byte) (err error) { +func (p *Signature) UnmarshalJSON(data []byte) (err error) { parsed, err := sigMapper.FromJSON(data) if err == nil && parsed != nil { - p.Signature = parsed.(Signature) + p.SignatureInner = parsed.(SignatureInner) } return } -func (p SignatureS) Empty() bool { - return p.Signature == nil +func (p Signature) Empty() bool { + return p.SignatureInner == nil } func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { @@ -65,7 +74,7 @@ func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { type SignatureEd25519 [64]byte func (sig SignatureEd25519) Bytes() []byte { - return wire.BinaryBytes(struct{ Signature }{sig}) + return wire.BinaryBytes(Signature{sig}) } func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } @@ -73,7 +82,7 @@ func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } func (sig SignatureEd25519) Equals(other Signature) bool { - if otherEd, ok := other.(SignatureEd25519); ok { + if otherEd, ok := other.Unwrap().(SignatureEd25519); ok { return bytes.Equal(sig[:], otherEd[:]) } else { return false @@ -97,7 +106,7 @@ func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error { type SignatureSecp256k1 []byte func (sig SignatureSecp256k1) Bytes() []byte { - return wire.BinaryBytes(struct{ Signature }{sig}) + return wire.BinaryBytes(Signature{sig}) } func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } @@ -105,7 +114,7 @@ func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } func (sig SignatureSecp256k1) Equals(other Signature) bool { - if otherEd, ok := other.(SignatureSecp256k1); ok { + if otherEd, ok := other.Unwrap().(SignatureSecp256k1); ok { return bytes.Equal(sig[:], otherEd[:]) } else { return false diff --git a/signature_test.go b/signature_test.go index f04262b77..92fed906d 100644 --- a/signature_test.go +++ b/signature_test.go @@ -22,9 +22,9 @@ func TestSignAndValidateEd25519(t *testing.T) { assert.True(t, pubKey.VerifyBytes(msg, sig)) // Mutate the signature, just one bit. - sigEd := sig.(SignatureEd25519) - sigEd[0] ^= byte(0x01) - sig = Signature(sigEd) + sigEd := sig.Unwrap().(SignatureEd25519) + sigEd[7] ^= byte(0x01) + sig = WrapSignature(sigEd) assert.False(t, pubKey.VerifyBytes(msg, sig)) } @@ -39,28 +39,28 @@ func TestSignAndValidateSecp256k1(t *testing.T) { assert.True(t, pubKey.VerifyBytes(msg, sig)) // Mutate the signature, just one bit. - sigEd := sig.(SignatureSecp256k1) - sigEd[0] ^= byte(0x01) - sig = Signature(sigEd) + sigEd := sig.Unwrap().(SignatureSecp256k1) + sigEd[3] ^= byte(0x01) + sig = WrapSignature(sigEd) assert.False(t, pubKey.VerifyBytes(msg, sig)) } func TestSignatureEncodings(t *testing.T) { cases := []struct { - privKey PrivKeyS + privKey PrivKey sigSize int sigType byte sigName string }{ { - privKey: PrivKeyS{GenPrivKeyEd25519()}, + privKey: WrapPrivKey(GenPrivKeyEd25519()), sigSize: ed25519.SignatureSize, sigType: TypeEd25519, sigName: NameEd25519, }, { - privKey: PrivKeyS{GenPrivKeySecp256k1()}, + privKey: WrapPrivKey(GenPrivKeySecp256k1()), sigSize: 0, // unknown sigType: TypeSecp256k1, sigName: NameSecp256k1, @@ -69,10 +69,10 @@ func TestSignatureEncodings(t *testing.T) { for _, tc := range cases { // note we embed them from the beginning.... - pubKey := PubKeyS{tc.privKey.PubKey()} + pubKey := tc.privKey.PubKey() msg := CRandBytes(128) - sig := SignatureS{tc.privKey.Sign(msg)} + sig := tc.privKey.Sign(msg) // store as wire bin, err := data.ToWire(sig) @@ -83,7 +83,7 @@ func TestSignatureEncodings(t *testing.T) { assert.Equal(t, tc.sigType, bin[0]) // and back - sig2 := SignatureS{} + sig2 := Signature{} err = data.FromWire(bin, &sig2) require.Nil(t, err, "%+v", err) assert.EqualValues(t, sig, sig2) @@ -95,7 +95,7 @@ func TestSignatureEncodings(t *testing.T) { assert.True(t, strings.Contains(string(js), tc.sigName)) // and back - sig3 := SignatureS{} + sig3 := Signature{} err = data.FromJSON(js, &sig3) require.Nil(t, err, "%+v", err) assert.EqualValues(t, sig, sig3) @@ -118,25 +118,25 @@ func TestWrapping(t *testing.T) { sig := priv.Sign(msg) // do some wrapping - pubs := []PubKeyS{ + pubs := []PubKey{ WrapPubKey(nil), WrapPubKey(pub), WrapPubKey(WrapPubKey(WrapPubKey(WrapPubKey(pub)))), - WrapPubKey(PubKeyS{PubKeyS{PubKeyS{pub}}}), + WrapPubKey(PubKey{PubKey{PubKey{pub}}}), } for _, p := range pubs { - _, ok := p.PubKey.(PubKeyS) + _, ok := p.PubKeyInner.(PubKey) assert.False(ok) } - sigs := []SignatureS{ + sigs := []Signature{ WrapSignature(nil), WrapSignature(sig), WrapSignature(WrapSignature(WrapSignature(WrapSignature(sig)))), - WrapSignature(SignatureS{SignatureS{SignatureS{sig}}}), + WrapSignature(Signature{Signature{Signature{sig}}}), } for _, s := range sigs { - _, ok := s.Signature.(SignatureS) + _, ok := s.SignatureInner.(Signature) assert.False(ok) } From 5b94758d4c5f0aa7842f56b31e88a8d2bdb736e2 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 22 Mar 2017 15:59:00 +0100 Subject: [PATCH 053/273] Make PubKey struct compatible with go-wire.JSONBytes/ReadJSON --- encode_test.go | 20 ++++++++++++++++++++ priv_key.go | 2 +- pub_key.go | 2 +- signature.go | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/encode_test.go b/encode_test.go index 667132a6f..71b7b3ae6 100644 --- a/encode_test.go +++ b/encode_test.go @@ -1,12 +1,14 @@ package crypto import ( + "fmt" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" data "github.com/tendermint/go-data" + wire "github.com/tendermint/go-wire" ) type byter interface { @@ -48,6 +50,18 @@ func checkJSON(t *testing.T, in interface{}, reader interface{}, typ string) { assert.True(t, strings.Contains(string(js), parts[1])) } +// make sure go-wire json can still figure this out... +func checkWireJSON(t *testing.T, in interface{}, reader interface{}, typ byte) { + // test to and from binary + var err error + js := wire.JSONBytes(in) + btyp := fmt.Sprintf("[%d,", typ) + assert.True(t, strings.HasPrefix(string(js), btyp), string(js)) + + wire.ReadJSON(reader, js, &err) + require.Nil(t, err, "%+v", err) +} + func TestKeyEncodings(t *testing.T) { cases := []struct { privKey PrivKey @@ -74,6 +88,9 @@ func TestKeyEncodings(t *testing.T) { priv3 := PrivKey{} checkJSON(t, tc.privKey, &priv3, tc.keyName) assert.EqualValues(t, tc.privKey, priv3) + priv4 := PrivKey{} + checkWireJSON(t, tc.privKey, &priv4, tc.keyType) + assert.EqualValues(t, tc.privKey, priv4) // check (de/en)codings of public key pubKey := tc.privKey.PubKey() @@ -83,6 +100,9 @@ func TestKeyEncodings(t *testing.T) { pub3 := PubKey{} checkJSON(t, pubKey, &pub3, tc.keyName) assert.EqualValues(t, pubKey, pub3) + pub4 := PubKey{} + checkWireJSON(t, pubKey, &pub4, tc.keyType) + assert.EqualValues(t, pubKey, pub4) } } diff --git a/priv_key.go b/priv_key.go index f00a762d8..5aa2d05ad 100644 --- a/priv_key.go +++ b/priv_key.go @@ -38,7 +38,7 @@ func init() { // PrivKey handles all encoding and exposes methods type PrivKey struct { - PrivKeyInner + PrivKeyInner `json:"unwrap"` } func WrapPrivKey(pk PrivKeyInner) PrivKey { diff --git a/pub_key.go b/pub_key.go index fa91b12f4..8373eb347 100644 --- a/pub_key.go +++ b/pub_key.go @@ -33,7 +33,7 @@ func init() { // PubKey add json serialization to PubKeyInner type PubKey struct { - PubKeyInner + PubKeyInner `json:"unwrap"` } func WrapPubKey(pk PubKeyInner) PubKey { diff --git a/signature.go b/signature.go index e7b6b1745..ba40166cd 100644 --- a/signature.go +++ b/signature.go @@ -29,7 +29,7 @@ func init() { // Signature add json serialization to Signature type Signature struct { - SignatureInner + SignatureInner `json:"unwrap"` } func WrapSignature(pk SignatureInner) Signature { From eb6fcef8d2d26bee5ba49c88fd5af305881fd3e9 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 29 Mar 2017 15:17:06 +0200 Subject: [PATCH 054/273] Better docs and naming thanks to bucky --- embed_test.go | 4 ++++ encode_test.go | 14 +++++--------- priv_key.go | 14 ++++++++++++-- pub_key.go | 14 ++++++++++++-- signature.go | 15 ++++++++++++--- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/embed_test.go b/embed_test.go index 77b821f03..eda72b438 100644 --- a/embed_test.go +++ b/embed_test.go @@ -95,7 +95,11 @@ func TestEncodeDemo(t *testing.T) { }{ {PubName{Foo{"pub-foo"}}, &PubName{}, "Foo: pub-foo"}, {PubName{Bar{7}}, &PubName{}, "Bar #7"}, + // Note these fail - if you can figure a solution here, I'll buy you a beer :) + // (ebuchman is right, you must either break the reflection system, or modify go-wire) + // but such a mod would let us make REALLY sure that no one could construct like this + // {PrivName{Foo{"priv-foo"}}, &PrivName{}, "Foo: priv-foo"}, // {PrivName{Bar{9}}, &PrivName{}, "Bar #9"}, } diff --git a/encode_test.go b/encode_test.go index 71b7b3ae6..9a8e5902c 100644 --- a/encode_test.go +++ b/encode_test.go @@ -82,25 +82,21 @@ func TestKeyEncodings(t *testing.T) { for _, tc := range cases { // check (de/en)codings of private key - priv2 := PrivKey{} + var priv2, priv3, priv4 PrivKey checkWire(t, tc.privKey, &priv2, tc.keyType) assert.EqualValues(t, tc.privKey, priv2) - priv3 := PrivKey{} checkJSON(t, tc.privKey, &priv3, tc.keyName) assert.EqualValues(t, tc.privKey, priv3) - priv4 := PrivKey{} checkWireJSON(t, tc.privKey, &priv4, tc.keyType) assert.EqualValues(t, tc.privKey, priv4) // check (de/en)codings of public key pubKey := tc.privKey.PubKey() - pub2 := PubKey{} + var pub2, pub3, pub4 PubKey checkWire(t, pubKey, &pub2, tc.keyType) assert.EqualValues(t, pubKey, pub2) - pub3 := PubKey{} checkJSON(t, pubKey, &pub3, tc.keyName) assert.EqualValues(t, pubKey, pub3) - pub4 := PubKey{} checkWireJSON(t, pubKey, &pub4, tc.keyType) assert.EqualValues(t, pubKey, pub4) } @@ -115,17 +111,17 @@ func toFromJSON(t *testing.T, in interface{}, recvr interface{}) { func TestNilEncodings(t *testing.T) { // make sure sigs are okay with nil - a, b := Signature{}, Signature{} + var a, b Signature toFromJSON(t, a, &b) assert.EqualValues(t, a, b) // make sure sigs are okay with nil - c, d := PubKey{}, PubKey{} + var c, d PubKey toFromJSON(t, c, &d) assert.EqualValues(t, c, d) // make sure sigs are okay with nil - e, f := PrivKey{}, PrivKey{} + var e, f PrivKey toFromJSON(t, e, &f) assert.EqualValues(t, e, f) diff --git a/priv_key.go b/priv_key.go index 5aa2d05ad..d21bdf458 100644 --- a/priv_key.go +++ b/priv_key.go @@ -11,7 +11,14 @@ import ( "github.com/tendermint/go-wire" ) -// PrivKeyInner is now the interface itself, use PrivKey in all code +/* +DO NOT USE this interface. + +It is public by necessity but should never be used directly +outside of this package. + +Only use the PrivKey, never the PrivKeyInner +*/ type PrivKeyInner interface { Bytes() []byte Sign(msg []byte) Signature @@ -36,11 +43,13 @@ func init() { RegisterImplementation(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } -// PrivKey handles all encoding and exposes methods +// PrivKey should be used instead of an interface in all external packages +// unless you demand a concrete implementation, then use that directly. type PrivKey struct { PrivKeyInner `json:"unwrap"` } +// WrapPrivKey goes from concrete implementation to "interface" struct func WrapPrivKey(pk PrivKeyInner) PrivKey { if wrap, ok := pk.(PrivKey); ok { pk = wrap.Unwrap() @@ -48,6 +57,7 @@ func WrapPrivKey(pk PrivKeyInner) PrivKey { return PrivKey{pk} } +// Unwrap recovers the concrete interface safely (regardless of levels of embeds) func (p PrivKey) Unwrap() PrivKeyInner { pk := p.PrivKeyInner for wrap, ok := pk.(PrivKey); ok; wrap, ok = pk.(PrivKey) { diff --git a/pub_key.go b/pub_key.go index 8373eb347..a763688fe 100644 --- a/pub_key.go +++ b/pub_key.go @@ -13,7 +13,14 @@ import ( "golang.org/x/crypto/ripemd160" ) -// PubKeyInner is now the interface itself, use PubKey struct in all code +/* +DO NOT USE this interface. + +It is public by necessity but should never be used directly +outside of this package. + +Only use the PubKey, never the PubKeyInner +*/ type PubKeyInner interface { Address() []byte Bytes() []byte @@ -31,11 +38,13 @@ func init() { RegisterImplementation(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) } -// PubKey add json serialization to PubKeyInner +// PubKey should be used instead of an interface in all external packages +// unless you demand a concrete implementation, then use that directly. type PubKey struct { PubKeyInner `json:"unwrap"` } +// WrapPubKey goes from concrete implementation to "interface" struct func WrapPubKey(pk PubKeyInner) PubKey { if wrap, ok := pk.(PubKey); ok { pk = wrap.Unwrap() @@ -43,6 +52,7 @@ func WrapPubKey(pk PubKeyInner) PubKey { return PubKey{pk} } +// Unwrap recovers the concrete interface safely (regardless of levels of embeds) func (p PubKey) Unwrap() PubKeyInner { pk := p.PubKeyInner for wrap, ok := pk.(PubKey); ok; wrap, ok = pk.(PubKey) { diff --git a/signature.go b/signature.go index ba40166cd..bb3e8f11b 100644 --- a/signature.go +++ b/signature.go @@ -9,8 +9,14 @@ import ( "github.com/tendermint/go-wire" ) -// SignatureInner is now the interface itself. -// Use Signature in all code +/* +DO NOT USE this interface. + +It is public by necessity but should never be used directly +outside of this package. + +Only use the Signature, never the SignatureInner +*/ type SignatureInner interface { Bytes() []byte IsZero() bool @@ -27,11 +33,13 @@ func init() { RegisterImplementation(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1) } -// Signature add json serialization to Signature +// Signature should be used instead of an interface in all external packages +// unless you demand a concrete implementation, then use that directly. type Signature struct { SignatureInner `json:"unwrap"` } +// WrapSignature goes from concrete implementation to "interface" struct func WrapSignature(pk SignatureInner) Signature { if wrap, ok := pk.(Signature); ok { pk = wrap.Unwrap() @@ -39,6 +47,7 @@ func WrapSignature(pk SignatureInner) Signature { return Signature{pk} } +// Unwrap recovers the concrete interface safely (regardless of levels of embeds) func (p Signature) Unwrap() SignatureInner { pk := p.SignatureInner for wrap, ok := pk.(Signature); ok; wrap, ok = pk.(Signature) { From a3324cc97bf90b49437eb4cf1da3c7733259b62d Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 9 Apr 2017 00:32:54 -0700 Subject: [PATCH 055/273] Cleanup; Implement .Wrap() --- crypto.go | 9 ++++ embed_test.go | 102 +++++++++++++++------------------------------- encode_test.go | 4 +- priv_key.go | 91 ++++++++++++++++++----------------------- pub_key.go | 85 ++++++++++++++++++-------------------- signature.go | 99 +++++++++++++++++++++----------------------- signature_test.go | 24 +++++------ 7 files changed, 181 insertions(+), 233 deletions(-) create mode 100644 crypto.go diff --git a/crypto.go b/crypto.go new file mode 100644 index 000000000..d9caf1ad9 --- /dev/null +++ b/crypto.go @@ -0,0 +1,9 @@ +package crypto + +// Types of implementations +const ( + TypeEd25519 = byte(0x01) + TypeSecp256k1 = byte(0x02) + NameEd25519 = "ed25519" + NameSecp256k1 = "secp256k1" +) diff --git a/embed_test.go b/embed_test.go index eda72b438..6ebba893c 100644 --- a/embed_test.go +++ b/embed_test.go @@ -9,50 +9,13 @@ import ( data "github.com/tendermint/go-data" ) -type Foo struct { - Name string -} - -func (f Foo) Greet() string { - return "Foo: " + f.Name -} - -type Bar struct { - Age int -} - -func (b Bar) Greet() string { - return fmt.Sprintf("Bar #%d", b.Age) +type PubName struct { + PubNameInner } type PubNameInner interface { - Greet() string -} - -type privNameInner interface { - Greet() string -} - -type Greeter interface { - Greet() string -} - -var ( - pubNameMapper, privNameMapper data.Mapper -) - -// register both public key types with go-data (and thus go-wire) -func init() { - pubNameMapper = data.NewMapper(PubName{}). - RegisterImplementation(Foo{}, "foo", 1). - RegisterImplementation(Bar{}, "bar", 2) - privNameMapper = data.NewMapper(PrivName{}). - RegisterImplementation(Foo{}, "foo", 1). - RegisterImplementation(Bar{}, "bar", 2) -} - -type PubName struct { - PubNameInner + AssertIsPubNameInner() + String() string } func (p PubName) MarshalJSON() ([]byte, error) { @@ -67,62 +30,61 @@ func (p *PubName) UnmarshalJSON(data []byte) error { return err } -type PrivName struct { - privNameInner -} +var pubNameMapper = data.NewMapper(PubName{}). + RegisterImplementation(PubNameFoo{}, "foo", 1). + RegisterImplementation(PubNameBar{}, "bar", 2) -func (p PrivName) MarshalJSON() ([]byte, error) { - return privNameMapper.ToJSON(p.privNameInner) +func (f PubNameFoo) AssertIsPubNameInner() {} +func (f PubNameBar) AssertIsPubNameInner() {} + +//---------------------------------------- + +type PubNameFoo struct { + Name string } -func (p *PrivName) UnmarshalJSON(data []byte) error { - parsed, err := privNameMapper.FromJSON(data) - if err == nil && parsed != nil { - p.privNameInner = parsed.(privNameInner) - } - return err +func (f PubNameFoo) String() string { return "Foo: " + f.Name } + +type PubNameBar struct { + Age int } +func (b PubNameBar) String() string { return fmt.Sprintf("Bar #%d", b.Age) } + +//---------------------------------------- + // TestEncodeDemo tries the various strategies to encode the objects func TestEncodeDemo(t *testing.T) { assert, require := assert.New(t), require.New(t) - // assert := assert.New(t) - // require := require.New(t) cases := []struct { - in, out Greeter + in, out PubNameInner expected string }{ - {PubName{Foo{"pub-foo"}}, &PubName{}, "Foo: pub-foo"}, - {PubName{Bar{7}}, &PubName{}, "Bar #7"}, - - // Note these fail - if you can figure a solution here, I'll buy you a beer :) - // (ebuchman is right, you must either break the reflection system, or modify go-wire) - // but such a mod would let us make REALLY sure that no one could construct like this - - // {PrivName{Foo{"priv-foo"}}, &PrivName{}, "Foo: priv-foo"}, - // {PrivName{Bar{9}}, &PrivName{}, "Bar #9"}, + {PubName{PubNameFoo{"pub-foo"}}, &PubName{}, "Foo: pub-foo"}, + {PubName{PubNameBar{7}}, &PubName{}, "Bar #7"}, } for i, tc := range cases { - // make sure it is proper to start - require.Equal(tc.expected, tc.in.Greet()) - // now, try to encode as binary + // Make sure it is proper to start + require.Equal(tc.expected, tc.in.String()) + + // Try to encode as binary b, err := data.ToWire(tc.in) if assert.Nil(err, "%d: %#v", i, tc.in) { err := data.FromWire(b, tc.out) if assert.Nil(err) { - assert.Equal(tc.expected, tc.out.Greet()) + assert.Equal(tc.expected, tc.out.String()) } } - // try to encode it as json + // Try to encode it as json j, err := data.ToJSON(tc.in) if assert.Nil(err, "%d: %#v", i, tc.in) { err := data.FromJSON(j, tc.out) if assert.Nil(err) { - assert.Equal(tc.expected, tc.out.Greet()) + assert.Equal(tc.expected, tc.out.String()) } } } diff --git a/encode_test.go b/encode_test.go index 9a8e5902c..2d709b943 100644 --- a/encode_test.go +++ b/encode_test.go @@ -69,12 +69,12 @@ func TestKeyEncodings(t *testing.T) { keyName string }{ { - privKey: WrapPrivKey(GenPrivKeyEd25519()), + privKey: GenPrivKeyEd25519().Wrap(), keyType: TypeEd25519, keyName: NameEd25519, }, { - privKey: WrapPrivKey(GenPrivKeySecp256k1()), + privKey: GenPrivKeySecp256k1().Wrap(), keyType: TypeSecp256k1, keyName: NameSecp256k1, }, diff --git a/priv_key.go b/priv_key.go index d21bdf458..74d5b5a3e 100644 --- a/priv_key.go +++ b/priv_key.go @@ -11,50 +11,38 @@ import ( "github.com/tendermint/go-wire" ) -/* -DO NOT USE this interface. +func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { + err = wire.ReadBinaryBytes(privKeyBytes, &privKey) + return +} -It is public by necessity but should never be used directly -outside of this package. +//---------------------------------------- -Only use the PrivKey, never the PrivKeyInner -*/ +type PrivKey struct { + PrivKeyInner `json:"unwrap"` +} + +// DO NOT USE THIS INTERFACE. +// You probably want to use PubKey type PrivKeyInner interface { + AssertIsPrivKeyInner() Bytes() []byte Sign(msg []byte) Signature PubKey() PubKey Equals(PrivKey) bool + Wrap() PrivKey } -// Types of implementations -const ( - TypeEd25519 = byte(0x01) - TypeSecp256k1 = byte(0x02) - NameEd25519 = "ed25519" - NameSecp256k1 = "secp256k1" -) - -var privKeyMapper data.Mapper - -// register both private key types with go-data (and thus go-wire) -func init() { - privKeyMapper = data.NewMapper(PrivKey{}). - RegisterImplementation(PrivKeyEd25519{}, NameEd25519, TypeEd25519). - RegisterImplementation(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) -} - -// PrivKey should be used instead of an interface in all external packages -// unless you demand a concrete implementation, then use that directly. -type PrivKey struct { - PrivKeyInner `json:"unwrap"` +func (p PrivKey) MarshalJSON() ([]byte, error) { + return privKeyMapper.ToJSON(p.PrivKeyInner) } -// WrapPrivKey goes from concrete implementation to "interface" struct -func WrapPrivKey(pk PrivKeyInner) PrivKey { - if wrap, ok := pk.(PrivKey); ok { - pk = wrap.Unwrap() +func (p *PrivKey) UnmarshalJSON(data []byte) (err error) { + parsed, err := privKeyMapper.FromJSON(data) + if err == nil && parsed != nil { + p.PrivKeyInner = parsed.(PrivKeyInner) } - return PrivKey{pk} + return } // Unwrap recovers the concrete interface safely (regardless of levels of embeds) @@ -66,32 +54,21 @@ func (p PrivKey) Unwrap() PrivKeyInner { return pk } -func (p PrivKey) MarshalJSON() ([]byte, error) { - return privKeyMapper.ToJSON(p.PrivKeyInner) -} - -func (p *PrivKey) UnmarshalJSON(data []byte) (err error) { - parsed, err := privKeyMapper.FromJSON(data) - if err == nil && parsed != nil { - p.PrivKeyInner = parsed.(PrivKeyInner) - } - return -} - func (p PrivKey) Empty() bool { return p.PrivKeyInner == nil } -func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { - err = wire.ReadBinaryBytes(privKeyBytes, &privKey) - return -} +var privKeyMapper = data.NewMapper(PrivKey{}). + RegisterImplementation(PrivKeyEd25519{}, NameEd25519, TypeEd25519). + RegisterImplementation(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) //------------------------------------- // Implements PrivKey type PrivKeyEd25519 [64]byte +func (privKey PrivKeyEd25519) AssertIsPrivKeyInner() {} + func (privKey PrivKeyEd25519) Bytes() []byte { return wire.BinaryBytes(PrivKey{privKey}) } @@ -99,13 +76,13 @@ func (privKey PrivKeyEd25519) Bytes() []byte { func (privKey PrivKeyEd25519) Sign(msg []byte) Signature { privKeyBytes := [64]byte(privKey) signatureBytes := ed25519.Sign(&privKeyBytes, msg) - return WrapSignature(SignatureEd25519(*signatureBytes)) + return SignatureEd25519(*signatureBytes).Wrap() } func (privKey PrivKeyEd25519) PubKey() PubKey { privKeyBytes := [64]byte(privKey) pubBytes := *ed25519.MakePublicKey(&privKeyBytes) - return WrapPubKey(PubKeyEd25519(pubBytes)) + return PubKeyEd25519(pubBytes).Wrap() } func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { @@ -149,6 +126,10 @@ func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { return PrivKeyEd25519(newKey) } +func (privKey PrivKeyEd25519) Wrap() PrivKey { + return PrivKey{privKey} +} + func GenPrivKeyEd25519() PrivKeyEd25519 { privKeyBytes := new([64]byte) copy(privKeyBytes[:32], CRandBytes(32)) @@ -171,6 +152,8 @@ func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 { // Implements PrivKey type PrivKeySecp256k1 [32]byte +func (privKey PrivKeySecp256k1) AssertIsPrivKeyInner() {} + func (privKey PrivKeySecp256k1) Bytes() []byte { return wire.BinaryBytes(PrivKey{privKey}) } @@ -181,14 +164,14 @@ func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature { if err != nil { PanicSanity(err) } - return WrapSignature(SignatureSecp256k1(sig__.Serialize())) + return SignatureSecp256k1(sig__.Serialize()).Wrap() } func (privKey PrivKeySecp256k1) PubKey() PubKey { _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) var pub PubKeySecp256k1 copy(pub[:], pub__.SerializeCompressed()) - return WrapPubKey(pub) + return pub.Wrap() } func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { @@ -214,6 +197,10 @@ func (privKey PrivKeySecp256k1) String() string { return Fmt("PrivKeySecp256k1{*****}") } +func (privKey PrivKeySecp256k1) Wrap() PrivKey { + return PrivKey{privKey} +} + /* // Deterministically generates new priv-key bytes from key. func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 { diff --git a/pub_key.go b/pub_key.go index a763688fe..e6567d347 100644 --- a/pub_key.go +++ b/pub_key.go @@ -13,80 +13,65 @@ import ( "golang.org/x/crypto/ripemd160" ) -/* -DO NOT USE this interface. +func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { + err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey) + return +} -It is public by necessity but should never be used directly -outside of this package. +//---------------------------------------- -Only use the PubKey, never the PubKeyInner -*/ +type PubKey struct { + PubKeyInner `json:"unwrap"` +} + +// DO NOT USE THIS INTERFACE. +// You probably want to use PubKey type PubKeyInner interface { + AssertIsPubKeyInner() Address() []byte Bytes() []byte KeyString() string VerifyBytes(msg []byte, sig Signature) bool Equals(PubKey) bool + Wrap() PubKey } -var pubKeyMapper data.Mapper - -// register both public key types with go-data (and thus go-wire) -func init() { - pubKeyMapper = data.NewMapper(PubKey{}). - RegisterImplementation(PubKeyEd25519{}, NameEd25519, TypeEd25519). - RegisterImplementation(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) +func (pk PubKey) MarshalJSON() ([]byte, error) { + return pubKeyMapper.ToJSON(pk.PubKeyInner) } -// PubKey should be used instead of an interface in all external packages -// unless you demand a concrete implementation, then use that directly. -type PubKey struct { - PubKeyInner `json:"unwrap"` -} - -// WrapPubKey goes from concrete implementation to "interface" struct -func WrapPubKey(pk PubKeyInner) PubKey { - if wrap, ok := pk.(PubKey); ok { - pk = wrap.Unwrap() +func (pk *PubKey) UnmarshalJSON(data []byte) (err error) { + parsed, err := pubKeyMapper.FromJSON(data) + if err == nil && parsed != nil { + pk.PubKeyInner = parsed.(PubKeyInner) } - return PubKey{pk} + return } // Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (p PubKey) Unwrap() PubKeyInner { - pk := p.PubKeyInner - for wrap, ok := pk.(PubKey); ok; wrap, ok = pk.(PubKey) { - pk = wrap.PubKeyInner - } - return pk -} - -func (p PubKey) MarshalJSON() ([]byte, error) { - return pubKeyMapper.ToJSON(p.PubKeyInner) -} - -func (p *PubKey) UnmarshalJSON(data []byte) (err error) { - parsed, err := pubKeyMapper.FromJSON(data) - if err == nil && parsed != nil { - p.PubKeyInner = parsed.(PubKeyInner) +func (pk PubKey) Unwrap() PubKeyInner { + pkI := pk.PubKeyInner + for wrap, ok := pkI.(PubKey); ok; wrap, ok = pkI.(PubKey) { + pkI = wrap.PubKeyInner } - return + return pkI } func (p PubKey) Empty() bool { return p.PubKeyInner == nil } -func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { - err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey) - return -} +var pubKeyMapper = data.NewMapper(PubKey{}). + RegisterImplementation(PubKeyEd25519{}, NameEd25519, TypeEd25519). + RegisterImplementation(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) //------------------------------------- // Implements PubKeyInner type PubKeyEd25519 [32]byte +func (pubKey PubKeyEd25519) AssertIsPubKeyInner() {} + func (pubKey PubKeyEd25519) Address() []byte { w, n, err := new(bytes.Buffer), new(int), new(error) wire.WriteBinary(pubKey[:], w, n, err) @@ -155,6 +140,10 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool { } } +func (pubKey PubKeyEd25519) Wrap() PubKey { + return PubKey{pubKey} +} + //------------------------------------- // Implements PubKey. @@ -162,6 +151,8 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool { // prefixed with 0x02 or 0x03, depending on the y-cord. type PubKeySecp256k1 [33]byte +func (pubKey PubKeySecp256k1) AssertIsPubKeyInner() {} + // Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) func (pubKey PubKeySecp256k1) Address() []byte { hasherSHA256 := sha256.New() @@ -223,3 +214,7 @@ func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { return false } } + +func (pubKey PubKeySecp256k1) Wrap() PubKey { + return PubKey{pubKey} +} diff --git a/signature.go b/signature.go index bb3e8f11b..66c9a8a27 100644 --- a/signature.go +++ b/signature.go @@ -9,79 +9,64 @@ import ( "github.com/tendermint/go-wire" ) -/* -DO NOT USE this interface. +func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { + err = wire.ReadBinaryBytes(sigBytes, &sig) + return +} -It is public by necessity but should never be used directly -outside of this package. +//---------------------------------------- -Only use the Signature, never the SignatureInner -*/ +type Signature struct { + SignatureInner `json:"unwrap"` +} + +// DO NOT USE THIS INTERFACE. +// You probably want to use Signature. type SignatureInner interface { + AssertIsSignatureInner() Bytes() []byte IsZero() bool String() string Equals(Signature) bool + Wrap() Signature } -var sigMapper data.Mapper - -// register both public key types with go-data (and thus go-wire) -func init() { - sigMapper = data.NewMapper(Signature{}). - RegisterImplementation(SignatureEd25519{}, NameEd25519, TypeEd25519). - RegisterImplementation(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1) +func (sig Signature) MarshalJSON() ([]byte, error) { + return sigMapper.ToJSON(sig.SignatureInner) } -// Signature should be used instead of an interface in all external packages -// unless you demand a concrete implementation, then use that directly. -type Signature struct { - SignatureInner `json:"unwrap"` -} - -// WrapSignature goes from concrete implementation to "interface" struct -func WrapSignature(pk SignatureInner) Signature { - if wrap, ok := pk.(Signature); ok { - pk = wrap.Unwrap() +func (sig *Signature) UnmarshalJSON(data []byte) (err error) { + parsed, err := sigMapper.FromJSON(data) + if err == nil && parsed != nil { + sig.SignatureInner = parsed.(SignatureInner) } - return Signature{pk} + return } // Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (p Signature) Unwrap() SignatureInner { - pk := p.SignatureInner +func (sig Signature) Unwrap() SignatureInner { + pk := sig.SignatureInner for wrap, ok := pk.(Signature); ok; wrap, ok = pk.(Signature) { pk = wrap.SignatureInner } return pk } -func (p Signature) MarshalJSON() ([]byte, error) { - return sigMapper.ToJSON(p.SignatureInner) -} - -func (p *Signature) UnmarshalJSON(data []byte) (err error) { - parsed, err := sigMapper.FromJSON(data) - if err == nil && parsed != nil { - p.SignatureInner = parsed.(SignatureInner) - } - return +func (sig Signature) Empty() bool { + return sig.SignatureInner == nil } -func (p Signature) Empty() bool { - return p.SignatureInner == nil -} - -func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { - err = wire.ReadBinaryBytes(sigBytes, &sig) - return -} +var sigMapper = data.NewMapper(Signature{}). + RegisterImplementation(SignatureEd25519{}, NameEd25519, TypeEd25519). + RegisterImplementation(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1) //------------------------------------- // Implements Signature type SignatureEd25519 [64]byte +func (sig SignatureEd25519) AssertIsSignatureInner() {} + func (sig SignatureEd25519) Bytes() []byte { return wire.BinaryBytes(Signature{sig}) } @@ -98,22 +83,28 @@ func (sig SignatureEd25519) Equals(other Signature) bool { } } -func (p SignatureEd25519) MarshalJSON() ([]byte, error) { - return data.Encoder.Marshal(p[:]) +func (sig SignatureEd25519) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(sig[:]) } -func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error { +func (sig *SignatureEd25519) UnmarshalJSON(enc []byte) error { var ref []byte err := data.Encoder.Unmarshal(&ref, enc) - copy(p[:], ref) + copy(sig[:], ref) return err } +func (sig SignatureEd25519) Wrap() Signature { + return Signature{sig} +} + //------------------------------------- // Implements Signature type SignatureSecp256k1 []byte +func (sig SignatureSecp256k1) AssertIsSignatureInner() {} + func (sig SignatureSecp256k1) Bytes() []byte { return wire.BinaryBytes(Signature{sig}) } @@ -129,10 +120,14 @@ func (sig SignatureSecp256k1) Equals(other Signature) bool { return false } } -func (p SignatureSecp256k1) MarshalJSON() ([]byte, error) { - return data.Encoder.Marshal(p) +func (sig SignatureSecp256k1) MarshalJSON() ([]byte, error) { + return data.Encoder.Marshal(sig) +} + +func (sig *SignatureSecp256k1) UnmarshalJSON(enc []byte) error { + return data.Encoder.Unmarshal((*[]byte)(sig), enc) } -func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error { - return data.Encoder.Unmarshal((*[]byte)(p), enc) +func (sig SignatureSecp256k1) Wrap() Signature { + return Signature{sig} } diff --git a/signature_test.go b/signature_test.go index 92fed906d..93aa17279 100644 --- a/signature_test.go +++ b/signature_test.go @@ -24,7 +24,7 @@ func TestSignAndValidateEd25519(t *testing.T) { // Mutate the signature, just one bit. sigEd := sig.Unwrap().(SignatureEd25519) sigEd[7] ^= byte(0x01) - sig = WrapSignature(sigEd) + sig = sigEd.Wrap() assert.False(t, pubKey.VerifyBytes(msg, sig)) } @@ -41,7 +41,7 @@ func TestSignAndValidateSecp256k1(t *testing.T) { // Mutate the signature, just one bit. sigEd := sig.Unwrap().(SignatureSecp256k1) sigEd[3] ^= byte(0x01) - sig = WrapSignature(sigEd) + sig = sigEd.Wrap() assert.False(t, pubKey.VerifyBytes(msg, sig)) } @@ -54,13 +54,13 @@ func TestSignatureEncodings(t *testing.T) { sigName string }{ { - privKey: WrapPrivKey(GenPrivKeyEd25519()), + privKey: GenPrivKeyEd25519().Wrap(), sigSize: ed25519.SignatureSize, sigType: TypeEd25519, sigName: NameEd25519, }, { - privKey: WrapPrivKey(GenPrivKeySecp256k1()), + privKey: GenPrivKeySecp256k1().Wrap(), sigSize: 0, // unknown sigType: TypeSecp256k1, sigName: NameSecp256k1, @@ -119,10 +119,10 @@ func TestWrapping(t *testing.T) { // do some wrapping pubs := []PubKey{ - WrapPubKey(nil), - WrapPubKey(pub), - WrapPubKey(WrapPubKey(WrapPubKey(WrapPubKey(pub)))), - WrapPubKey(PubKey{PubKey{PubKey{pub}}}), + PubKey{nil}, + pub.Wrap(), + pub.Wrap().Wrap().Wrap(), + PubKey{PubKey{PubKey{pub}}}.Wrap(), } for _, p := range pubs { _, ok := p.PubKeyInner.(PubKey) @@ -130,10 +130,10 @@ func TestWrapping(t *testing.T) { } sigs := []Signature{ - WrapSignature(nil), - WrapSignature(sig), - WrapSignature(WrapSignature(WrapSignature(WrapSignature(sig)))), - WrapSignature(Signature{Signature{Signature{sig}}}), + Signature{nil}, + sig.Wrap(), + sig.Wrap().Wrap().Wrap(), + Signature{Signature{Signature{sig}}}.Wrap(), } for _, s := range sigs { _, ok := s.SignatureInner.(Signature) From 926741c0a1b409d734ab635d52f6ffa5c4c03d2b Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 9 Apr 2017 01:29:33 -0700 Subject: [PATCH 056/273] remove coin param --- hd/address.go | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/hd/address.go b/hd/address.go index afdeefbc4..139707e46 100644 --- a/hd/address.go +++ b/hd/address.go @@ -22,21 +22,13 @@ import ( "golang.org/x/crypto/ripemd160" ) -const ( - // BIP32 chainpath prefix - CHAINPATH_PREFIX_DEPOSIT = 0 - CHAINPATH_PREFIX_CHANGE = 1 - CHAINPATH_PREFIX_SWEEP = 2 - CHAINPATH_PREFIX_SWEEP_DRY = 102 -) - -func ComputeAddress(coin string, pubKeyHex string, chainHex string, path string, index int32) string { +func ComputeAddress(pubKeyHex string, chainHex string, path string, index int32) string { pubKeyBytes := DerivePublicKeyForPath( HexDecode(pubKeyHex), HexDecode(chainHex), fmt.Sprintf("%v/%v", path, index), ) - return AddrFromPubKeyBytes(coin, pubKeyBytes) + return AddrFromPubKeyBytes(pubKeyBytes) } func ComputePrivateKey(mprivHex string, chainHex string, path string, index int32) string { @@ -48,9 +40,9 @@ func ComputePrivateKey(mprivHex string, chainHex string, path string, index int3 return HexEncode(privKeyBytes) } -func ComputeAddressForPrivKey(coin string, privKey string) string { +func ComputeAddressForPrivKey(privKey string) string { pubKeyBytes := PubKeyBytesFromPrivKeyBytes(HexDecode(privKey), true) - return AddrFromPubKeyBytes(coin, pubKeyBytes) + return AddrFromPubKeyBytes(pubKeyBytes) } func SignMessage(privKey string, message string, compress bool) string { @@ -86,8 +78,8 @@ func ComputeMastersFromSeed(seed string) (string, string, string, string) { return HexEncode(pubKeyBytes), HexEncode(secret), HexEncode(chain), HexEncode(secret) } -func ComputeWIF(coin string, privKey string, compress bool) string { - return WIFFromPrivKeyBytes(coin, HexDecode(privKey), compress) +func ComputeWIF(privKey string, compress bool) string { + return WIFFromPrivKeyBytes(HexDecode(privKey), compress) } func ComputeTxId(rawTxHex string) string { @@ -100,7 +92,7 @@ func printKeyInfo(privKeyBytes []byte, pubKeyBytes []byte, chain []byte) { if pubKeyBytes == nil { pubKeyBytes = PubKeyBytesFromPrivKeyBytes(privKeyBytes, true) } - addr := AddrFromPubKeyBytes("BTC", pubKeyBytes) + addr := AddrFromPubKeyBytes(pubKeyBytes) log.Println("\nprikey:\t%v\npubKeyBytes:\t%v\naddr:\t%v\nchain:\t%v", HexEncode(privKeyBytes), HexEncode(pubKeyBytes), @@ -225,8 +217,9 @@ func I64(key []byte, data []byte) ([]byte, []byte) { return I[:32], I[32:] } -func AddrFromPubKeyBytes(coin string, pubKeyBytes []byte) string { - prefix := byte(0x00) // TODO Make const or configurable +// This returns a Bitcoin-like address. +func AddrFromPubKeyBytes(pubKeyBytes []byte) string { + prefix := byte(0x80) // TODO Make const or configurable h160 := CalcHash160(pubKeyBytes) h160 = append([]byte{prefix}, h160...) checksum := CalcHash256(h160) @@ -234,7 +227,15 @@ func AddrFromPubKeyBytes(coin string, pubKeyBytes []byte) string { return base58.Encode(b) } -func WIFFromPrivKeyBytes(coin string, privKeyBytes []byte, compress bool) string { +func AddrBytesFromPubKeyBytes(pubKeyBytes []byte) (addrBytes []byte, checksum []byte) { + prefix := byte(0x80) // TODO Make const or configurable + h160 := CalcHash160(pubKeyBytes) + _h160 := append([]byte{prefix}, h160...) + checksum = CalcHash256(_h160)[:4] + return h160, checksum +} + +func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string { prefix := byte(0x80) // TODO Make const or configurable bytes := append([]byte{prefix}, privKeyBytes...) if compress { From f17e6bf44c323d0b8883963428bc774aefebfda8 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 10 Apr 2017 03:01:35 -0700 Subject: [PATCH 057/273] Fix bitcoin addr scheme --- hd/address.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hd/address.go b/hd/address.go index 139707e46..28f70a98f 100644 --- a/hd/address.go +++ b/hd/address.go @@ -219,7 +219,7 @@ func I64(key []byte, data []byte) ([]byte, []byte) { // This returns a Bitcoin-like address. func AddrFromPubKeyBytes(pubKeyBytes []byte) string { - prefix := byte(0x80) // TODO Make const or configurable + prefix := byte(0x00) // TODO Make const or configurable h160 := CalcHash160(pubKeyBytes) h160 = append([]byte{prefix}, h160...) checksum := CalcHash256(h160) @@ -228,7 +228,7 @@ func AddrFromPubKeyBytes(pubKeyBytes []byte) string { } func AddrBytesFromPubKeyBytes(pubKeyBytes []byte) (addrBytes []byte, checksum []byte) { - prefix := byte(0x80) // TODO Make const or configurable + prefix := byte(0x00) // TODO Make const or configurable h160 := CalcHash160(pubKeyBytes) _h160 := append([]byte{prefix}, h160...) checksum = CalcHash256(_h160)[:4] From 9e57d521efa0bf734c51e0cad34837d31becc60b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 10 Apr 2017 13:05:52 +0200 Subject: [PATCH 058/273] Add type assertions for sig/pub/privkey implemenetations --- priv_key.go | 4 ++++ pub_key.go | 4 ++++ signature.go | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/priv_key.go b/priv_key.go index 74d5b5a3e..efb85908c 100644 --- a/priv_key.go +++ b/priv_key.go @@ -64,6 +64,8 @@ var privKeyMapper = data.NewMapper(PrivKey{}). //------------------------------------- +var _ PrivKeyInner = PrivKeyEd25519{} + // Implements PrivKey type PrivKeyEd25519 [64]byte @@ -149,6 +151,8 @@ func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 { //------------------------------------- +var _ PrivKeyInner = PrivKeySecp256k1{} + // Implements PrivKey type PrivKeySecp256k1 [32]byte diff --git a/pub_key.go b/pub_key.go index e6567d347..4de7d59cd 100644 --- a/pub_key.go +++ b/pub_key.go @@ -67,6 +67,8 @@ var pubKeyMapper = data.NewMapper(PubKey{}). //------------------------------------- +var _ PubKeyInner = PubKeyEd25519{} + // Implements PubKeyInner type PubKeyEd25519 [32]byte @@ -146,6 +148,8 @@ func (pubKey PubKeyEd25519) Wrap() PubKey { //------------------------------------- +var _ PubKeyInner = PubKeySecp256k1{} + // Implements PubKey. // Compressed pubkey (just the x-cord), // prefixed with 0x02 or 0x03, depending on the y-cord. diff --git a/signature.go b/signature.go index 66c9a8a27..5a165dc42 100644 --- a/signature.go +++ b/signature.go @@ -62,6 +62,8 @@ var sigMapper = data.NewMapper(Signature{}). //------------------------------------- +var _ SignatureInner = SignatureEd25519{} + // Implements Signature type SignatureEd25519 [64]byte @@ -100,6 +102,8 @@ func (sig SignatureEd25519) Wrap() Signature { //------------------------------------- +var _ SignatureInner = SignatureSecp256k1{} + // Implements Signature type SignatureSecp256k1 []byte From aecc32d3636d86cf66af9b39fc20bb53578c78c2 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 10 Apr 2017 13:10:57 +0200 Subject: [PATCH 059/273] Make dependencies explicit in glide.yaml --- .gitignore | 5 +++++ Makefile | 2 +- glide.yaml | 31 +++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 glide.yaml diff --git a/.gitignore b/.gitignore index 381931381..aac058142 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ *.swp *.swo +vendor + +# these should be locked in the including repo, the dependencies are mainly +# for testing and documentation +glide.lock diff --git a/Makefile b/Makefile index 0cd05448a..b6bd861a6 100644 --- a/Makefile +++ b/Makefile @@ -6,4 +6,4 @@ docs: godoc2md $(REPO) > README.md test: - go test ./... + go test `glide novendor` diff --git a/glide.yaml b/glide.yaml new file mode 100644 index 000000000..4703d68c6 --- /dev/null +++ b/glide.yaml @@ -0,0 +1,31 @@ +package: github.com/tendermint/go-crypto +import: +- package: github.com/btcsuite/btcd + subpackages: + - btcec +- package: github.com/btcsuite/btcutil + subpackages: + - base58 +- package: github.com/tendermint/ed25519 + subpackages: + - extra25519 +- package: github.com/tendermint/go-common +- package: github.com/tendermint/go-data + version: develop +- package: github.com/tendermint/go-wire + version: develop +- package: golang.org/x/crypto + subpackages: + - blowfish + - nacl/secretbox + - openpgp/armor + - ripemd160 +testImport: +- package: github.com/mndrix/btcutil +- package: github.com/stretchr/testify + version: ^1.1.4 + subpackages: + - assert + - require +- package: github.com/tyler-smith/go-bip32 +- package: github.com/tyler-smith/go-bip39 From c410fc5e246e9accf95c6e80cb3c6aca2280755c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 10 Apr 2017 14:24:07 +0200 Subject: [PATCH 060/273] Add extra test for encoding with sig,for p2p test fail --- encode_test.go | 73 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/encode_test.go b/encode_test.go index 2d709b943..c3380d435 100644 --- a/encode_test.go +++ b/encode_test.go @@ -16,13 +16,15 @@ type byter interface { } // go to wire encoding and back -func checkWire(t *testing.T, in byter, reader interface{}, typ byte) { +func checkWire(t *testing.T, in byter, reader interface{}, typ byte, size int) { // test to and from binary bin, err := data.ToWire(in) require.Nil(t, err, "%+v", err) assert.Equal(t, typ, bin[0]) // make sure this is compatible with current (Bytes()) encoding assert.Equal(t, in.Bytes(), bin) + // make sure we have the expected length + assert.Equal(t, size, len(bin)) err = data.FromWire(bin, reader) require.Nil(t, err, "%+v", err) @@ -67,23 +69,29 @@ func TestKeyEncodings(t *testing.T) { privKey PrivKey keyType byte keyName string + // 1 (type byte) + size of byte array + privSize, pubSize int }{ { - privKey: GenPrivKeyEd25519().Wrap(), - keyType: TypeEd25519, - keyName: NameEd25519, + privKey: GenPrivKeyEd25519().Wrap(), + keyType: TypeEd25519, + keyName: NameEd25519, + privSize: 65, + pubSize: 33, }, { - privKey: GenPrivKeySecp256k1().Wrap(), - keyType: TypeSecp256k1, - keyName: NameSecp256k1, + privKey: GenPrivKeySecp256k1().Wrap(), + keyType: TypeSecp256k1, + keyName: NameSecp256k1, + privSize: 33, + pubSize: 34, }, } for _, tc := range cases { // check (de/en)codings of private key var priv2, priv3, priv4 PrivKey - checkWire(t, tc.privKey, &priv2, tc.keyType) + checkWire(t, tc.privKey, &priv2, tc.keyType, tc.privSize) assert.EqualValues(t, tc.privKey, priv2) checkJSON(t, tc.privKey, &priv3, tc.keyName) assert.EqualValues(t, tc.privKey, priv3) @@ -93,7 +101,7 @@ func TestKeyEncodings(t *testing.T) { // check (de/en)codings of public key pubKey := tc.privKey.PubKey() var pub2, pub3, pub4 PubKey - checkWire(t, pubKey, &pub2, tc.keyType) + checkWire(t, pubKey, &pub2, tc.keyType, tc.pubSize) assert.EqualValues(t, pubKey, pub2) checkJSON(t, pubKey, &pub3, tc.keyName) assert.EqualValues(t, pubKey, pub3) @@ -126,3 +134,50 @@ func TestNilEncodings(t *testing.T) { assert.EqualValues(t, e, f) } + +type SigMessage struct { + Key PubKey + Sig Signature +} + +func (s SigMessage) Bytes() []byte { + return wire.BinaryBytes(s) +} + +func TestEmbededWireEncodings(t *testing.T) { + assert := assert.New(t) + + cases := []struct { + privKey PrivKey + keyType byte + keyName string + size int // pub + sig size + }{ + { + privKey: GenPrivKeyEd25519().Wrap(), + keyType: TypeEd25519, + keyName: NameEd25519, + size: 2 + 32 + 64, + }, + // { + // privKey: GenPrivKeySecp256k1().Wrap(), + // keyType: TypeSecp256k1, + // keyName: NameSecp256k1, + // size: 2 + 33 + 72, // ugh, either 72 or 73 depending.... + // }, + } + + payload := randBytes(20) + for i, tc := range cases { + pubKey := tc.privKey.PubKey() + sig := tc.privKey.Sign(payload) + assert.True(pubKey.VerifyBytes(payload, sig), "%d", i) + + msg := SigMessage{ + Key: pubKey, + Sig: sig, + } + var msg2 SigMessage + checkWire(t, msg, &msg2, tc.keyType, tc.size) + } +} From 8bb25ec5ed8fcdc75cd67e77765379b524fd6931 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 18 Apr 2017 18:17:02 -0400 Subject: [PATCH 061/273] update paths --- armor.go | 2 +- embed_test.go | 2 +- encode_test.go | 2 +- glide.yaml | 7 +++---- priv_key.go | 4 ++-- pub_key.go | 4 ++-- random.go | 2 +- signature.go | 4 ++-- signature_test.go | 2 +- symmetric.go | 2 +- 10 files changed, 15 insertions(+), 16 deletions(-) diff --git a/armor.go b/armor.go index 9343284e1..3d2eff5e7 100644 --- a/armor.go +++ b/armor.go @@ -4,7 +4,7 @@ import ( "bytes" "io/ioutil" - . "github.com/tendermint/go-common" + . "github.com/tendermint/tmlibs/common" "golang.org/x/crypto/openpgp/armor" ) diff --git a/embed_test.go b/embed_test.go index 6ebba893c..e2d2fe504 100644 --- a/embed_test.go +++ b/embed_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - data "github.com/tendermint/go-data" + data "github.com/tendermint/go-wire/data" ) type PubName struct { diff --git a/encode_test.go b/encode_test.go index c3380d435..6c5d03a1d 100644 --- a/encode_test.go +++ b/encode_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - data "github.com/tendermint/go-data" + data "github.com/tendermint/go-wire/data" wire "github.com/tendermint/go-wire" ) diff --git a/glide.yaml b/glide.yaml index 4703d68c6..d5e0e2bbf 100644 --- a/glide.yaml +++ b/glide.yaml @@ -9,11 +9,10 @@ import: - package: github.com/tendermint/ed25519 subpackages: - extra25519 -- package: github.com/tendermint/go-common -- package: github.com/tendermint/go-data - version: develop +- package: github.com/tendermint/tmlibs + version: unstable - package: github.com/tendermint/go-wire - version: develop + version: unstable - package: golang.org/x/crypto subpackages: - blowfish diff --git a/priv_key.go b/priv_key.go index efb85908c..85f8a8ec4 100644 --- a/priv_key.go +++ b/priv_key.go @@ -6,8 +6,8 @@ import ( secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" - . "github.com/tendermint/go-common" - data "github.com/tendermint/go-data" + . "github.com/tendermint/tmlibs/common" + data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-wire" ) diff --git a/pub_key.go b/pub_key.go index 4de7d59cd..99839f288 100644 --- a/pub_key.go +++ b/pub_key.go @@ -7,8 +7,8 @@ import ( secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" - . "github.com/tendermint/go-common" - data "github.com/tendermint/go-data" + . "github.com/tendermint/tmlibs/common" + data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-wire" "golang.org/x/crypto/ripemd160" ) diff --git a/random.go b/random.go index edadeaab6..40cbcf8fa 100644 --- a/random.go +++ b/random.go @@ -8,7 +8,7 @@ import ( "io" "sync" - . "github.com/tendermint/go-common" + . "github.com/tendermint/tmlibs/common" ) var gRandInfo *randInfo diff --git a/signature.go b/signature.go index 5a165dc42..36451ed48 100644 --- a/signature.go +++ b/signature.go @@ -4,8 +4,8 @@ import ( "bytes" "fmt" - . "github.com/tendermint/go-common" - data "github.com/tendermint/go-data" + . "github.com/tendermint/tmlibs/common" + data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-wire" ) diff --git a/signature_test.go b/signature_test.go index 93aa17279..5e9f06723 100644 --- a/signature_test.go +++ b/signature_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/ed25519" - data "github.com/tendermint/go-data" + data "github.com/tendermint/go-wire/data" ) func TestSignAndValidateEd25519(t *testing.T) { diff --git a/symmetric.go b/symmetric.go index 36bddd44c..d4ac9b55b 100644 --- a/symmetric.go +++ b/symmetric.go @@ -3,7 +3,7 @@ package crypto import ( "errors" - . "github.com/tendermint/go-common" + . "github.com/tendermint/tmlibs/common" "golang.org/x/crypto/nacl/secretbox" ) From 17ed6d178d8d1eff960ff84b38be4ceda97bade8 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 19 Apr 2017 16:51:29 +0200 Subject: [PATCH 062/273] move go-crypto files pre-keys merge --- LICENSE => crypto/LICENSE | 0 Makefile => crypto/Makefile | 0 README.md => crypto/README.md | 0 armor.go => crypto/armor.go | 0 armor_test.go => crypto/armor_test.go | 0 {bcrypt => crypto/bcrypt}/base64.go | 0 {bcrypt => crypto/bcrypt}/bcrypt.go | 0 crypto.go => crypto/crypto.go | 0 embed_test.go => crypto/embed_test.go | 0 encode_test.go => crypto/encode_test.go | 0 glide.yaml => crypto/glide.yaml | 0 hash.go => crypto/hash.go | 0 {hd => crypto/hd}/address.go | 0 {hd => crypto/hd}/address_test.go | 0 {hd => crypto/hd}/hd_test.go | 0 {hd => crypto/hd}/test.json | 0 priv_key.go => crypto/priv_key.go | 0 pub_key.go => crypto/pub_key.go | 0 pub_key_test.go => crypto/pub_key_test.go | 0 random.go => crypto/random.go | 0 signature.go => crypto/signature.go | 0 signature_test.go => crypto/signature_test.go | 0 symmetric.go => crypto/symmetric.go | 0 symmetric_test.go => crypto/symmetric_test.go | 0 24 files changed, 0 insertions(+), 0 deletions(-) rename LICENSE => crypto/LICENSE (100%) rename Makefile => crypto/Makefile (100%) rename README.md => crypto/README.md (100%) rename armor.go => crypto/armor.go (100%) rename armor_test.go => crypto/armor_test.go (100%) rename {bcrypt => crypto/bcrypt}/base64.go (100%) rename {bcrypt => crypto/bcrypt}/bcrypt.go (100%) rename crypto.go => crypto/crypto.go (100%) rename embed_test.go => crypto/embed_test.go (100%) rename encode_test.go => crypto/encode_test.go (100%) rename glide.yaml => crypto/glide.yaml (100%) rename hash.go => crypto/hash.go (100%) rename {hd => crypto/hd}/address.go (100%) rename {hd => crypto/hd}/address_test.go (100%) rename {hd => crypto/hd}/hd_test.go (100%) rename {hd => crypto/hd}/test.json (100%) rename priv_key.go => crypto/priv_key.go (100%) rename pub_key.go => crypto/pub_key.go (100%) rename pub_key_test.go => crypto/pub_key_test.go (100%) rename random.go => crypto/random.go (100%) rename signature.go => crypto/signature.go (100%) rename signature_test.go => crypto/signature_test.go (100%) rename symmetric.go => crypto/symmetric.go (100%) rename symmetric_test.go => crypto/symmetric_test.go (100%) diff --git a/LICENSE b/crypto/LICENSE similarity index 100% rename from LICENSE rename to crypto/LICENSE diff --git a/Makefile b/crypto/Makefile similarity index 100% rename from Makefile rename to crypto/Makefile diff --git a/README.md b/crypto/README.md similarity index 100% rename from README.md rename to crypto/README.md diff --git a/armor.go b/crypto/armor.go similarity index 100% rename from armor.go rename to crypto/armor.go diff --git a/armor_test.go b/crypto/armor_test.go similarity index 100% rename from armor_test.go rename to crypto/armor_test.go diff --git a/bcrypt/base64.go b/crypto/bcrypt/base64.go similarity index 100% rename from bcrypt/base64.go rename to crypto/bcrypt/base64.go diff --git a/bcrypt/bcrypt.go b/crypto/bcrypt/bcrypt.go similarity index 100% rename from bcrypt/bcrypt.go rename to crypto/bcrypt/bcrypt.go diff --git a/crypto.go b/crypto/crypto.go similarity index 100% rename from crypto.go rename to crypto/crypto.go diff --git a/embed_test.go b/crypto/embed_test.go similarity index 100% rename from embed_test.go rename to crypto/embed_test.go diff --git a/encode_test.go b/crypto/encode_test.go similarity index 100% rename from encode_test.go rename to crypto/encode_test.go diff --git a/glide.yaml b/crypto/glide.yaml similarity index 100% rename from glide.yaml rename to crypto/glide.yaml diff --git a/hash.go b/crypto/hash.go similarity index 100% rename from hash.go rename to crypto/hash.go diff --git a/hd/address.go b/crypto/hd/address.go similarity index 100% rename from hd/address.go rename to crypto/hd/address.go diff --git a/hd/address_test.go b/crypto/hd/address_test.go similarity index 100% rename from hd/address_test.go rename to crypto/hd/address_test.go diff --git a/hd/hd_test.go b/crypto/hd/hd_test.go similarity index 100% rename from hd/hd_test.go rename to crypto/hd/hd_test.go diff --git a/hd/test.json b/crypto/hd/test.json similarity index 100% rename from hd/test.json rename to crypto/hd/test.json diff --git a/priv_key.go b/crypto/priv_key.go similarity index 100% rename from priv_key.go rename to crypto/priv_key.go diff --git a/pub_key.go b/crypto/pub_key.go similarity index 100% rename from pub_key.go rename to crypto/pub_key.go diff --git a/pub_key_test.go b/crypto/pub_key_test.go similarity index 100% rename from pub_key_test.go rename to crypto/pub_key_test.go diff --git a/random.go b/crypto/random.go similarity index 100% rename from random.go rename to crypto/random.go diff --git a/signature.go b/crypto/signature.go similarity index 100% rename from signature.go rename to crypto/signature.go diff --git a/signature_test.go b/crypto/signature_test.go similarity index 100% rename from signature_test.go rename to crypto/signature_test.go diff --git a/symmetric.go b/crypto/symmetric.go similarity index 100% rename from symmetric.go rename to crypto/symmetric.go diff --git a/symmetric_test.go b/crypto/symmetric_test.go similarity index 100% rename from symmetric_test.go rename to crypto/symmetric_test.go From 9016390a6e4d957b909650dbfa63b81510c3a68d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 19 Apr 2017 16:55:15 +0200 Subject: [PATCH 063/273] Moved crypto code to top level again --- crypto/LICENSE => LICENSE | 0 crypto/Makefile => Makefile | 0 crypto/README.md => README.md | 0 crypto/armor.go => armor.go | 0 crypto/armor_test.go => armor_test.go | 0 {crypto/bcrypt => bcrypt}/base64.go | 0 {crypto/bcrypt => bcrypt}/bcrypt.go | 0 crypto/crypto.go => crypto.go | 0 crypto/embed_test.go => embed_test.go | 0 crypto/encode_test.go => encode_test.go | 0 crypto/glide.yaml => glide.yaml | 0 crypto/hash.go => hash.go | 0 {crypto/hd => hd}/address.go | 0 {crypto/hd => hd}/address_test.go | 0 {crypto/hd => hd}/hd_test.go | 0 {crypto/hd => hd}/test.json | 0 keys/cmd/keys/main.go | 2 +- keys/cmd/root.go | 6 +++--- keys/cmd/serve.go | 2 +- keys/cmd/utils.go | 2 +- keys/cryptostore/enc_storage.go | 2 +- keys/cryptostore/encoder_test.go | 2 +- keys/cryptostore/holder.go | 2 +- keys/cryptostore/holder_test.go | 4 ++-- keys/cryptostore/storage_test.go | 2 +- keys/server/helpers.go | 2 +- keys/server/keys.go | 4 ++-- keys/server/keys_test.go | 10 +++++----- keys/storage/filestorage/main.go | 2 +- keys/storage/filestorage/main_test.go | 2 +- keys/storage/memstorage/main.go | 2 +- keys/storage/memstorage/main_test.go | 2 +- keys/tx/multi_test.go | 6 +++--- keys/tx/one_test.go | 6 +++--- keys/tx/reader.go | 2 +- keys/tx/reader_test.go | 4 ++-- crypto/priv_key.go => priv_key.go | 0 crypto/pub_key.go => pub_key.go | 0 crypto/pub_key_test.go => pub_key_test.go | 0 crypto/random.go => random.go | 0 crypto/signature.go => signature.go | 0 crypto/signature_test.go => signature_test.go | 0 crypto/symmetric.go => symmetric.go | 0 crypto/symmetric_test.go => symmetric_test.go | 0 44 files changed, 33 insertions(+), 33 deletions(-) rename crypto/LICENSE => LICENSE (100%) rename crypto/Makefile => Makefile (100%) rename crypto/README.md => README.md (100%) rename crypto/armor.go => armor.go (100%) rename crypto/armor_test.go => armor_test.go (100%) rename {crypto/bcrypt => bcrypt}/base64.go (100%) rename {crypto/bcrypt => bcrypt}/bcrypt.go (100%) rename crypto/crypto.go => crypto.go (100%) rename crypto/embed_test.go => embed_test.go (100%) rename crypto/encode_test.go => encode_test.go (100%) rename crypto/glide.yaml => glide.yaml (100%) rename crypto/hash.go => hash.go (100%) rename {crypto/hd => hd}/address.go (100%) rename {crypto/hd => hd}/address_test.go (100%) rename {crypto/hd => hd}/hd_test.go (100%) rename {crypto/hd => hd}/test.json (100%) rename crypto/priv_key.go => priv_key.go (100%) rename crypto/pub_key.go => pub_key.go (100%) rename crypto/pub_key_test.go => pub_key_test.go (100%) rename crypto/random.go => random.go (100%) rename crypto/signature.go => signature.go (100%) rename crypto/signature_test.go => signature_test.go (100%) rename crypto/symmetric.go => symmetric.go (100%) rename crypto/symmetric_test.go => symmetric_test.go (100%) diff --git a/crypto/LICENSE b/LICENSE similarity index 100% rename from crypto/LICENSE rename to LICENSE diff --git a/crypto/Makefile b/Makefile similarity index 100% rename from crypto/Makefile rename to Makefile diff --git a/crypto/README.md b/README.md similarity index 100% rename from crypto/README.md rename to README.md diff --git a/crypto/armor.go b/armor.go similarity index 100% rename from crypto/armor.go rename to armor.go diff --git a/crypto/armor_test.go b/armor_test.go similarity index 100% rename from crypto/armor_test.go rename to armor_test.go diff --git a/crypto/bcrypt/base64.go b/bcrypt/base64.go similarity index 100% rename from crypto/bcrypt/base64.go rename to bcrypt/base64.go diff --git a/crypto/bcrypt/bcrypt.go b/bcrypt/bcrypt.go similarity index 100% rename from crypto/bcrypt/bcrypt.go rename to bcrypt/bcrypt.go diff --git a/crypto/crypto.go b/crypto.go similarity index 100% rename from crypto/crypto.go rename to crypto.go diff --git a/crypto/embed_test.go b/embed_test.go similarity index 100% rename from crypto/embed_test.go rename to embed_test.go diff --git a/crypto/encode_test.go b/encode_test.go similarity index 100% rename from crypto/encode_test.go rename to encode_test.go diff --git a/crypto/glide.yaml b/glide.yaml similarity index 100% rename from crypto/glide.yaml rename to glide.yaml diff --git a/crypto/hash.go b/hash.go similarity index 100% rename from crypto/hash.go rename to hash.go diff --git a/crypto/hd/address.go b/hd/address.go similarity index 100% rename from crypto/hd/address.go rename to hd/address.go diff --git a/crypto/hd/address_test.go b/hd/address_test.go similarity index 100% rename from crypto/hd/address_test.go rename to hd/address_test.go diff --git a/crypto/hd/hd_test.go b/hd/hd_test.go similarity index 100% rename from crypto/hd/hd_test.go rename to hd/hd_test.go diff --git a/crypto/hd/test.json b/hd/test.json similarity index 100% rename from crypto/hd/test.json rename to hd/test.json diff --git a/keys/cmd/keys/main.go b/keys/cmd/keys/main.go index 8b92b3f49..995df845b 100644 --- a/keys/cmd/keys/main.go +++ b/keys/cmd/keys/main.go @@ -17,7 +17,7 @@ package main import ( "os" - "github.com/tendermint/go-keys/cmd" + "github.com/tendermint/go-crypto/keys/cmd" ) func main() { diff --git a/keys/cmd/root.go b/keys/cmd/root.go index 64adf2b0b..401e7ec38 100644 --- a/keys/cmd/root.go +++ b/keys/cmd/root.go @@ -19,9 +19,9 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" - keys "github.com/tendermint/go-keys" - "github.com/tendermint/go-keys/cryptostore" - "github.com/tendermint/go-keys/storage/filestorage" + keys "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/go-crypto/keys/cryptostore" + "github.com/tendermint/go-crypto/keys/storage/filestorage" ) const KeySubdir = "keys" diff --git a/keys/cmd/serve.go b/keys/cmd/serve.go index c3f7dbe39..5ea96db3f 100644 --- a/keys/cmd/serve.go +++ b/keys/cmd/serve.go @@ -25,7 +25,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/go-keys/server" + "github.com/tendermint/go-crypto/keys/server" ) // serveCmd represents the serve command diff --git a/keys/cmd/utils.go b/keys/cmd/utils.go index 31a3a8df3..c61383004 100644 --- a/keys/cmd/utils.go +++ b/keys/cmd/utils.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/viper" data "github.com/tendermint/go-data" - keys "github.com/tendermint/go-keys" + keys "github.com/tendermint/go-crypto/keys" ) const PassLength = 10 diff --git a/keys/cryptostore/enc_storage.go b/keys/cryptostore/enc_storage.go index 9589f4cc1..70e212138 100644 --- a/keys/cryptostore/enc_storage.go +++ b/keys/cryptostore/enc_storage.go @@ -2,7 +2,7 @@ package cryptostore import ( crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-keys" + keys "github.com/tendermint/go-crypto/keys" ) // encryptedStorage needs passphrase to get private keys diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go index 8b72509ed..0535737d7 100644 --- a/keys/cryptostore/encoder_test.go +++ b/keys/cryptostore/encoder_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tendermint/go-keys/cryptostore" + "github.com/tendermint/go-crypto/keys/cryptostore" ) func TestNoopEncoder(t *testing.T) { diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 549326614..42d4662de 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -1,6 +1,6 @@ package cryptostore -import keys "github.com/tendermint/go-keys" +import keys "github.com/tendermint/go-crypto/keys" // Manager combines encyption and storage implementation to provide // a full-featured key manager diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 860869c86..4f0383198 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/go-keys/cryptostore" - "github.com/tendermint/go-keys/storage/memstorage" + "github.com/tendermint/go-crypto/keys/cryptostore" + "github.com/tendermint/go-crypto/keys/storage/memstorage" ) // TestKeyManagement makes sure we can manipulate these keys well diff --git a/keys/cryptostore/storage_test.go b/keys/cryptostore/storage_test.go index 78d107c11..b109c44e8 100644 --- a/keys/cryptostore/storage_test.go +++ b/keys/cryptostore/storage_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - keys "github.com/tendermint/go-keys" + keys "github.com/tendermint/go-crypto/keys" ) func TestSortKeys(t *testing.T) { diff --git a/keys/server/helpers.go b/keys/server/helpers.go index 111f158e7..954922060 100644 --- a/keys/server/helpers.go +++ b/keys/server/helpers.go @@ -13,7 +13,7 @@ import ( "net/http" data "github.com/tendermint/go-data" - "github.com/tendermint/go-keys/server/types" + "github.com/tendermint/go-crypto/keys/server/types" "github.com/pkg/errors" ) diff --git a/keys/server/keys.go b/keys/server/keys.go index 78a382e5e..90d6da2b0 100644 --- a/keys/server/keys.go +++ b/keys/server/keys.go @@ -5,8 +5,8 @@ import ( "net/http" "github.com/gorilla/mux" - keys "github.com/tendermint/go-keys" - "github.com/tendermint/go-keys/server/types" + keys "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/go-crypto/keys/server/types" ) type Keys struct { diff --git a/keys/server/keys_test.go b/keys/server/keys_test.go index 8333e8e53..4908559b0 100644 --- a/keys/server/keys_test.go +++ b/keys/server/keys_test.go @@ -10,11 +10,11 @@ import ( "github.com/gorilla/mux" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - keys "github.com/tendermint/go-keys" - "github.com/tendermint/go-keys/cryptostore" - "github.com/tendermint/go-keys/server" - "github.com/tendermint/go-keys/server/types" - "github.com/tendermint/go-keys/storage/memstorage" + keys "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/go-crypto/keys/cryptostore" + "github.com/tendermint/go-crypto/keys/server" + "github.com/tendermint/go-crypto/keys/server/types" + "github.com/tendermint/go-crypto/keys/storage/memstorage" ) func TestKeyServer(t *testing.T) { diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go index 737f0772c..1add482e2 100644 --- a/keys/storage/filestorage/main.go +++ b/keys/storage/filestorage/main.go @@ -14,7 +14,7 @@ import ( "github.com/pkg/errors" crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-keys" + keys "github.com/tendermint/go-crypto/keys" ) const ( diff --git a/keys/storage/filestorage/main_test.go b/keys/storage/filestorage/main_test.go index 890898dcb..c569eb6f9 100644 --- a/keys/storage/filestorage/main_test.go +++ b/keys/storage/filestorage/main_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-keys" + keys "github.com/tendermint/go-crypto/keys" ) func TestBasicCRUD(t *testing.T) { diff --git a/keys/storage/memstorage/main.go b/keys/storage/memstorage/main.go index 69c8d9b03..195fa7a17 100644 --- a/keys/storage/memstorage/main.go +++ b/keys/storage/memstorage/main.go @@ -7,7 +7,7 @@ package memstorage import ( "github.com/pkg/errors" - keys "github.com/tendermint/go-keys" + keys "github.com/tendermint/go-crypto/keys" ) type data struct { diff --git a/keys/storage/memstorage/main_test.go b/keys/storage/memstorage/main_test.go index 7605c8225..8bc7e355f 100644 --- a/keys/storage/memstorage/main_test.go +++ b/keys/storage/memstorage/main_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-keys" + keys "github.com/tendermint/go-crypto/keys" ) func TestBasicCRUD(t *testing.T) { diff --git a/keys/tx/multi_test.go b/keys/tx/multi_test.go index 815b9e15a..97463a5f7 100644 --- a/keys/tx/multi_test.go +++ b/keys/tx/multi_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-keys" - "github.com/tendermint/go-keys/cryptostore" - "github.com/tendermint/go-keys/storage/memstorage" + keys "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/go-crypto/keys/cryptostore" + "github.com/tendermint/go-crypto/keys/storage/memstorage" ) func TestMultiSig(t *testing.T) { diff --git a/keys/tx/one_test.go b/keys/tx/one_test.go index 71b8011ef..05af347b4 100644 --- a/keys/tx/one_test.go +++ b/keys/tx/one_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-keys" - "github.com/tendermint/go-keys/cryptostore" - "github.com/tendermint/go-keys/storage/memstorage" + keys "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/go-crypto/keys/cryptostore" + "github.com/tendermint/go-crypto/keys/storage/memstorage" ) func TestOneSig(t *testing.T) { diff --git a/keys/tx/reader.go b/keys/tx/reader.go index 7689693cb..16a403719 100644 --- a/keys/tx/reader.go +++ b/keys/tx/reader.go @@ -3,7 +3,7 @@ package tx import ( crypto "github.com/tendermint/go-crypto" data "github.com/tendermint/go-data" - keys "github.com/tendermint/go-keys" + keys "github.com/tendermint/go-crypto/keys" ) const ( diff --git a/keys/tx/reader_test.go b/keys/tx/reader_test.go index 54b76af96..4b365604d 100644 --- a/keys/tx/reader_test.go +++ b/keys/tx/reader_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" data "github.com/tendermint/go-data" - "github.com/tendermint/go-keys/cryptostore" - "github.com/tendermint/go-keys/storage/memstorage" + "github.com/tendermint/go-crypto/keys/cryptostore" + "github.com/tendermint/go-crypto/keys/storage/memstorage" ) func TestReader(t *testing.T) { diff --git a/crypto/priv_key.go b/priv_key.go similarity index 100% rename from crypto/priv_key.go rename to priv_key.go diff --git a/crypto/pub_key.go b/pub_key.go similarity index 100% rename from crypto/pub_key.go rename to pub_key.go diff --git a/crypto/pub_key_test.go b/pub_key_test.go similarity index 100% rename from crypto/pub_key_test.go rename to pub_key_test.go diff --git a/crypto/random.go b/random.go similarity index 100% rename from crypto/random.go rename to random.go diff --git a/crypto/signature.go b/signature.go similarity index 100% rename from crypto/signature.go rename to signature.go diff --git a/crypto/signature_test.go b/signature_test.go similarity index 100% rename from crypto/signature_test.go rename to signature_test.go diff --git a/crypto/symmetric.go b/symmetric.go similarity index 100% rename from crypto/symmetric.go rename to symmetric.go diff --git a/crypto/symmetric_test.go b/symmetric_test.go similarity index 100% rename from crypto/symmetric_test.go rename to symmetric_test.go From 0bfae964e140ef1d8b25e5838430c459e04760e1 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 19 Apr 2017 17:07:12 +0200 Subject: [PATCH 064/273] Moved keys cmd to top level --- .gitignore | 4 - Makefile | 20 +++- {keys/cmd => cmd}/README.md | 0 {keys/cmd => cmd}/common.go | 2 +- {keys/cmd => cmd}/get.go | 0 {keys/cmd => cmd}/keys/main.go | 2 +- {keys/cmd => cmd}/list.go | 0 {keys/cmd => cmd}/new.go | 0 {keys/cmd => cmd}/root.go | 0 {keys/cmd => cmd}/serve.go | 0 {keys/cmd => cmd}/update.go | 0 {keys/cmd => cmd}/utils.go | 2 +- keys/glide.lock => glide.lock | 75 ++++++++---- glide.yaml | 10 ++ keys/LICENSE | 202 --------------------------------- keys/glide.yaml | 19 ---- 16 files changed, 82 insertions(+), 254 deletions(-) rename {keys/cmd => cmd}/README.md (100%) rename {keys/cmd => cmd}/common.go (98%) rename {keys/cmd => cmd}/get.go (100%) rename {keys/cmd => cmd}/keys/main.go (94%) rename {keys/cmd => cmd}/list.go (100%) rename {keys/cmd => cmd}/new.go (100%) rename {keys/cmd => cmd}/root.go (100%) rename {keys/cmd => cmd}/serve.go (100%) rename {keys/cmd => cmd}/update.go (100%) rename {keys/cmd => cmd}/utils.go (97%) rename keys/glide.lock => glide.lock (60%) delete mode 100644 keys/LICENSE delete mode 100644 keys/glide.yaml diff --git a/.gitignore b/.gitignore index aac058142..f37225baa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ *.swp *.swo vendor - -# these should be locked in the including repo, the dependencies are mainly -# for testing and documentation -glide.lock diff --git a/Makefile b/Makefile index b6bd861a6..59440fe66 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,27 @@ -.PHONY: docs +.PHONEY: all docs test install get_vendor_deps ensure_tools + +GOTOOLS = \ + github.com/Masterminds/glide REPO:=github.com/tendermint/go-crypto docs: @go get github.com/davecheney/godoc2md godoc2md $(REPO) > README.md +all: install test + +install: + go install ./cmd/keys + test: go test `glide novendor` + +get_vendor_deps: ensure_tools + @rm -rf vendor/ + @echo "--> Running glide install" + @glide install + +ensure_tools: + go get $(GOTOOLS) + + diff --git a/keys/cmd/README.md b/cmd/README.md similarity index 100% rename from keys/cmd/README.md rename to cmd/README.md diff --git a/keys/cmd/common.go b/cmd/common.go similarity index 98% rename from keys/cmd/common.go rename to cmd/common.go index eb7a158ae..c68cd4304 100644 --- a/keys/cmd/common.go +++ b/cmd/common.go @@ -8,8 +8,8 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - data "github.com/tendermint/go-data" "github.com/tendermint/go-data/base58" + data "github.com/tendermint/go-wire/data" ) /******* diff --git a/keys/cmd/get.go b/cmd/get.go similarity index 100% rename from keys/cmd/get.go rename to cmd/get.go diff --git a/keys/cmd/keys/main.go b/cmd/keys/main.go similarity index 94% rename from keys/cmd/keys/main.go rename to cmd/keys/main.go index 995df845b..8dd8d6505 100644 --- a/keys/cmd/keys/main.go +++ b/cmd/keys/main.go @@ -17,7 +17,7 @@ package main import ( "os" - "github.com/tendermint/go-crypto/keys/cmd" + "github.com/tendermint/go-crypto/cmd" ) func main() { diff --git a/keys/cmd/list.go b/cmd/list.go similarity index 100% rename from keys/cmd/list.go rename to cmd/list.go diff --git a/keys/cmd/new.go b/cmd/new.go similarity index 100% rename from keys/cmd/new.go rename to cmd/new.go diff --git a/keys/cmd/root.go b/cmd/root.go similarity index 100% rename from keys/cmd/root.go rename to cmd/root.go diff --git a/keys/cmd/serve.go b/cmd/serve.go similarity index 100% rename from keys/cmd/serve.go rename to cmd/serve.go diff --git a/keys/cmd/update.go b/cmd/update.go similarity index 100% rename from keys/cmd/update.go rename to cmd/update.go diff --git a/keys/cmd/utils.go b/cmd/utils.go similarity index 97% rename from keys/cmd/utils.go rename to cmd/utils.go index c61383004..a75262676 100644 --- a/keys/cmd/utils.go +++ b/cmd/utils.go @@ -6,8 +6,8 @@ import ( "github.com/bgentry/speakeasy" "github.com/pkg/errors" "github.com/spf13/viper" - data "github.com/tendermint/go-data" keys "github.com/tendermint/go-crypto/keys" + data "github.com/tendermint/go-wire/data" ) const PassLength = 10 diff --git a/keys/glide.lock b/glide.lock similarity index 60% rename from keys/glide.lock rename to glide.lock index c74262a4e..b804b4801 100644 --- a/keys/glide.lock +++ b/glide.lock @@ -1,14 +1,26 @@ -hash: 4a517b0f71ea6e3aadcf98286cde97c2f567e9e7999a4c7ec9ce6e5b6c21564a -updated: 2017-03-02T16:57:20.740518259-05:00 +hash: 8a63c035134ec024df64d8cc43a732712e48e4cfc5de30d45c1b692b3e9a75b8 +updated: 2017-04-19T17:06:49.640329917+02:00 imports: - name: github.com/bgentry/speakeasy version: 675b82c74c0ed12283ee81ba8a534c8982c07b85 - name: github.com/btcsuite/btcd - version: d06c0bb181529331be8f8d9350288c420d9e60e4 + version: 583684b21bfbde9b5fc4403916fd7c807feb0289 subpackages: - btcec + - chaincfg + - chaincfg/chainhash + - wire +- name: github.com/btcsuite/btcutil + version: a5ecb5d9547afe8d1672073dbdc348203de744a0 + subpackages: + - base58 + - hdkeychain +- name: github.com/btcsuite/golangcrypto + version: 53f62d9b43e87a6c56975cf862af7edf33a8d0df + subpackages: + - ripemd160 - name: github.com/fsnotify/fsnotify - version: 7d7316ed6e1ed2de075aab8dfc76de5d158d66e1 + version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-playground/locales version: 084b0226cf88d891a2bdeccac01d592af13a8f7b subpackages: @@ -20,9 +32,9 @@ imports: - name: github.com/gorilla/context version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 - name: github.com/gorilla/handlers - version: 13d73096a474cac93275c679c7b8a2dc17ddba82 + version: 3a5767ca75ece5f7f1440b1d16975247f8d8b221 - name: github.com/gorilla/mux - version: 599cba5e7b6137d46ddf58fb1765f5d928e69604 + version: 392c28fe23e1c45ddba891b0320b3b5df220beea - name: github.com/hashicorp/hcl version: 630949a3c5fa3c613328e1b8256052cbc2327c9b subpackages: @@ -37,25 +49,25 @@ imports: - name: github.com/inconshreveable/mousetrap version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/magiconair/properties - version: b3b15ef068fd0b17ddf408a23669f20811d194d2 + version: 51463bfca2576e06c62a8504b5c0f06d61312647 - name: github.com/mattn/go-colorable - version: 5411d3eea5978e6cdc258b30de592b60df6aba96 + version: a392f450ea64cee2b268dfaacdc2502b50a22b18 - name: github.com/mattn/go-isatty - version: 281032e84ae07510239465db46bf442aa44b953a + version: 57fdcb988a5c543893cc61bce354a6e24ab70022 - name: github.com/mitchellh/mapstructure - version: db1efb556f84b25a0a13a04aad883943538ad2e0 + version: 53818660ed4955e899c0bcafa97299a388bd7c8e - name: github.com/pelletier/go-buffruneio version: c37440a7cf42ac63b919c752ca73a85067e05992 - name: github.com/pelletier/go-toml version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a - name: github.com/pkg/errors - version: 248dadf4e9068a0b3e79f02ed0a610d935de5302 + version: bfd5150e4e41705ded2129ec33379de1cb90b513 - name: github.com/spf13/afero version: 9be650865eab0c12963d8753212f4f9c66cdcf12 subpackages: - mem - name: github.com/spf13/cast - version: f820543c3592e283e311a60d2a600a664e39f6f7 + version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c - name: github.com/spf13/jwalterweatherman @@ -63,55 +75,64 @@ imports: - name: github.com/spf13/pflag version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 - name: github.com/spf13/viper - version: 7538d73b4eb9511d85a9f1dfef202eeb8ac260f4 + version: 5d46e70da8c0b6f812e0b170b7a985753b5c63cb - name: github.com/tendermint/ed25519 version: 1f52c6f8b8a5c7908aff4497c186af344b428925 subpackages: - edwards25519 - extra25519 -- name: github.com/tendermint/go-common - version: 339e135776142939d82bc8e699db0bf391fd938d -- name: github.com/tendermint/go-crypto - version: 562b4cc9ef0d20217f6e95679f9e83cb7bc98b17 - name: github.com/tendermint/go-data - version: 32271140e8fd5abdbb22e268d7a02421fa382f0b + version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 subpackages: - base58 -- name: github.com/tendermint/go-logger - version: cefb3a45c0bf3c493a04e9bcd9b1540528be59f2 - name: github.com/tendermint/go-wire - version: 3216ec9d47bbdf8d4fc27d22169ea86a6688bc15 + version: 9127836cbb6dd99e020cb840a0cedcedc4671468 + subpackages: + - data + - data/base58 - name: github.com/tendermint/log15 version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 subpackages: - term +- name: github.com/tendermint/tmlibs + version: 2f8551d3b614dd0c0c6c114c42ab25901cc41a52 + subpackages: + - common + - logger - name: golang.org/x/crypto - version: 453249f01cfeb54c3d549ddb75ff152ca243f9d8 + version: 728b753d0135da6801d45a38e6f43ff55779c5c2 subpackages: + - bcrypt + - blowfish - nacl/secretbox - openpgp/armor - openpgp/errors + - pbkdf2 - poly1305 - ripemd160 - salsa20/salsa - name: golang.org/x/sys - version: e24f485414aeafb646f6fca458b0bf869c0880a1 + version: 99f16d856c9836c42d24e7ab64ea72916925fa97 subpackages: - unix - name: golang.org/x/text - version: d680ca3ed853995402af43b866311167281bdc20 + version: f4b4367115ec2de254587813edaa901bc1c723a8 subpackages: - transform - unicode/norm - name: gopkg.in/go-playground/validator.v9 version: 4bd19358521c53f09639f21e2a9d6883d6890f24 - name: gopkg.in/yaml.v2 - version: a3f3340b5840cee44f372bddb5880fcbc419b46a + version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b testImports: +- name: github.com/cmars/basen + version: fe3947df716ebfda9847eb1b9a48f9592e06478c - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew +- name: github.com/mndrix/btcutil + version: d3a63a5752ecf3fbc06bd97365da752111c263df - name: github.com/pmezard/go-difflib version: d8ed2627bdf02c080bf22230dbb337003b7aba2d subpackages: @@ -121,3 +142,7 @@ testImports: subpackages: - assert - require +- name: github.com/tyler-smith/go-bip32 + version: eb790af526c30f23a7c8b00a48e342f9d0bd6386 +- name: github.com/tyler-smith/go-bip39 + version: 8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc diff --git a/glide.yaml b/glide.yaml index d5e0e2bbf..2566feef9 100644 --- a/glide.yaml +++ b/glide.yaml @@ -13,12 +13,22 @@ import: version: unstable - package: github.com/tendermint/go-wire version: unstable + subpackages: + - data + - data/base58 - package: golang.org/x/crypto subpackages: - blowfish - nacl/secretbox - openpgp/armor - ripemd160 +- package: github.com/bgentry/speakeasy +- package: github.com/gorilla/handlers +- package: github.com/gorilla/mux +- package: github.com/pkg/errors +- package: github.com/spf13/cobra +- package: github.com/spf13/viper +- package: gopkg.in/go-playground/validator.v9 testImport: - package: github.com/mndrix/btcutil - package: github.com/stretchr/testify diff --git a/keys/LICENSE b/keys/LICENSE deleted file mode 100644 index d64569567..000000000 --- a/keys/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/keys/glide.yaml b/keys/glide.yaml deleted file mode 100644 index 39402fa8b..000000000 --- a/keys/glide.yaml +++ /dev/null @@ -1,19 +0,0 @@ -package: github.com/tendermint/go-keys -import: -- package: github.com/bgentry/speakeasy -- package: github.com/gorilla/handlers -- package: github.com/gorilla/mux -- package: github.com/pkg/errors -- package: github.com/spf13/cobra -- package: github.com/spf13/viper -- package: github.com/tendermint/go-crypto - version: develop -- package: github.com/tendermint/go-data - subpackages: - - base58 -- package: gopkg.in/go-playground/validator.v9 -testImport: -- package: github.com/stretchr/testify - subpackages: - - assert - - require From 91bd7efb7bcc2eecda2715286a08b8dddf5f3f64 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 19 Apr 2017 17:14:19 +0200 Subject: [PATCH 065/273] Fixed all imports in keys --- keys/cryptostore/enc_storage.go | 4 ++-- keys/cryptostore/encoder.go | 2 +- keys/cryptostore/encoder_test.go | 2 +- keys/cryptostore/generator.go | 4 ++-- keys/server/helpers.go | 2 +- keys/storage/filestorage/main.go | 2 +- keys/storage/filestorage/main_test.go | 2 +- keys/storage/memstorage/main_test.go | 2 +- keys/transactions.go | 4 ++-- keys/tx/multi.go | 10 +++++----- keys/tx/one.go | 7 +++---- keys/tx/reader.go | 6 +++--- keys/tx/reader_test.go | 2 +- 13 files changed, 24 insertions(+), 25 deletions(-) diff --git a/keys/cryptostore/enc_storage.go b/keys/cryptostore/enc_storage.go index 70e212138..daeb220b5 100644 --- a/keys/cryptostore/enc_storage.go +++ b/keys/cryptostore/enc_storage.go @@ -24,7 +24,7 @@ func (es encryptedStorage) Put(name, pass string, key crypto.PrivKey) error { func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.Info, error) { secret, info, err := es.store.Get(name) if err != nil { - return nil, info, err + return crypto.PrivKey{}, info, err } key, err := es.coder.Decrypt(secret, pass) return key, info, err @@ -44,6 +44,6 @@ func info(name string, key crypto.PrivKey) keys.Info { return keys.Info{ Name: name, Address: pub.Address(), - PubKey: crypto.PubKeyS{pub}, + PubKey: pub, } } diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 03bc1e4e8..12792813c 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -37,7 +37,7 @@ func (e secretbox) Decrypt(data []byte, pass string) (crypto.PrivKey, error) { s := secret(pass) private, err := crypto.DecryptSymmetric(data, s) if err != nil { - return nil, errors.Wrap(err, "Invalid Passphrase") + return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } key, err := crypto.PrivKeyFromBytes(private) return key, errors.Wrap(err, "Invalid Passphrase") diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go index 0535737d7..e5ea21111 100644 --- a/keys/cryptostore/encoder_test.go +++ b/keys/cryptostore/encoder_test.go @@ -50,7 +50,7 @@ func TestSecretBox(t *testing.T) { // decoding with a different pass is an error pk, err := enc.Decrypt(b, "decode") require.NotNil(err) - require.Nil(pk) + require.True(pk.Empty()) // but decoding with the same passphrase gets us our key pk, err = enc.Decrypt(b, pass) diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index cf877f20b..6bbdb6441 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -25,11 +25,11 @@ func (f GenFunc) Generate() crypto.PrivKey { } func genEd25519() crypto.PrivKey { - return crypto.GenPrivKeyEd25519() + return crypto.GenPrivKeyEd25519().Wrap() } func genSecp256() crypto.PrivKey { - return crypto.GenPrivKeySecp256k1() + return crypto.GenPrivKeySecp256k1().Wrap() } func getGenerator(algo string) (Generator, error) { diff --git a/keys/server/helpers.go b/keys/server/helpers.go index 954922060..710e4f392 100644 --- a/keys/server/helpers.go +++ b/keys/server/helpers.go @@ -12,7 +12,7 @@ import ( "io/ioutil" "net/http" - data "github.com/tendermint/go-data" + data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-crypto/keys/server/types" "github.com/pkg/errors" diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go index 1add482e2..696b200fc 100644 --- a/keys/storage/filestorage/main.go +++ b/keys/storage/filestorage/main.go @@ -135,7 +135,7 @@ func readInfo(path string) (info keys.Info, err error) { return } pk, err := crypto.PubKeyFromBytes(data) - info.PubKey = crypto.PubKeyS{pk} + info.PubKey = pk return } diff --git a/keys/storage/filestorage/main_test.go b/keys/storage/filestorage/main_test.go index c569eb6f9..28c950c2c 100644 --- a/keys/storage/filestorage/main_test.go +++ b/keys/storage/filestorage/main_test.go @@ -25,7 +25,7 @@ func TestBasicCRUD(t *testing.T) { pubkey := crypto.GenPrivKeyEd25519().PubKey() info := keys.Info{ Name: name, - PubKey: crypto.PubKeyS{pubkey}, + PubKey: pubkey.Wrap(), } // No data: Get and Delete return nothing diff --git a/keys/storage/memstorage/main_test.go b/keys/storage/memstorage/main_test.go index 8bc7e355f..feccb387f 100644 --- a/keys/storage/memstorage/main_test.go +++ b/keys/storage/memstorage/main_test.go @@ -17,7 +17,7 @@ func TestBasicCRUD(t *testing.T) { pubkey := crypto.GenPrivKeyEd25519().PubKey() info := keys.Info{ Name: name, - PubKey: crypto.PubKeyS{pubkey}, + PubKey: pubkey, } // No data: Get and Delete return nothing diff --git a/keys/transactions.go b/keys/transactions.go index 91dc0e273..aafb77873 100644 --- a/keys/transactions.go +++ b/keys/transactions.go @@ -4,14 +4,14 @@ import ( "sort" crypto "github.com/tendermint/go-crypto" - data "github.com/tendermint/go-data" + data "github.com/tendermint/go-wire/data" ) // Info is the public information about a key type Info struct { Name string `json:"name"` Address data.Bytes `json:"address"` - PubKey crypto.PubKeyS `json:"pubkey"` + PubKey crypto.PubKey `json:"pubkey"` } func (i *Info) Format() Info { diff --git a/keys/tx/multi.go b/keys/tx/multi.go index eac86b010..f069fb273 100644 --- a/keys/tx/multi.go +++ b/keys/tx/multi.go @@ -3,7 +3,7 @@ package tx import ( "github.com/pkg/errors" crypto "github.com/tendermint/go-crypto" - data "github.com/tendermint/go-data" + data "github.com/tendermint/go-wire/data" ) // MultiSig lets us wrap arbitrary data with a go-crypto signature @@ -16,8 +16,8 @@ type MultiSig struct { } type Signed struct { - Sig crypto.SignatureS - Pubkey crypto.PubKeyS + Sig crypto.Signature + Pubkey crypto.PubKey } var _ SigInner = &MultiSig{} @@ -36,12 +36,12 @@ func (s *MultiSig) SignBytes() []byte { // Depending on the Signable, one may be able to call this multiple times for multisig // Returns error if called with invalid data or too many times func (s *MultiSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error { - if pubkey == nil || sig == nil { + if pubkey.Empty() || sig.Empty() { return errors.New("Signature or Key missing") } // set the value once we are happy - x := Signed{crypto.SignatureS{sig}, crypto.PubKeyS{pubkey}} + x := Signed{sig, pubkey} s.Sigs = append(s.Sigs, x) return nil } diff --git a/keys/tx/one.go b/keys/tx/one.go index 0ad61dd50..af468cc2c 100644 --- a/keys/tx/one.go +++ b/keys/tx/one.go @@ -3,7 +3,7 @@ package tx import ( "github.com/pkg/errors" crypto "github.com/tendermint/go-crypto" - data "github.com/tendermint/go-data" + data "github.com/tendermint/go-wire/data" ) // OneSig lets us wrap arbitrary data with a go-crypto signature @@ -31,7 +31,7 @@ func (s *OneSig) SignBytes() []byte { // Depending on the Signable, one may be able to call this multiple times for multisig // Returns error if called with invalid data or too many times func (s *OneSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error { - if pubkey == nil || sig == nil { + if pubkey.Empty() || sig.Empty() { return errors.New("Signature or Key missing") } if !s.Sig.Empty() { @@ -39,8 +39,7 @@ func (s *OneSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error { } // set the value once we are happy - s.Pubkey = crypto.PubKeyS{pubkey} - s.Sig = crypto.SignatureS{sig} + s.Signed = Signed{sig, pubkey} return nil } diff --git a/keys/tx/reader.go b/keys/tx/reader.go index 16a403719..265e88b46 100644 --- a/keys/tx/reader.go +++ b/keys/tx/reader.go @@ -2,8 +2,8 @@ package tx import ( crypto "github.com/tendermint/go-crypto" - data "github.com/tendermint/go-data" keys "github.com/tendermint/go-crypto/keys" + data "github.com/tendermint/go-wire/data" ) const ( @@ -18,8 +18,8 @@ var TxMapper data.Mapper func init() { TxMapper = data.NewMapper(Sig{}). - RegisterInterface(&OneSig{}, nameOneSig, typeOneSig). - RegisterInterface(&MultiSig{}, nameMultiSig, typeMultiSig) + RegisterImplementation(&OneSig{}, nameOneSig, typeOneSig). + RegisterImplementation(&MultiSig{}, nameMultiSig, typeMultiSig) } /* diff --git a/keys/tx/reader_test.go b/keys/tx/reader_test.go index 4b365604d..c50481f14 100644 --- a/keys/tx/reader_test.go +++ b/keys/tx/reader_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" - data "github.com/tendermint/go-data" + data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-crypto/keys/cryptostore" "github.com/tendermint/go-crypto/keys/storage/memstorage" ) From e3f9b8731bb2e8cb38f2d49dee92713e95f264bb Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 14:31:49 -0400 Subject: [PATCH 066/273] circle.yml --- circle.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 000000000..23ac4bd9f --- /dev/null +++ b/circle.yml @@ -0,0 +1,21 @@ +machine: + environment: + GOPATH: /home/ubuntu/.go_workspace + PROJECT_PARENT_PATH: "$GOPATH/src/github.com/$CIRCLE_PROJECT_USERNAME" + PROJECT_PATH: $GOPATH/src/github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME + GO15VENDOREXPERIMENT: 1 + hosts: + circlehost: 127.0.0.1 + localhost: 127.0.0.1 + +dependencies: + override: + - mkdir -p "$PROJECT_PARENT_PATH" + - ln -sf "$HOME/$CIRCLE_PROJECT_REPONAME/" "$PROJECT_PATH" + post: + - go version + +test: + override: + - "go version" + - "cd $PROJECT_PATH && make get_vendor_deps && make test" From 9b95da8fa4187f6799558d89b271dc8ab6485615 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 21 Apr 2017 16:10:06 -0400 Subject: [PATCH 067/273] go-data -> go-wire/data --- cmd/common.go | 2 +- glide.lock | 20 ++++++++------------ glide.yaml | 4 ++-- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/cmd/common.go b/cmd/common.go index c68cd4304..098bb6c7d 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -8,8 +8,8 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/go-data/base58" data "github.com/tendermint/go-wire/data" + "github.com/tendermint/go-wire/data/base58" ) /******* diff --git a/glide.lock b/glide.lock index b804b4801..dd8ec1952 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 8a63c035134ec024df64d8cc43a732712e48e4cfc5de30d45c1b692b3e9a75b8 -updated: 2017-04-19T17:06:49.640329917+02:00 +hash: 3bcee9fbccf29d21217b24b6a83ec51e1514f37b2ae5d8718cf6c5df80f4fb2c +updated: 2017-04-21T16:09:28.762932633-04:00 imports: - name: github.com/bgentry/speakeasy version: 675b82c74c0ed12283ee81ba8a534c8982c07b85 @@ -51,9 +51,9 @@ imports: - name: github.com/magiconair/properties version: 51463bfca2576e06c62a8504b5c0f06d61312647 - name: github.com/mattn/go-colorable - version: a392f450ea64cee2b268dfaacdc2502b50a22b18 + version: d228849504861217f796da67fae4f6e347643f15 - name: github.com/mattn/go-isatty - version: 57fdcb988a5c543893cc61bce354a6e24ab70022 + version: 30a891c33c7cde7b02a981314b4228ec99380cca - name: github.com/mitchellh/mapstructure version: 53818660ed4955e899c0bcafa97299a388bd7c8e - name: github.com/pelletier/go-buffruneio @@ -81,12 +81,8 @@ imports: subpackages: - edwards25519 - extra25519 -- name: github.com/tendermint/go-data - version: e7fcc6d081ec8518912fcdc103188275f83a3ee5 - subpackages: - - base58 - name: github.com/tendermint/go-wire - version: 9127836cbb6dd99e020cb840a0cedcedc4671468 + version: 334005c236d19c632fb5f073f9de3b0fab6a522b subpackages: - data - data/base58 @@ -95,12 +91,12 @@ imports: subpackages: - term - name: github.com/tendermint/tmlibs - version: 2f8551d3b614dd0c0c6c114c42ab25901cc41a52 + version: 1ea866fd691ded9c1de16408934927d133550efc subpackages: - common - logger - name: golang.org/x/crypto - version: 728b753d0135da6801d45a38e6f43ff55779c5c2 + version: 7c6cc321c680f03b9ef0764448e780704f486b51 subpackages: - bcrypt - blowfish @@ -112,7 +108,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/sys - version: 99f16d856c9836c42d24e7ab64ea72916925fa97 + version: d75a52659825e75fff6158388dddc6a5b04f9ba5 subpackages: - unix - name: golang.org/x/text diff --git a/glide.yaml b/glide.yaml index 2566feef9..58e3aecca 100644 --- a/glide.yaml +++ b/glide.yaml @@ -10,9 +10,9 @@ import: subpackages: - extra25519 - package: github.com/tendermint/tmlibs - version: unstable + version: develop - package: github.com/tendermint/go-wire - version: unstable + version: develop subpackages: - data - data/base58 From 197a2b270fd94ee03824b158e738fce62862d0b8 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 27 Apr 2017 20:59:48 +0200 Subject: [PATCH 068/273] Consolidate keys.Manager interface --- keys/transactions.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/keys/transactions.go b/keys/transactions.go index aafb77873..13d37feb5 100644 --- a/keys/transactions.go +++ b/keys/transactions.go @@ -9,8 +9,8 @@ import ( // Info is the public information about a key type Info struct { - Name string `json:"name"` - Address data.Bytes `json:"address"` + Name string `json:"name"` + Address data.Bytes `json:"address"` PubKey crypto.PubKey `json:"pubkey"` } @@ -62,6 +62,7 @@ type Signer interface { // Manager allows simple CRUD on a keystore, as an aid to signing type Manager interface { + Signer Create(name, passphrase, algo string) (Info, error) List() (Infos, error) Get(name string) (Info, error) From 524ba917a3a1636f21ab2c0bf76b6526903ab879 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 2 May 2017 17:18:08 +0200 Subject: [PATCH 069/273] Use new PrepareMainCmd from tmlibs/cli --- cmd/keys/main.go | 3 ++- glide.lock | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/keys/main.go b/cmd/keys/main.go index 8dd8d6505..0b0d93dec 100644 --- a/cmd/keys/main.go +++ b/cmd/keys/main.go @@ -18,10 +18,11 @@ import ( "os" "github.com/tendermint/go-crypto/cmd" + "github.com/tendermint/tmlibs/cli" ) func main() { - cmd.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) + cli.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) cmd.RootCmd.Execute() // exec() } diff --git a/glide.lock b/glide.lock index dd8ec1952..485e75c76 100644 --- a/glide.lock +++ b/glide.lock @@ -91,10 +91,11 @@ imports: subpackages: - term - name: github.com/tendermint/tmlibs - version: 1ea866fd691ded9c1de16408934927d133550efc + version: d4ab9679d71c8fc174284696d15930cb799fa24f subpackages: - common - logger + - cli - name: golang.org/x/crypto version: 7c6cc321c680f03b9ef0764448e780704f486b51 subpackages: From e71bbb2509b586f0b24f120b6ba57f32aefa1579 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 5 May 2017 19:25:44 +0200 Subject: [PATCH 070/273] Update to make full use of new tmlibs/cli helpers --- cmd/common.go | 120 ----------------------------------------------- cmd/get.go | 15 +++--- cmd/keys/main.go | 5 +- cmd/list.go | 16 ++----- cmd/new.go | 20 ++++---- cmd/root.go | 3 +- cmd/update.go | 21 ++++----- cmd/utils.go | 5 +- glide.lock | 39 ++++++++------- 9 files changed, 55 insertions(+), 189 deletions(-) delete mode 100644 cmd/common.go diff --git a/cmd/common.go b/cmd/common.go deleted file mode 100644 index 098bb6c7d..000000000 --- a/cmd/common.go +++ /dev/null @@ -1,120 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "strings" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/viper" - data "github.com/tendermint/go-wire/data" - "github.com/tendermint/go-wire/data/base58" -) - -/******* - -TODO - -This file should move into go-common or the like as a basis for all cli tools. -It is here for experimentation of re-use between go-keys and light-client. - -*********/ - -const ( - RootFlag = "root" - OutputFlag = "output" - EncodingFlag = "encoding" -) - -func PrepareMainCmd(cmd *cobra.Command, envPrefix, defautRoot string) func() { - cobra.OnInitialize(func() { initEnv(envPrefix) }) - cmd.PersistentFlags().StringP(RootFlag, "r", defautRoot, "root directory for config and data") - cmd.PersistentFlags().StringP(EncodingFlag, "e", "hex", "Binary encoding (hex|b64|btc)") - cmd.PersistentFlags().StringP(OutputFlag, "o", "text", "Output format (text|json)") - cmd.PersistentPreRunE = multiE(bindFlags, setEncoding, validateOutput, cmd.PersistentPreRunE) - return func() { execute(cmd) } -} - -// initEnv sets to use ENV variables if set. -func initEnv(prefix string) { - // env variables with TM prefix (eg. TM_ROOT) - viper.SetEnvPrefix(prefix) - viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) - viper.AutomaticEnv() -} - -// execute adds all child commands to the root command sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func execute(cmd *cobra.Command) { - if err := cmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } -} - -type wrapE func(cmd *cobra.Command, args []string) error - -func multiE(fs ...wrapE) wrapE { - return func(cmd *cobra.Command, args []string) error { - for _, f := range fs { - if f != nil { - if err := f(cmd, args); err != nil { - return err - } - } - } - return nil - } -} - -func bindFlags(cmd *cobra.Command, args []string) error { - // cmd.Flags() includes flags from this command and all persistent flags from the parent - if err := viper.BindPFlags(cmd.Flags()); err != nil { - return err - } - - // rootDir is command line flag, env variable, or default $HOME/.tlc - rootDir := viper.GetString("root") - viper.SetConfigName("config") // name of config file (without extension) - viper.AddConfigPath(rootDir) // search root directory - - // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - // stderr, so if we redirect output to json file, this doesn't appear - // fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) - } else if _, ok := err.(viper.ConfigFileNotFoundError); !ok { - // we ignore not found error, only parse error - // stderr, so if we redirect output to json file, this doesn't appear - fmt.Fprintf(os.Stderr, "%#v", err) - } - return nil -} - -// setEncoding reads the encoding flag -func setEncoding(cmd *cobra.Command, args []string) error { - // validate and set encoding - enc := viper.GetString("encoding") - switch enc { - case "hex": - data.Encoder = data.HexEncoder - case "b64": - data.Encoder = data.B64Encoder - case "btc": - data.Encoder = base58.BTCEncoder - default: - return errors.Errorf("Unsupported encoding: %s", enc) - } - return nil -} - -func validateOutput(cmd *cobra.Command, args []string) error { - // validate output format - output := viper.GetString(OutputFlag) - switch output { - case "text", "json": - default: - return errors.Errorf("Unsupported output format: %s", output) - } - return nil -} diff --git a/cmd/get.go b/cmd/get.go index 9b8718996..6e8c620d0 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -15,7 +15,7 @@ package cmd import ( - "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -25,20 +25,17 @@ var getCmd = &cobra.Command{ Use: "get ", Short: "Get details of one key", Long: `Return public details of one local key.`, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { - fmt.Println("You must provide a name for the key") - return + return errors.New("You must provide a name for the key") } name := args[0] info, err := GetKeyManager().Get(name) - if err != nil { - fmt.Println(err.Error()) - return + if err == nil { + printInfo(info) } - - printInfo(info) + return err }, } diff --git a/cmd/keys/main.go b/cmd/keys/main.go index 0b0d93dec..82b355346 100644 --- a/cmd/keys/main.go +++ b/cmd/keys/main.go @@ -22,7 +22,6 @@ import ( ) func main() { - cli.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) - cmd.RootCmd.Execute() - // exec() + root := cli.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) + root.Execute() } diff --git a/cmd/list.go b/cmd/list.go index 875520159..b0419a1e4 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -14,11 +14,7 @@ package cmd -import ( - "fmt" - - "github.com/spf13/cobra" -) +import "github.com/spf13/cobra" // listCmd represents the list command var listCmd = &cobra.Command{ @@ -26,14 +22,12 @@ var listCmd = &cobra.Command{ Short: "List all keys", Long: `Return a list of all public keys stored by this key manager along with their associated name and address.`, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { infos, err := GetKeyManager().List() - if err != nil { - fmt.Println(err.Error()) - return + if err == nil { + printInfos(infos) } - - printInfos(infos) + return err }, } diff --git a/cmd/new.go b/cmd/new.go index b59874bb0..033410e6a 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -15,7 +15,7 @@ package cmd import ( - "fmt" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -28,7 +28,7 @@ var newCmd = &cobra.Command{ Long: `Add a public/private key pair to the key store. The password muts be entered in the terminal and not passed as a command line argument for security.`, - Run: newPassword, + RunE: newPassword, } func init() { @@ -36,25 +36,21 @@ func init() { newCmd.Flags().StringP("type", "t", "ed25519", "Type of key (ed25519|secp256k1)") } -func newPassword(cmd *cobra.Command, args []string) { +func newPassword(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { - fmt.Println("You must provide a name for the key") - return + return errors.New("You must provide a name for the key") } name := args[0] algo := viper.GetString("type") pass, err := getCheckPassword("Enter a passphrase:", "Repeat the passphrase:") if err != nil { - fmt.Println(err.Error()) - return + return err } info, err := GetKeyManager().Create(name, pass, algo) - if err != nil { - fmt.Println(err.Error()) - return + if err == nil { + printInfo(info) } - - printInfo(info) + return err } diff --git a/cmd/root.go b/cmd/root.go index 401e7ec38..33153d850 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -22,6 +22,7 @@ import ( keys "github.com/tendermint/go-crypto/keys" "github.com/tendermint/go-crypto/keys/cryptostore" "github.com/tendermint/go-crypto/keys/storage/filestorage" + "github.com/tendermint/tmlibs/cli" ) const KeySubdir = "keys" @@ -45,7 +46,7 @@ needs to sign with a private key.`, func GetKeyManager() keys.Manager { if manager == nil { // store the keys directory - rootDir := viper.GetString("root") + rootDir := viper.GetString(cli.HomeFlag) keyDir := filepath.Join(rootDir, KeySubdir) // and construct the key manager manager = cryptostore.New( diff --git a/cmd/update.go b/cmd/update.go index 3835242c5..c046af126 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -17,6 +17,8 @@ package cmd import ( "fmt" + "github.com/pkg/errors" + "github.com/spf13/cobra" ) @@ -25,35 +27,32 @@ var updateCmd = &cobra.Command{ Use: "update ", Short: "Change the password for a private key", Long: `Change the password for a private key.`, - Run: updatePassword, + RunE: updatePassword, } func init() { RootCmd.AddCommand(updateCmd) } -func updatePassword(cmd *cobra.Command, args []string) { +func updatePassword(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { - fmt.Println("You must provide a name for the key") - return + return errors.New("You must provide a name for the key") } name := args[0] oldpass, err := getPassword("Enter the current passphrase:") if err != nil { - fmt.Println(err.Error()) - return + return err } newpass, err := getCheckPassword("Enter the new passphrase:", "Repeat the new passphrase:") if err != nil { - fmt.Println(err.Error()) - return + return err } err = GetKeyManager().Update(name, oldpass, newpass) if err != nil { - fmt.Println(err.Error()) - } else { - fmt.Println("Password successfully updated!") + return err } + fmt.Println("Password successfully updated!") + return nil } diff --git a/cmd/utils.go b/cmd/utils.go index a75262676..f2faa892b 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/viper" keys "github.com/tendermint/go-crypto/keys" data "github.com/tendermint/go-wire/data" + "github.com/tendermint/tmlibs/cli" ) const PassLength = 10 @@ -40,7 +41,7 @@ func getCheckPassword(prompt, prompt2 string) (string, error) { } func printInfo(info keys.Info) { - switch viper.Get(OutputFlag) { + switch viper.Get(cli.OutputFlag) { case "text": addr, err := data.ToText(info.Address) if err != nil { @@ -61,7 +62,7 @@ func printInfo(info keys.Info) { } func printInfos(infos keys.Infos) { - switch viper.Get(OutputFlag) { + switch viper.Get(cli.OutputFlag) { case "text": fmt.Println("All keys:") for _, i := range infos { diff --git a/glide.lock b/glide.lock index 485e75c76..7b3087993 100644 --- a/glide.lock +++ b/glide.lock @@ -1,10 +1,10 @@ hash: 3bcee9fbccf29d21217b24b6a83ec51e1514f37b2ae5d8718cf6c5df80f4fb2c -updated: 2017-04-21T16:09:28.762932633-04:00 +updated: 2017-05-05T19:07:08.418096598+02:00 imports: - name: github.com/bgentry/speakeasy version: 675b82c74c0ed12283ee81ba8a534c8982c07b85 - name: github.com/btcsuite/btcd - version: 583684b21bfbde9b5fc4403916fd7c807feb0289 + version: 4b348c1d33373d672edd83fc576892d0e46686d2 subpackages: - btcec - chaincfg @@ -28,7 +28,7 @@ imports: - name: github.com/go-playground/universal-translator version: b32fa301c9fe55953584134cb6853a13c87ec0a1 - name: github.com/go-stack/stack - version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 + version: 7a2f19628aabfe68f0766b59e74d6315f8347d22 - name: github.com/gorilla/context version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 - name: github.com/gorilla/handlers @@ -36,7 +36,7 @@ imports: - name: github.com/gorilla/mux version: 392c28fe23e1c45ddba891b0320b3b5df220beea - name: github.com/hashicorp/hcl - version: 630949a3c5fa3c613328e1b8256052cbc2327c9b + version: a4b07c25de5ff55ad3b8936cea69a79a3d95a855 subpackages: - hcl/ast - hcl/parser @@ -51,17 +51,17 @@ imports: - name: github.com/magiconair/properties version: 51463bfca2576e06c62a8504b5c0f06d61312647 - name: github.com/mattn/go-colorable - version: d228849504861217f796da67fae4f6e347643f15 + version: ded68f7a9561c023e790de24279db7ebf473ea80 - name: github.com/mattn/go-isatty - version: 30a891c33c7cde7b02a981314b4228ec99380cca + version: fc9e8d8ef48496124e79ae0df75490096eccf6fe - name: github.com/mitchellh/mapstructure - version: 53818660ed4955e899c0bcafa97299a388bd7c8e + version: cc8532a8e9a55ea36402aa21efdf403a60d34096 - name: github.com/pelletier/go-buffruneio version: c37440a7cf42ac63b919c752ca73a85067e05992 - name: github.com/pelletier/go-toml - version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a + version: 97253b98df84f9eef872866d079e74b8265150f1 - name: github.com/pkg/errors - version: bfd5150e4e41705ded2129ec33379de1cb90b513 + version: c605e284fe17294bda444b34710735b29d1a9d90 - name: github.com/spf13/afero version: 9be650865eab0c12963d8753212f4f9c66cdcf12 subpackages: @@ -69,35 +69,34 @@ imports: - name: github.com/spf13/cast version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: fcd0c5a1df88f5d6784cb4feead962c3f3d0b66c + version: 8f0203be891287870100e4af46262cdf4a4261d1 - name: github.com/spf13/jwalterweatherman version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66 - name: github.com/spf13/pflag - version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 + version: c990990ab4981d84da820b7b00c85139ca150b5f - name: github.com/spf13/viper - version: 5d46e70da8c0b6f812e0b170b7a985753b5c63cb + version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/tendermint/ed25519 version: 1f52c6f8b8a5c7908aff4497c186af344b428925 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 334005c236d19c632fb5f073f9de3b0fab6a522b + version: b53add0b622662731985485f3a19be7f684660b8 subpackages: - data - data/base58 - name: github.com/tendermint/log15 - version: ae0f3d6450da9eac7074b439c8e1c3cabf0d5ce6 + version: f91285dece9f4875421b481da3e613d83d44f29b subpackages: - term - name: github.com/tendermint/tmlibs - version: d4ab9679d71c8fc174284696d15930cb799fa24f + version: 706b9fbd671d5d49ecf1b2ea3bb34e51d61ff091 subpackages: - - common - - logger - cli + - common - name: golang.org/x/crypto - version: 7c6cc321c680f03b9ef0764448e780704f486b51 + version: 5a033cc77e57eca05bdb50522851d29e03569cbe subpackages: - bcrypt - blowfish @@ -109,11 +108,11 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/sys - version: d75a52659825e75fff6158388dddc6a5b04f9ba5 + version: 9ccfe848b9db8435a24c424abbc07a921adf1df5 subpackages: - unix - name: golang.org/x/text - version: f4b4367115ec2de254587813edaa901bc1c723a8 + version: 470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4 subpackages: - transform - unicode/norm From d901fba6628e15b83d564753b3bd3cf2c5438686 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 15 May 2017 09:40:00 -0400 Subject: [PATCH 071/273] add changelog and version --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ version.go | 3 +++ 2 files changed, 30 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 version.go diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..72c4bf2cd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,27 @@ +# Changelog + +## 0.2.0 (May 15, 2017) + +BREAKING CHANGES: + +- [hd] The following functions no longer take a `coin string` as argument: `ComputeAddress`, `AddrFromPubKeyBytes`, `ComputeAddressForPrivKey`, `ComputeWIF`, `WIFFromPrivKeyBytes` +- Changes to `PrivKey`, `PubKey`, and `Signature` (denoted `Xxx` below): + - interfaces are renamed `XxxInner`, and are not for use outside the package, though they must be exposed for sake of serialization. + - `Xxx` is now a struct that wraps the corresponding `XxxInner` interface + +FEATURES: + +- `github.com/tendermint/go-keys -> github.com/tendermint/go-crypto/keys` - command and lib for generating and managing encrypted keys +- [hd] New function `WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string` +- Changes to `PrivKey`, `PubKey`, and `Signature` (denoted `Xxx` below): + - Expose a new method `Unwrap() XxxInner` on the `Xxx` struct which returns the corresponding `XxxInner` interface + - Expose a new method `Wrap() Xxx` on the `XxxInner` interface which returns the corresponding `Xxx` struct + +IMPROVEMENTS: + +- Update to use new `tmlibs` repository + +## 0.1.0 (April 14, 2017) + +Initial release + diff --git a/version.go b/version.go new file mode 100644 index 000000000..e2c9c787b --- /dev/null +++ b/version.go @@ -0,0 +1,3 @@ +package crypto + +const Version = "0.2.0" From a42b10e0feb465eb56fbc6bb5b71d57ef646ec57 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 15 May 2017 09:41:07 -0400 Subject: [PATCH 072/273] update glide --- glide.lock | 62 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/glide.lock b/glide.lock index 7b3087993..1f026ceb9 100644 --- a/glide.lock +++ b/glide.lock @@ -1,34 +1,42 @@ hash: 3bcee9fbccf29d21217b24b6a83ec51e1514f37b2ae5d8718cf6c5df80f4fb2c -updated: 2017-05-05T19:07:08.418096598+02:00 +updated: 2017-05-15T09:40:53.073691731-04:00 imports: - name: github.com/bgentry/speakeasy - version: 675b82c74c0ed12283ee81ba8a534c8982c07b85 + version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd - name: github.com/btcsuite/btcd - version: 4b348c1d33373d672edd83fc576892d0e46686d2 + version: b8df516b4b267acf2de46be593a9d948d1d2c420 subpackages: - btcec - chaincfg - chaincfg/chainhash - wire - name: github.com/btcsuite/btcutil - version: a5ecb5d9547afe8d1672073dbdc348203de744a0 + version: 66871daeb12123ece012a9628d2798d01195c4b3 subpackages: - base58 - hdkeychain -- name: github.com/btcsuite/golangcrypto - version: 53f62d9b43e87a6c56975cf862af7edf33a8d0df - subpackages: - - ripemd160 +- name: github.com/btcsuite/fastsha256 + version: 637e656429416087660c84436a2a035d69d54e2e +- name: github.com/clipperhouse/typewriter + version: c1a48da378ebb7db1db9f35981b5cc24bf2e5b85 - name: github.com/fsnotify/fsnotify version: 4da3e2cfbabc9f751898f250b49f2439785783a1 +- name: github.com/go-kit/kit + version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 + subpackages: + - log + - log/level + - log/term +- name: github.com/go-logfmt/logfmt + version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-playground/locales - version: 084b0226cf88d891a2bdeccac01d592af13a8f7b + version: 1e5f1161c6416a5ff48840eb8724a394e48cc534 subpackages: - currency - name: github.com/go-playground/universal-translator - version: b32fa301c9fe55953584134cb6853a13c87ec0a1 + version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack - version: 7a2f19628aabfe68f0766b59e74d6315f8347d22 + version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 - name: github.com/gorilla/context version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 - name: github.com/gorilla/handlers @@ -48,20 +56,18 @@ imports: - json/token - name: github.com/inconshreveable/mousetrap version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 +- name: github.com/kr/logfmt + version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/magiconair/properties version: 51463bfca2576e06c62a8504b5c0f06d61312647 -- name: github.com/mattn/go-colorable - version: ded68f7a9561c023e790de24279db7ebf473ea80 -- name: github.com/mattn/go-isatty - version: fc9e8d8ef48496124e79ae0df75490096eccf6fe - name: github.com/mitchellh/mapstructure version: cc8532a8e9a55ea36402aa21efdf403a60d34096 - name: github.com/pelletier/go-buffruneio version: c37440a7cf42ac63b919c752ca73a85067e05992 - name: github.com/pelletier/go-toml - version: 97253b98df84f9eef872866d079e74b8265150f1 + version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a - name: github.com/pkg/errors - version: c605e284fe17294bda444b34710735b29d1a9d90 + version: ff09b135c25aae272398c51a07235b90a75aa4f0 - name: github.com/spf13/afero version: 9be650865eab0c12963d8753212f4f9c66cdcf12 subpackages: @@ -69,11 +75,11 @@ imports: - name: github.com/spf13/cast version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: 8f0203be891287870100e4af46262cdf4a4261d1 + version: db6b9a8b3f3f400c8ecb4a4d7d02245b8facad66 - name: github.com/spf13/jwalterweatherman version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66 - name: github.com/spf13/pflag - version: c990990ab4981d84da820b7b00c85139ca150b5f + version: 80fe0fb4eba54167e2ccae1c6c950e72abf61b73 - name: github.com/spf13/viper version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/tendermint/ed25519 @@ -82,21 +88,18 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: b53add0b622662731985485f3a19be7f684660b8 + version: 59ba5af720a8cbaf5594595e1d8aae23bfd18e31 subpackages: - data - data/base58 -- name: github.com/tendermint/log15 - version: f91285dece9f4875421b481da3e613d83d44f29b - subpackages: - - term - name: github.com/tendermint/tmlibs - version: 706b9fbd671d5d49ecf1b2ea3bb34e51d61ff091 + version: 8f5a175ff4c869fedde710615a11f5745ff69bf3 subpackages: - cli - common + - log - name: golang.org/x/crypto - version: 5a033cc77e57eca05bdb50522851d29e03569cbe + version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e subpackages: - bcrypt - blowfish @@ -116,8 +119,13 @@ imports: subpackages: - transform - unicode/norm +- name: golang.org/x/tools + version: 144c6642b5d832d6c44a53dad6ee61665dd432ce + subpackages: + - go/ast/astutil + - imports - name: gopkg.in/go-playground/validator.v9 - version: 4bd19358521c53f09639f21e2a9d6883d6890f24 + version: 6d8c18553ea1ac493d049edd6f102f52e618f085 - name: gopkg.in/yaml.v2 version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b testImports: From c38a6f55b375c3f213e8acbd66f399d8a7b8ea70 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 15 May 2017 02:22:58 +0200 Subject: [PATCH 073/273] Prepare for codegen --- _gen.go | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 _gen.go diff --git a/_gen.go b/_gen.go new file mode 100644 index 000000000..36e39887f --- /dev/null +++ b/_gen.go @@ -0,0 +1,7 @@ +package main + +import ( + _ "github.com/tendermint/go-wire/data" + _ "github.com/clipperhouse/stringer" + _ "github.com/clipperhouse/set" +) From f16f71199218d8c0e7e9ef0284c361a51b258afd Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 15 May 2017 02:31:05 +0200 Subject: [PATCH 074/273] First code from codegen... wrong names --- pub_key.go | 47 +++----------------------------- pubkeyinner_holder.go | 62 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 43 deletions(-) create mode 100644 pubkeyinner_holder.go diff --git a/pub_key.go b/pub_key.go index 99839f288..a4da59d2f 100644 --- a/pub_key.go +++ b/pub_key.go @@ -7,9 +7,9 @@ import ( secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" - . "github.com/tendermint/tmlibs/common" - data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-wire" + data "github.com/tendermint/go-wire/data" + . "github.com/tendermint/tmlibs/common" "golang.org/x/crypto/ripemd160" ) @@ -20,12 +20,10 @@ func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { //---------------------------------------- -type PubKey struct { - PubKeyInner `json:"unwrap"` -} - // DO NOT USE THIS INTERFACE. // You probably want to use PubKey + +// +gen holder:"PubKey,Impl[PubKeyEd25519,PubKeySecp256k1]" type PubKeyInner interface { AssertIsPubKeyInner() Address() []byte @@ -36,35 +34,6 @@ type PubKeyInner interface { Wrap() PubKey } -func (pk PubKey) MarshalJSON() ([]byte, error) { - return pubKeyMapper.ToJSON(pk.PubKeyInner) -} - -func (pk *PubKey) UnmarshalJSON(data []byte) (err error) { - parsed, err := pubKeyMapper.FromJSON(data) - if err == nil && parsed != nil { - pk.PubKeyInner = parsed.(PubKeyInner) - } - return -} - -// Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (pk PubKey) Unwrap() PubKeyInner { - pkI := pk.PubKeyInner - for wrap, ok := pkI.(PubKey); ok; wrap, ok = pkI.(PubKey) { - pkI = wrap.PubKeyInner - } - return pkI -} - -func (p PubKey) Empty() bool { - return p.PubKeyInner == nil -} - -var pubKeyMapper = data.NewMapper(PubKey{}). - RegisterImplementation(PubKeyEd25519{}, NameEd25519, TypeEd25519). - RegisterImplementation(PubKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) - //------------------------------------- var _ PubKeyInner = PubKeyEd25519{} @@ -142,10 +111,6 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool { } } -func (pubKey PubKeyEd25519) Wrap() PubKey { - return PubKey{pubKey} -} - //------------------------------------- var _ PubKeyInner = PubKeySecp256k1{} @@ -218,7 +183,3 @@ func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { return false } } - -func (pubKey PubKeySecp256k1) Wrap() PubKey { - return PubKey{pubKey} -} diff --git a/pubkeyinner_holder.go b/pubkeyinner_holder.go new file mode 100644 index 000000000..16bfcf8a8 --- /dev/null +++ b/pubkeyinner_holder.go @@ -0,0 +1,62 @@ +// Generated by: main +// TypeWriter: holder +// Directive: +gen on PubKeyInner + +package crypto + +import ( + "github.com/tendermint/go-wire/data" +) + +// Auto-generated adapters for happily unmarshaling interfaces +// Apache License 2.0 +// Copyright (c) 2017 Ethan Frey (ethan.frey@tendermint.com) + +type PubKey struct { + PubKeyInner +} + +var PubKeyMapper = data.NewMapper(PubKey{}) + +func (h PubKey) MarshalJSON() ([]byte, error) { + return PubKeyMapper.ToJSON(h.PubKeyInner) +} + +func (h *PubKey) UnmarshalJSON(data []byte) (err error) { + parsed, err := PubKeyMapper.FromJSON(data) + if err == nil && parsed != nil { + h.PubKeyInner = parsed.(PubKeyInner) + } + return err +} + +// Unwrap recovers the concrete interface safely (regardless of levels of embeds) +func (h PubKey) Unwrap() PubKeyInner { + hi := h.PubKeyInner + for wrap, ok := hi.(PubKey); ok; wrap, ok = hi.(PubKey) { + hi = wrap.PubKeyInner + } + return hi +} + +func (h PubKey) Empty() bool { + return h.PubKeyInner == nil +} + +/*** below are bindings for each implementation ***/ + +func init() { + PubKeyMapper.RegisterImplementation(PubKeyEd25519{}, "pubkeyed25519", 0x1) +} + +func (hi PubKeyEd25519) Wrap() PubKey { + return PubKey{hi} +} + +func init() { + PubKeyMapper.RegisterImplementation(PubKeySecp256k1{}, "pubkeysecp256k1", 0x2) +} + +func (hi PubKeySecp256k1) Wrap() PubKey { + return PubKey{hi} +} From ee200d998fb42e23462569745c53c800fbdc6891 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 15 May 2017 02:46:28 +0200 Subject: [PATCH 075/273] Fix unwrap for proper json format --- encode_test.go | 4 ++-- pub_key.go | 3 +-- pubkeyinner_holder.go | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/encode_test.go b/encode_test.go index 6c5d03a1d..1b70d88ec 100644 --- a/encode_test.go +++ b/encode_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - data "github.com/tendermint/go-wire/data" wire "github.com/tendermint/go-wire" + data "github.com/tendermint/go-wire/data" ) type byter interface { @@ -58,7 +58,7 @@ func checkWireJSON(t *testing.T, in interface{}, reader interface{}, typ byte) { var err error js := wire.JSONBytes(in) btyp := fmt.Sprintf("[%d,", typ) - assert.True(t, strings.HasPrefix(string(js), btyp), string(js)) + assert.True(t, strings.HasPrefix(string(js), btyp), string(js), btyp) wire.ReadJSON(reader, js, &err) require.Nil(t, err, "%+v", err) diff --git a/pub_key.go b/pub_key.go index a4da59d2f..7483ff93a 100644 --- a/pub_key.go +++ b/pub_key.go @@ -22,8 +22,7 @@ func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { // DO NOT USE THIS INTERFACE. // You probably want to use PubKey - -// +gen holder:"PubKey,Impl[PubKeyEd25519,PubKeySecp256k1]" +// +gen holder:"PubKey,Impl[PubKeyEd25519,PubKeySecp256k1],ed25519,secp256k1" type PubKeyInner interface { AssertIsPubKeyInner() Address() []byte diff --git a/pubkeyinner_holder.go b/pubkeyinner_holder.go index 16bfcf8a8..ee0ca9f00 100644 --- a/pubkeyinner_holder.go +++ b/pubkeyinner_holder.go @@ -13,7 +13,7 @@ import ( // Copyright (c) 2017 Ethan Frey (ethan.frey@tendermint.com) type PubKey struct { - PubKeyInner + PubKeyInner "json:\"unwrap\"" } var PubKeyMapper = data.NewMapper(PubKey{}) @@ -46,7 +46,7 @@ func (h PubKey) Empty() bool { /*** below are bindings for each implementation ***/ func init() { - PubKeyMapper.RegisterImplementation(PubKeyEd25519{}, "pubkeyed25519", 0x1) + PubKeyMapper.RegisterImplementation(PubKeyEd25519{}, "ed25519", 0x1) } func (hi PubKeyEd25519) Wrap() PubKey { @@ -54,7 +54,7 @@ func (hi PubKeyEd25519) Wrap() PubKey { } func init() { - PubKeyMapper.RegisterImplementation(PubKeySecp256k1{}, "pubkeysecp256k1", 0x2) + PubKeyMapper.RegisterImplementation(PubKeySecp256k1{}, "secp256k1", 0x2) } func (hi PubKeySecp256k1) Wrap() PubKey { From 746a2e286df37747cc00d60bd326f1c21e8aef02 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 15 May 2017 02:51:52 +0200 Subject: [PATCH 076/273] Codegen wrappers for privkey and signature as well --- priv_key.go | 46 ++--------------------------- privkeyinner_holder.go | 62 ++++++++++++++++++++++++++++++++++++++++ signature.go | 47 +++--------------------------- signatureinner_holder.go | 62 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 86 deletions(-) create mode 100644 privkeyinner_holder.go create mode 100644 signatureinner_holder.go diff --git a/priv_key.go b/priv_key.go index 85f8a8ec4..056e50b55 100644 --- a/priv_key.go +++ b/priv_key.go @@ -6,9 +6,9 @@ import ( secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" - . "github.com/tendermint/tmlibs/common" - data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-wire" + data "github.com/tendermint/go-wire/data" + . "github.com/tendermint/tmlibs/common" ) func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { @@ -18,12 +18,9 @@ func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { //---------------------------------------- -type PrivKey struct { - PrivKeyInner `json:"unwrap"` -} - // DO NOT USE THIS INTERFACE. // You probably want to use PubKey +// +gen holder:"PrivKey,Impl[PrivKeyEd25519,PrivKeySecp256k1],ed25519,secp256k1" type PrivKeyInner interface { AssertIsPrivKeyInner() Bytes() []byte @@ -33,35 +30,6 @@ type PrivKeyInner interface { Wrap() PrivKey } -func (p PrivKey) MarshalJSON() ([]byte, error) { - return privKeyMapper.ToJSON(p.PrivKeyInner) -} - -func (p *PrivKey) UnmarshalJSON(data []byte) (err error) { - parsed, err := privKeyMapper.FromJSON(data) - if err == nil && parsed != nil { - p.PrivKeyInner = parsed.(PrivKeyInner) - } - return -} - -// Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (p PrivKey) Unwrap() PrivKeyInner { - pk := p.PrivKeyInner - for wrap, ok := pk.(PrivKey); ok; wrap, ok = pk.(PrivKey) { - pk = wrap.PrivKeyInner - } - return pk -} - -func (p PrivKey) Empty() bool { - return p.PrivKeyInner == nil -} - -var privKeyMapper = data.NewMapper(PrivKey{}). - RegisterImplementation(PrivKeyEd25519{}, NameEd25519, TypeEd25519). - RegisterImplementation(PrivKeySecp256k1{}, NameSecp256k1, TypeSecp256k1) - //------------------------------------- var _ PrivKeyInner = PrivKeyEd25519{} @@ -128,10 +96,6 @@ func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { return PrivKeyEd25519(newKey) } -func (privKey PrivKeyEd25519) Wrap() PrivKey { - return PrivKey{privKey} -} - func GenPrivKeyEd25519() PrivKeyEd25519 { privKeyBytes := new([64]byte) copy(privKeyBytes[:32], CRandBytes(32)) @@ -201,10 +165,6 @@ func (privKey PrivKeySecp256k1) String() string { return Fmt("PrivKeySecp256k1{*****}") } -func (privKey PrivKeySecp256k1) Wrap() PrivKey { - return PrivKey{privKey} -} - /* // Deterministically generates new priv-key bytes from key. func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 { diff --git a/privkeyinner_holder.go b/privkeyinner_holder.go new file mode 100644 index 000000000..2621ca560 --- /dev/null +++ b/privkeyinner_holder.go @@ -0,0 +1,62 @@ +// Generated by: main +// TypeWriter: holder +// Directive: +gen on PrivKeyInner + +package crypto + +import ( + "github.com/tendermint/go-wire/data" +) + +// Auto-generated adapters for happily unmarshaling interfaces +// Apache License 2.0 +// Copyright (c) 2017 Ethan Frey (ethan.frey@tendermint.com) + +type PrivKey struct { + PrivKeyInner "json:\"unwrap\"" +} + +var PrivKeyMapper = data.NewMapper(PrivKey{}) + +func (h PrivKey) MarshalJSON() ([]byte, error) { + return PrivKeyMapper.ToJSON(h.PrivKeyInner) +} + +func (h *PrivKey) UnmarshalJSON(data []byte) (err error) { + parsed, err := PrivKeyMapper.FromJSON(data) + if err == nil && parsed != nil { + h.PrivKeyInner = parsed.(PrivKeyInner) + } + return err +} + +// Unwrap recovers the concrete interface safely (regardless of levels of embeds) +func (h PrivKey) Unwrap() PrivKeyInner { + hi := h.PrivKeyInner + for wrap, ok := hi.(PrivKey); ok; wrap, ok = hi.(PrivKey) { + hi = wrap.PrivKeyInner + } + return hi +} + +func (h PrivKey) Empty() bool { + return h.PrivKeyInner == nil +} + +/*** below are bindings for each implementation ***/ + +func init() { + PrivKeyMapper.RegisterImplementation(PrivKeyEd25519{}, "ed25519", 0x1) +} + +func (hi PrivKeyEd25519) Wrap() PrivKey { + return PrivKey{hi} +} + +func init() { + PrivKeyMapper.RegisterImplementation(PrivKeySecp256k1{}, "secp256k1", 0x2) +} + +func (hi PrivKeySecp256k1) Wrap() PrivKey { + return PrivKey{hi} +} diff --git a/signature.go b/signature.go index 36451ed48..12b584d71 100644 --- a/signature.go +++ b/signature.go @@ -4,9 +4,9 @@ import ( "bytes" "fmt" - . "github.com/tendermint/tmlibs/common" - data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-wire" + data "github.com/tendermint/go-wire/data" + . "github.com/tendermint/tmlibs/common" ) func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { @@ -16,12 +16,9 @@ func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { //---------------------------------------- -type Signature struct { - SignatureInner `json:"unwrap"` -} - // DO NOT USE THIS INTERFACE. // You probably want to use Signature. +// +gen holder:"Signature,Impl[SignatureEd25519,SignatureSecp256k1],ed25519,secp256k1" type SignatureInner interface { AssertIsSignatureInner() Bytes() []byte @@ -31,35 +28,6 @@ type SignatureInner interface { Wrap() Signature } -func (sig Signature) MarshalJSON() ([]byte, error) { - return sigMapper.ToJSON(sig.SignatureInner) -} - -func (sig *Signature) UnmarshalJSON(data []byte) (err error) { - parsed, err := sigMapper.FromJSON(data) - if err == nil && parsed != nil { - sig.SignatureInner = parsed.(SignatureInner) - } - return -} - -// Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (sig Signature) Unwrap() SignatureInner { - pk := sig.SignatureInner - for wrap, ok := pk.(Signature); ok; wrap, ok = pk.(Signature) { - pk = wrap.SignatureInner - } - return pk -} - -func (sig Signature) Empty() bool { - return sig.SignatureInner == nil -} - -var sigMapper = data.NewMapper(Signature{}). - RegisterImplementation(SignatureEd25519{}, NameEd25519, TypeEd25519). - RegisterImplementation(SignatureSecp256k1{}, NameSecp256k1, TypeSecp256k1) - //------------------------------------- var _ SignatureInner = SignatureEd25519{} @@ -96,10 +64,6 @@ func (sig *SignatureEd25519) UnmarshalJSON(enc []byte) error { return err } -func (sig SignatureEd25519) Wrap() Signature { - return Signature{sig} -} - //------------------------------------- var _ SignatureInner = SignatureSecp256k1{} @@ -124,6 +88,7 @@ func (sig SignatureSecp256k1) Equals(other Signature) bool { return false } } + func (sig SignatureSecp256k1) MarshalJSON() ([]byte, error) { return data.Encoder.Marshal(sig) } @@ -131,7 +96,3 @@ func (sig SignatureSecp256k1) MarshalJSON() ([]byte, error) { func (sig *SignatureSecp256k1) UnmarshalJSON(enc []byte) error { return data.Encoder.Unmarshal((*[]byte)(sig), enc) } - -func (sig SignatureSecp256k1) Wrap() Signature { - return Signature{sig} -} diff --git a/signatureinner_holder.go b/signatureinner_holder.go new file mode 100644 index 000000000..cbe1fe093 --- /dev/null +++ b/signatureinner_holder.go @@ -0,0 +1,62 @@ +// Generated by: main +// TypeWriter: holder +// Directive: +gen on SignatureInner + +package crypto + +import ( + "github.com/tendermint/go-wire/data" +) + +// Auto-generated adapters for happily unmarshaling interfaces +// Apache License 2.0 +// Copyright (c) 2017 Ethan Frey (ethan.frey@tendermint.com) + +type Signature struct { + SignatureInner "json:\"unwrap\"" +} + +var SignatureMapper = data.NewMapper(Signature{}) + +func (h Signature) MarshalJSON() ([]byte, error) { + return SignatureMapper.ToJSON(h.SignatureInner) +} + +func (h *Signature) UnmarshalJSON(data []byte) (err error) { + parsed, err := SignatureMapper.FromJSON(data) + if err == nil && parsed != nil { + h.SignatureInner = parsed.(SignatureInner) + } + return err +} + +// Unwrap recovers the concrete interface safely (regardless of levels of embeds) +func (h Signature) Unwrap() SignatureInner { + hi := h.SignatureInner + for wrap, ok := hi.(Signature); ok; wrap, ok = hi.(Signature) { + hi = wrap.SignatureInner + } + return hi +} + +func (h Signature) Empty() bool { + return h.SignatureInner == nil +} + +/*** below are bindings for each implementation ***/ + +func init() { + SignatureMapper.RegisterImplementation(SignatureEd25519{}, "ed25519", 0x1) +} + +func (hi SignatureEd25519) Wrap() Signature { + return Signature{hi} +} + +func init() { + SignatureMapper.RegisterImplementation(SignatureSecp256k1{}, "secp256k1", 0x2) +} + +func (hi SignatureSecp256k1) Wrap() Signature { + return Signature{hi} +} From 79c580492e6b8658605c8ceea5f6bc52739d0339 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 15 May 2017 15:56:08 +0200 Subject: [PATCH 077/273] add make codegen for gen --- Makefile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 59440fe66..d453f7ad1 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONEY: all docs test install get_vendor_deps ensure_tools +.PHONEY: all docs test install get_vendor_deps ensure_tools codegen GOTOOLS = \ github.com/Masterminds/glide @@ -24,4 +24,12 @@ get_vendor_deps: ensure_tools ensure_tools: go get $(GOTOOLS) +prepgen: install + cd ../go-wire && make tools + go install ./vendor/github.com/btcsuite/btcutil/base58 + go install ./vendor/github.com/stretchr/testify/assert + go install ./vendor/github.com/stretchr/testify/require + go install ./vendor/golang.org/x/crypto/bcrypt +codegen: prepgen + gen From bee63ce4ff15b8d48a0ee6fa9d902775f86fa1a1 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 15 May 2017 19:13:49 +0200 Subject: [PATCH 078/273] Cleaned up build process, moved codegen to separate package in go-wire --- Makefile | 7 ++++--- _gen.go | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index d453f7ad1..ca9703399 100644 --- a/Makefile +++ b/Makefile @@ -25,11 +25,12 @@ ensure_tools: go get $(GOTOOLS) prepgen: install - cd ../go-wire && make tools go install ./vendor/github.com/btcsuite/btcutil/base58 go install ./vendor/github.com/stretchr/testify/assert go install ./vendor/github.com/stretchr/testify/require go install ./vendor/golang.org/x/crypto/bcrypt -codegen: prepgen - gen +codegen: + @echo "--> regenerating all interface wrappers" + @gen + @echo "Done!" diff --git a/_gen.go b/_gen.go index 36e39887f..a98feaf4e 100644 --- a/_gen.go +++ b/_gen.go @@ -1,7 +1,6 @@ package main import ( - _ "github.com/tendermint/go-wire/data" + _ "github.com/tendermint/go-wire/gen" _ "github.com/clipperhouse/stringer" - _ "github.com/clipperhouse/set" ) From db5cb8d92c3e993786f406e9fcfebbbd60bd2d87 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 16 May 2017 16:59:40 +0200 Subject: [PATCH 079/273] Change codegen name holder->wrapper --- glide.lock | 2 +- priv_key.go | 2 +- privkeyinner_holder.go => privkeyinner_wrapper.go | 2 +- pub_key.go | 2 +- pubkeyinner_holder.go => pubkeyinner_wrapper.go | 2 +- signature.go | 2 +- signatureinner_holder.go => signatureinner_wrapper.go | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) rename privkeyinner_holder.go => privkeyinner_wrapper.go (98%) rename pubkeyinner_holder.go => pubkeyinner_wrapper.go (98%) rename signatureinner_holder.go => signatureinner_wrapper.go (98%) diff --git a/glide.lock b/glide.lock index 1f026ceb9..82dd5111e 100644 --- a/glide.lock +++ b/glide.lock @@ -88,7 +88,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 59ba5af720a8cbaf5594595e1d8aae23bfd18e31 + version: 97beaedf0f4dbc035309157c92be3b30cc6e5d74 subpackages: - data - data/base58 diff --git a/priv_key.go b/priv_key.go index 056e50b55..0c6bd2ae7 100644 --- a/priv_key.go +++ b/priv_key.go @@ -20,7 +20,7 @@ func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { // DO NOT USE THIS INTERFACE. // You probably want to use PubKey -// +gen holder:"PrivKey,Impl[PrivKeyEd25519,PrivKeySecp256k1],ed25519,secp256k1" +// +gen wrapper:"PrivKey,Impl[PrivKeyEd25519,PrivKeySecp256k1],ed25519,secp256k1" type PrivKeyInner interface { AssertIsPrivKeyInner() Bytes() []byte diff --git a/privkeyinner_holder.go b/privkeyinner_wrapper.go similarity index 98% rename from privkeyinner_holder.go rename to privkeyinner_wrapper.go index 2621ca560..05ce69672 100644 --- a/privkeyinner_holder.go +++ b/privkeyinner_wrapper.go @@ -1,5 +1,5 @@ // Generated by: main -// TypeWriter: holder +// TypeWriter: wrapper // Directive: +gen on PrivKeyInner package crypto diff --git a/pub_key.go b/pub_key.go index 7483ff93a..4d5c31b21 100644 --- a/pub_key.go +++ b/pub_key.go @@ -22,7 +22,7 @@ func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { // DO NOT USE THIS INTERFACE. // You probably want to use PubKey -// +gen holder:"PubKey,Impl[PubKeyEd25519,PubKeySecp256k1],ed25519,secp256k1" +// +gen wrapper:"PubKey,Impl[PubKeyEd25519,PubKeySecp256k1],ed25519,secp256k1" type PubKeyInner interface { AssertIsPubKeyInner() Address() []byte diff --git a/pubkeyinner_holder.go b/pubkeyinner_wrapper.go similarity index 98% rename from pubkeyinner_holder.go rename to pubkeyinner_wrapper.go index ee0ca9f00..7b36c324d 100644 --- a/pubkeyinner_holder.go +++ b/pubkeyinner_wrapper.go @@ -1,5 +1,5 @@ // Generated by: main -// TypeWriter: holder +// TypeWriter: wrapper // Directive: +gen on PubKeyInner package crypto diff --git a/signature.go b/signature.go index 12b584d71..1c5b8d69e 100644 --- a/signature.go +++ b/signature.go @@ -18,7 +18,7 @@ func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { // DO NOT USE THIS INTERFACE. // You probably want to use Signature. -// +gen holder:"Signature,Impl[SignatureEd25519,SignatureSecp256k1],ed25519,secp256k1" +// +gen wrapper:"Signature,Impl[SignatureEd25519,SignatureSecp256k1],ed25519,secp256k1" type SignatureInner interface { AssertIsSignatureInner() Bytes() []byte diff --git a/signatureinner_holder.go b/signatureinner_wrapper.go similarity index 98% rename from signatureinner_holder.go rename to signatureinner_wrapper.go index cbe1fe093..1fdd790d6 100644 --- a/signatureinner_holder.go +++ b/signatureinner_wrapper.go @@ -1,5 +1,5 @@ // Generated by: main -// TypeWriter: holder +// TypeWriter: wrapper // Directive: +gen on SignatureInner package crypto From c61497b56e43096e47872ec12782d5bf9e20b4f0 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 18 May 2017 11:35:32 +0200 Subject: [PATCH 080/273] CHANGELOG: update release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72c4bf2cd..510785477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.2.0 (May 15, 2017) +## 0.2.0 (May 18, 2017) BREAKING CHANGES: From 0edd1297a9a90b2569c117bbc38a901d468a9efd Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 19 Jun 2017 17:07:12 +0200 Subject: [PATCH 081/273] Got basic key test working --- .gitignore | 1 + Makefile | 17 ++++++++++++++--- tests/keys.sh | 30 ++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100755 tests/keys.sh diff --git a/.gitignore b/.gitignore index f37225baa..d19e6457f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.swp *.swo vendor +shunit2 diff --git a/Makefile b/Makefile index ca9703399..e40d0e6ff 100644 --- a/Makefile +++ b/Makefile @@ -8,13 +8,24 @@ docs: @go get github.com/davecheney/godoc2md godoc2md $(REPO) > README.md -all: install test +all: get_vendor_deps install test install: go install ./cmd/keys -test: +test: test_unit test_cli + +test_unit: go test `glide novendor` + #go run tests/tendermint/*.go + +test_cli: tests/shunit2 + # sudo apt-get install jq + @./tests/keys.sh + +tests/shunit2: + wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ + -q -O tests/shunit2 get_vendor_deps: ensure_tools @rm -rf vendor/ @@ -30,7 +41,7 @@ prepgen: install go install ./vendor/github.com/stretchr/testify/require go install ./vendor/golang.org/x/crypto/bcrypt -codegen: +codegen: @echo "--> regenerating all interface wrappers" @gen @echo "Done!" diff --git a/tests/keys.sh b/tests/keys.sh new file mode 100755 index 000000000..b4bdcdd40 --- /dev/null +++ b/tests/keys.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +EXE=keys + +oneTimeSetUp() { + PASS=qwertyuiop + export TM_HOME=$HOME/.keys_test + rm -rf $TM_HOME + assertTrue $? +} + +newKey(){ + assertNotNull "keyname required" "$1" + KEYPASS=${2:-qwertyuiop} + (echo $KEYPASS; echo $KEYPASS) | ${EXE} new $1 >/dev/null 2>&1 + assertTrue "created $1" $? +} + +testMakeKeys() { + USER=demouser + assertFalse "already user $USER" "${EXE} list | grep $USER" + assertEquals "1" `${EXE} list | wc -l` + newKey $USER + assertTrue "no user $USER" "${EXE} list | grep $USER" + assertEquals "2" `${EXE} list | wc -l` +} + +# load and run these tests with shunit2! +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory +. $DIR/shunit2 From 0c32d2722fc32523829029953bf9ade2933f4a7c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 19 Jun 2017 17:49:16 +0200 Subject: [PATCH 082/273] #17 - better support passwords in tests, more cli tests --- cmd/utils.go | 40 +++++++++++++++++++++++++++++++++++++--- glide.lock | 15 +++++---------- tests/keys.sh | 46 ++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 82 insertions(+), 19 deletions(-) diff --git a/cmd/utils.go b/cmd/utils.go index f2faa892b..d082bbbc9 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -1,20 +1,49 @@ package cmd import ( + "bufio" "fmt" + "os" + "strings" "github.com/bgentry/speakeasy" + "github.com/mattn/go-isatty" "github.com/pkg/errors" "github.com/spf13/viper" - keys "github.com/tendermint/go-crypto/keys" + data "github.com/tendermint/go-wire/data" "github.com/tendermint/tmlibs/cli" + + keys "github.com/tendermint/go-crypto/keys" ) const PassLength = 10 -func getPassword(prompt string) (string, error) { - pass, err := speakeasy.Ask(prompt) +// if we read from non-tty, we just need to init the buffer reader once, +// in case we try to read multiple passwords (eg. update) +var buf *bufio.Reader + +func inputIsTty() bool { + return isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd()) +} + +func stdinPassword() (string, error) { + if buf == nil { + buf = bufio.NewReader(os.Stdin) + } + pass, err := buf.ReadString('\n') + if err != nil { + return "", err + } + return strings.TrimSpace(pass), nil +} + +func getPassword(prompt string) (pass string, err error) { + if inputIsTty() { + pass, err = speakeasy.Ask(prompt) + } else { + pass, err = stdinPassword() + } if err != nil { return "", err } @@ -25,6 +54,11 @@ func getPassword(prompt string) (string, error) { } func getCheckPassword(prompt, prompt2 string) (string, error) { + // simple read on no-tty + if !inputIsTty() { + return getPassword(prompt) + } + // TODO: own function??? pass, err := getPassword(prompt) if err != nil { diff --git a/glide.lock b/glide.lock index 82dd5111e..71292ce11 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 3bcee9fbccf29d21217b24b6a83ec51e1514f37b2ae5d8718cf6c5df80f4fb2c -updated: 2017-05-15T09:40:53.073691731-04:00 +updated: 2017-06-19T17:16:58.037568333+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -17,8 +17,6 @@ imports: - hdkeychain - name: github.com/btcsuite/fastsha256 version: 637e656429416087660c84436a2a035d69d54e2e -- name: github.com/clipperhouse/typewriter - version: c1a48da378ebb7db1db9f35981b5cc24bf2e5b85 - name: github.com/fsnotify/fsnotify version: 4da3e2cfbabc9f751898f250b49f2439785783a1 - name: github.com/go-kit/kit @@ -60,6 +58,8 @@ imports: version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/magiconair/properties version: 51463bfca2576e06c62a8504b5c0f06d61312647 +- name: github.com/mattn/go-isatty + version: 9622e0cc9d8f9be434ca605520ff9a16808fee47 - name: github.com/mitchellh/mapstructure version: cc8532a8e9a55ea36402aa21efdf403a60d34096 - name: github.com/pelletier/go-buffruneio @@ -88,12 +88,12 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 97beaedf0f4dbc035309157c92be3b30cc6e5d74 + version: 5f88da3dbc1a72844e6dfaf274ce87f851d488eb subpackages: - data - data/base58 - name: github.com/tendermint/tmlibs - version: 8f5a175ff4c869fedde710615a11f5745ff69bf3 + version: bd9d0d1637dadf1330e167189d5e5031aadcda6f subpackages: - cli - common @@ -119,11 +119,6 @@ imports: subpackages: - transform - unicode/norm -- name: golang.org/x/tools - version: 144c6642b5d832d6c44a53dad6ee61665dd432ce - subpackages: - - go/ast/astutil - - imports - name: gopkg.in/go-playground/validator.v9 version: 6d8c18553ea1ac493d049edd6f102f52e618f085 - name: gopkg.in/yaml.v2 diff --git a/tests/keys.sh b/tests/keys.sh index b4bdcdd40..82c8083ec 100755 --- a/tests/keys.sh +++ b/tests/keys.sh @@ -12,17 +12,51 @@ oneTimeSetUp() { newKey(){ assertNotNull "keyname required" "$1" KEYPASS=${2:-qwertyuiop} - (echo $KEYPASS; echo $KEYPASS) | ${EXE} new $1 >/dev/null 2>&1 + KEY=$(echo $KEYPASS | ${EXE} new $1) assertTrue "created $1" $? + return $? } -testMakeKeys() { +# updateKey +updateKey() { + (echo $2; echo $3) | keys update $1 > /dev/null + return $? +} + +test00MakeKeys() { USER=demouser - assertFalse "already user $USER" "${EXE} list | grep $USER" - assertEquals "1" `${EXE} list | wc -l` + assertFalse "already user $USER" "${EXE} get $USER" newKey $USER - assertTrue "no user $USER" "${EXE} list | grep $USER" - assertEquals "2" `${EXE} list | wc -l` + assertTrue "no user $USER" "${EXE} get $USER" + # make sure bad password not accepted + assertFalse "accepts short password" "echo 123 | keys new badpass" +} + +test01ListKeys() { + # one line plus the number of keys + assertEquals "2" $(keys list | wc -l) + newKey foobar + assertEquals "3" $(keys list | wc -l) + # we got the proper name here... + assertEquals "foobar" $(keys list -o json | jq .[1].name | tr -d \" ) + # we get all names in normal output + EXPECTEDNAMES=$(echo demouser; echo foobar) + TEXTNAMES=$(keys list | tail -n +2 | cut -f1) + assertEquals "$EXPECTEDNAMES" "$TEXTNAMES" + # let's make sure the addresses match! + assertEquals "text and json addresses don't match" $(keys list | tail -1 | cut -f3) $(keys list -o json | jq .[1].address | tr -d \") +} + +test02updateKeys() { + USER=changer + PASS1=awsedrftgyhu + PASS2=S4H.9j.D9S7hso + PASS3=h8ybO7GY6d2 + + newKey $USER $PASS1 + assertFalse "accepts invalid pass" "updateKey $USER $PASS2 $PASS2" + assertTrue "doesn't update" "updateKey $USER $PASS1 $PASS2" + assertTrue "takes new key after update" "updateKey $USER $PASS2 $PASS3" } # load and run these tests with shunit2! From ea4f45828d2ebf78c485d36de129ed6e8a62b643 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 19 Jun 2017 17:52:45 +0200 Subject: [PATCH 083/273] Update circle ci for new cli tests --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 23ac4bd9f..a37187dd9 100644 --- a/circle.yml +++ b/circle.yml @@ -18,4 +18,4 @@ dependencies: test: override: - "go version" - - "cd $PROJECT_PATH && make get_vendor_deps && make test" + - "cd $PROJECT_PATH && make all" From 2278f566bf90ea989042ce39a892d8226a935471 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 14:57:49 +0200 Subject: [PATCH 084/273] Add beginning of wordcodec for bytes --- keys/wordcodec.go | 152 +++ keys/wordcodec_test.go | 85 ++ keys/wordlist/english.txt | 2048 +++++++++++++++++++++++++++++++++++++ 3 files changed, 2285 insertions(+) create mode 100644 keys/wordcodec.go create mode 100644 keys/wordcodec_test.go create mode 100644 keys/wordlist/english.txt diff --git a/keys/wordcodec.go b/keys/wordcodec.go new file mode 100644 index 000000000..3a750940b --- /dev/null +++ b/keys/wordcodec.go @@ -0,0 +1,152 @@ +package keys + +import ( + "fmt" + "io/ioutil" + "math/big" + "os" + "strings" + + "github.com/pkg/errors" +) + +const BankSize = 2048 + +// TODO: add error-checking codecs for invalid phrases + +type Codec interface { + BytesToWords([]byte) ([]string, error) + WordsToBytes([]string) ([]byte, error) +} + +type WordCodec struct { + words []string + bytes map[string]int +} + +var _ Codec = WordCodec{} + +func NewCodec(words []string) (codec WordCodec, err error) { + if len(words) != BankSize { + return codec, errors.Errorf("Bank must have %d words, found %d", BankSize, len(words)) + } + + b := map[string]int{} + for i, w := range words { + if _, ok := b[w]; ok { + return codec, errors.Errorf("Duplicate word in list: %s", w) + } + b[w] = i + } + + return WordCodec{words, b}, nil +} + +func LoadCodec(bank string) (codec WordCodec, err error) { + words, err := loadBank(bank) + if err != nil { + return codec, err + } + return NewCodec(words) +} + +// loadBank opens a wordlist file and returns all words inside +func loadBank(bank string) ([]string, error) { + filename := "wordlist/" + bank + ".txt" + words, err := getData(filename) + if err != nil { + return nil, err + } + wordsAll := strings.Split(strings.TrimSpace(words), "\n") + return wordsAll, nil +} + +// TODO: read from go-bind assets +func getData(filename string) (string, error) { + f, err := os.Open(filename) + if err != nil { + return "", errors.WithStack(err) + } + defer f.Close() + + data, err := ioutil.ReadAll(f) + if err != nil { + return "", errors.WithStack(err) + } + + return string(data), nil +} + +// given this many bytes, we will produce this many words +func wordlenFromBytes(numBytes int) int { + // 8 bits per byte, and we add +10 so it rounds up + return (8*numBytes + 10) / 11 +} + +// given this many words, we will produce this many bytes. +// sometimes there are two possibilities. +// if maybeShorter is true, then represents len OR len-1 bytes +func bytelenFromWords(numWords int) (length int, maybeShorter bool) { + // calculate the max number of complete bytes we could store in this word + length = 11 * numWords / 8 + // if one less byte would also generate this length, set maybeShorter + if wordlenFromBytes(length-1) == numWords { + maybeShorter = true + } + return +} + +// TODO: add checksum +func (c WordCodec) BytesToWords(data []byte) (words []string, err error) { + // 2048 words per bank, which is 2^11. + numWords := wordlenFromBytes(len(data)) + + n2048 := big.NewInt(2048) + nData := big.NewInt(0).SetBytes(data) + nRem := big.NewInt(0) + // Alternative, use condition "nData.BitLen() > 0" + // to allow for shorter words when data has leading 0's + for i := 0; i < numWords; i++ { + nData.DivMod(nData, n2048, nRem) + rem := nRem.Int64() + words = append(words, c.words[rem]) + } + fmt.Println(words) + return words, nil +} + +func (c WordCodec) WordsToBytes(words []string) ([]byte, error) { + // // 2048 words per bank, which is 2^11. + // numWords := (8*len(dest) + 10) / 11 + // if numWords != len(words) { + // return errors.New(Fmt("Expected %v words for %v dest bytes", numWords, len(dest))) + // } + + l := len(words) + n2048 := big.NewInt(2048) + nData := big.NewInt(0) + // since we output words based on the remainder, the first word has the lowest + // value... we must load them in reverse order + for i := 1; i <= l; i++ { + w := words[l-i] + rem, ok := c.bytes[w] + if !ok { + return nil, errors.Errorf("Unrecognized word: %s", w) + } + nRem := big.NewInt(int64(rem)) + nData.Mul(nData, n2048) + nData.Add(nData, nRem) + fmt.Printf("+%d: %v\n", rem, nData) + } + + // we copy into a slice of the expected size, so it is not shorter if there + // are lots of leading 0s + dataBytes := nData.Bytes() + fmt.Printf("%#v\n", dataBytes) + + outLen, _ := bytelenFromWords(len(words)) + output := make([]byte, outLen) + copy(output[outLen-len(dataBytes):], dataBytes) + fmt.Printf("%#v\n", output) + return output, nil +} diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go new file mode 100644 index 000000000..b75bc9661 --- /dev/null +++ b/keys/wordcodec_test.go @@ -0,0 +1,85 @@ +package keys + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestLengthCalc(t *testing.T) { + assert := assert.New(t) + + cases := []struct { + bytes, words int + flexible bool + }{ + {1, 1, false}, + {2, 2, false}, + // bytes pairs with same word count + {3, 3, true}, + {4, 3, true}, + {5, 4, false}, + // bytes pairs with same word count + {10, 8, true}, + {11, 8, true}, + {12, 9, false}, + {13, 10, false}, + {20, 15, false}, + // bytes pairs with same word count + {21, 16, true}, + {32, 24, true}, + } + + for _, tc := range cases { + wl := wordlenFromBytes(tc.bytes) + assert.Equal(tc.words, wl, "%d", tc.bytes) + + bl, flex := bytelenFromWords(tc.words) + assert.Equal(tc.flexible, flex, "%d", tc.words) + if !flex { + assert.Equal(tc.bytes, bl, "%d", tc.words) + } else { + // check if it is either tc.bytes or tc.bytes +1 + choices := []int{tc.bytes, tc.bytes + 1} + assert.Contains(choices, bl, "%d", tc.words) + } + } +} + +func TestEncodeDecode(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + codec, err := LoadCodec("english") + require.Nil(err, "%+v", err) + + cases := [][]byte{ + // {7, 8, 9}, // TODO: 3 words -> 3 or 4 bytes + // {12, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes + {1, 2, 3, 4, 5}, // normal + {0, 0, 0, 0, 5, 22, 123, 55, 22}, // leading 0s (9 chars, clear) + {22, 44, 55, 1, 13, 0, 0, 0, 0}, // trailing 0s (9 chars, clear) + {0, 5, 253, 2, 0}, // leading and trailing zeros + // others? + } + + for i, tc := range cases { + w, err := codec.BytesToWords(tc) + if assert.Nil(err, "%d: %v", i, err) { + b, err := codec.WordsToBytes(w) + if assert.Nil(err, "%d: %v", i, err) { + assert.Equal(len(tc), len(b)) + assert.Equal(tc, b) + } + } + } +} + +func TestCheckInvalidLists(t *testing.T) { + // assert, require := assert.New(t), require.New(t) + +} + +func TestCheckTypoDetection(t *testing.T) { + +} diff --git a/keys/wordlist/english.txt b/keys/wordlist/english.txt new file mode 100644 index 000000000..942040ed5 --- /dev/null +++ b/keys/wordlist/english.txt @@ -0,0 +1,2048 @@ +abandon +ability +able +about +above +absent +absorb +abstract +absurd +abuse +access +accident +account +accuse +achieve +acid +acoustic +acquire +across +act +action +actor +actress +actual +adapt +add +addict +address +adjust +admit +adult +advance +advice +aerobic +affair +afford +afraid +again +age +agent +agree +ahead +aim +air +airport +aisle +alarm +album +alcohol +alert +alien +all +alley +allow +almost +alone +alpha +already +also +alter +always +amateur +amazing +among +amount +amused +analyst +anchor +ancient +anger +angle +angry +animal +ankle +announce +annual +another +answer +antenna +antique +anxiety +any +apart +apology +appear +apple +approve +april +arch +arctic +area +arena +argue +arm +armed +armor +army +around +arrange +arrest +arrive +arrow +art +artefact +artist +artwork +ask +aspect +assault +asset +assist +assume +asthma +athlete +atom +attack +attend +attitude +attract +auction +audit +august +aunt +author +auto +autumn +average +avocado +avoid +awake +aware +away +awesome +awful +awkward +axis +baby +bachelor +bacon +badge +bag +balance +balcony +ball +bamboo +banana +banner +bar +barely +bargain +barrel +base +basic +basket +battle +beach +bean +beauty +because +become +beef +before +begin +behave +behind +believe +below +belt +bench +benefit +best +betray +better +between +beyond +bicycle +bid +bike +bind +biology +bird +birth +bitter +black +blade +blame +blanket +blast +bleak +bless +blind +blood +blossom +blouse +blue +blur +blush +board +boat +body +boil +bomb +bone +bonus +book +boost +border +boring +borrow +boss +bottom +bounce +box +boy +bracket +brain +brand +brass +brave +bread +breeze +brick +bridge +brief +bright +bring +brisk +broccoli +broken +bronze +broom +brother +brown +brush +bubble +buddy +budget +buffalo +build +bulb +bulk +bullet +bundle +bunker +burden +burger +burst +bus +business +busy +butter +buyer +buzz +cabbage +cabin +cable +cactus +cage +cake +call +calm +camera +camp +can +canal +cancel +candy +cannon +canoe +canvas +canyon +capable +capital +captain +car +carbon +card +cargo +carpet +carry +cart +case +cash +casino +castle +casual +cat +catalog +catch +category +cattle +caught +cause +caution +cave +ceiling +celery +cement +census +century +cereal +certain +chair +chalk +champion +change +chaos +chapter +charge +chase +chat +cheap +check +cheese +chef +cherry +chest +chicken +chief +child +chimney +choice +choose +chronic +chuckle +chunk +churn +cigar +cinnamon +circle +citizen +city +civil +claim +clap +clarify +claw +clay +clean +clerk +clever +click +client +cliff +climb +clinic +clip +clock +clog +close +cloth +cloud +clown +club +clump +cluster +clutch +coach +coast +coconut +code +coffee +coil +coin +collect +color +column +combine +come +comfort +comic +common +company +concert +conduct +confirm +congress +connect +consider +control +convince +cook +cool +copper +copy +coral +core +corn +correct +cost +cotton +couch +country +couple +course +cousin +cover +coyote +crack +cradle +craft +cram +crane +crash +crater +crawl +crazy +cream +credit +creek +crew +cricket +crime +crisp +critic +crop +cross +crouch +crowd +crucial +cruel +cruise +crumble +crunch +crush +cry +crystal +cube +culture +cup +cupboard +curious +current +curtain +curve +cushion +custom +cute +cycle +dad +damage +damp +dance +danger +daring +dash +daughter +dawn +day +deal +debate +debris +decade +december +decide +decline +decorate +decrease +deer +defense +define +defy +degree +delay +deliver +demand +demise +denial +dentist +deny +depart +depend +deposit +depth +deputy +derive +describe +desert +design +desk +despair +destroy +detail +detect +develop +device +devote +diagram +dial +diamond +diary +dice +diesel +diet +differ +digital +dignity +dilemma +dinner +dinosaur +direct +dirt +disagree +discover +disease +dish +dismiss +disorder +display +distance +divert +divide +divorce +dizzy +doctor +document +dog +doll +dolphin +domain +donate +donkey +donor +door +dose +double +dove +draft +dragon +drama +drastic +draw +dream +dress +drift +drill +drink +drip +drive +drop +drum +dry +duck +dumb +dune +during +dust +dutch +duty +dwarf +dynamic +eager +eagle +early +earn +earth +easily +east +easy +echo +ecology +economy +edge +edit +educate +effort +egg +eight +either +elbow +elder +electric +elegant +element +elephant +elevator +elite +else +embark +embody +embrace +emerge +emotion +employ +empower +empty +enable +enact +end +endless +endorse +enemy +energy +enforce +engage +engine +enhance +enjoy +enlist +enough +enrich +enroll +ensure +enter +entire +entry +envelope +episode +equal +equip +era +erase +erode +erosion +error +erupt +escape +essay +essence +estate +eternal +ethics +evidence +evil +evoke +evolve +exact +example +excess +exchange +excite +exclude +excuse +execute +exercise +exhaust +exhibit +exile +exist +exit +exotic +expand +expect +expire +explain +expose +express +extend +extra +eye +eyebrow +fabric +face +faculty +fade +faint +faith +fall +false +fame +family +famous +fan +fancy +fantasy +farm +fashion +fat +fatal +father +fatigue +fault +favorite +feature +february +federal +fee +feed +feel +female +fence +festival +fetch +fever +few +fiber +fiction +field +figure +file +film +filter +final +find +fine +finger +finish +fire +firm +first +fiscal +fish +fit +fitness +fix +flag +flame +flash +flat +flavor +flee +flight +flip +float +flock +floor +flower +fluid +flush +fly +foam +focus +fog +foil +fold +follow +food +foot +force +forest +forget +fork +fortune +forum +forward +fossil +foster +found +fox +fragile +frame +frequent +fresh +friend +fringe +frog +front +frost +frown +frozen +fruit +fuel +fun +funny +furnace +fury +future +gadget +gain +galaxy +gallery +game +gap +garage +garbage +garden +garlic +garment +gas +gasp +gate +gather +gauge +gaze +general +genius +genre +gentle +genuine +gesture +ghost +giant +gift +giggle +ginger +giraffe +girl +give +glad +glance +glare +glass +glide +glimpse +globe +gloom +glory +glove +glow +glue +goat +goddess +gold +good +goose +gorilla +gospel +gossip +govern +gown +grab +grace +grain +grant +grape +grass +gravity +great +green +grid +grief +grit +grocery +group +grow +grunt +guard +guess +guide +guilt +guitar +gun +gym +habit +hair +half +hammer +hamster +hand +happy +harbor +hard +harsh +harvest +hat +have +hawk +hazard +head +health +heart +heavy +hedgehog +height +hello +helmet +help +hen +hero +hidden +high +hill +hint +hip +hire +history +hobby +hockey +hold +hole +holiday +hollow +home +honey +hood +hope +horn +horror +horse +hospital +host +hotel +hour +hover +hub +huge +human +humble +humor +hundred +hungry +hunt +hurdle +hurry +hurt +husband +hybrid +ice +icon +idea +identify +idle +ignore +ill +illegal +illness +image +imitate +immense +immune +impact +impose +improve +impulse +inch +include +income +increase +index +indicate +indoor +industry +infant +inflict +inform +inhale +inherit +initial +inject +injury +inmate +inner +innocent +input +inquiry +insane +insect +inside +inspire +install +intact +interest +into +invest +invite +involve +iron +island +isolate +issue +item +ivory +jacket +jaguar +jar +jazz +jealous +jeans +jelly +jewel +job +join +joke +journey +joy +judge +juice +jump +jungle +junior +junk +just +kangaroo +keen +keep +ketchup +key +kick +kid +kidney +kind +kingdom +kiss +kit +kitchen +kite +kitten +kiwi +knee +knife +knock +know +lab +label +labor +ladder +lady +lake +lamp +language +laptop +large +later +latin +laugh +laundry +lava +law +lawn +lawsuit +layer +lazy +leader +leaf +learn +leave +lecture +left +leg +legal +legend +leisure +lemon +lend +length +lens +leopard +lesson +letter +level +liar +liberty +library +license +life +lift +light +like +limb +limit +link +lion +liquid +list +little +live +lizard +load +loan +lobster +local +lock +logic +lonely +long +loop +lottery +loud +lounge +love +loyal +lucky +luggage +lumber +lunar +lunch +luxury +lyrics +machine +mad +magic +magnet +maid +mail +main +major +make +mammal +man +manage +mandate +mango +mansion +manual +maple +marble +march +margin +marine +market +marriage +mask +mass +master +match +material +math +matrix +matter +maximum +maze +meadow +mean +measure +meat +mechanic +medal +media +melody +melt +member +memory +mention +menu +mercy +merge +merit +merry +mesh +message +metal +method +middle +midnight +milk +million +mimic +mind +minimum +minor +minute +miracle +mirror +misery +miss +mistake +mix +mixed +mixture +mobile +model +modify +mom +moment +monitor +monkey +monster +month +moon +moral +more +morning +mosquito +mother +motion +motor +mountain +mouse +move +movie +much +muffin +mule +multiply +muscle +museum +mushroom +music +must +mutual +myself +mystery +myth +naive +name +napkin +narrow +nasty +nation +nature +near +neck +need +negative +neglect +neither +nephew +nerve +nest +net +network +neutral +never +news +next +nice +night +noble +noise +nominee +noodle +normal +north +nose +notable +note +nothing +notice +novel +now +nuclear +number +nurse +nut +oak +obey +object +oblige +obscure +observe +obtain +obvious +occur +ocean +october +odor +off +offer +office +often +oil +okay +old +olive +olympic +omit +once +one +onion +online +only +open +opera +opinion +oppose +option +orange +orbit +orchard +order +ordinary +organ +orient +original +orphan +ostrich +other +outdoor +outer +output +outside +oval +oven +over +own +owner +oxygen +oyster +ozone +pact +paddle +page +pair +palace +palm +panda +panel +panic +panther +paper +parade +parent +park +parrot +party +pass +patch +path +patient +patrol +pattern +pause +pave +payment +peace +peanut +pear +peasant +pelican +pen +penalty +pencil +people +pepper +perfect +permit +person +pet +phone +photo +phrase +physical +piano +picnic +picture +piece +pig +pigeon +pill +pilot +pink +pioneer +pipe +pistol +pitch +pizza +place +planet +plastic +plate +play +please +pledge +pluck +plug +plunge +poem +poet +point +polar +pole +police +pond +pony +pool +popular +portion +position +possible +post +potato +pottery +poverty +powder +power +practice +praise +predict +prefer +prepare +present +pretty +prevent +price +pride +primary +print +priority +prison +private +prize +problem +process +produce +profit +program +project +promote +proof +property +prosper +protect +proud +provide +public +pudding +pull +pulp +pulse +pumpkin +punch +pupil +puppy +purchase +purity +purpose +purse +push +put +puzzle +pyramid +quality +quantum +quarter +question +quick +quit +quiz +quote +rabbit +raccoon +race +rack +radar +radio +rail +rain +raise +rally +ramp +ranch +random +range +rapid +rare +rate +rather +raven +raw +razor +ready +real +reason +rebel +rebuild +recall +receive +recipe +record +recycle +reduce +reflect +reform +refuse +region +regret +regular +reject +relax +release +relief +rely +remain +remember +remind +remove +render +renew +rent +reopen +repair +repeat +replace +report +require +rescue +resemble +resist +resource +response +result +retire +retreat +return +reunion +reveal +review +reward +rhythm +rib +ribbon +rice +rich +ride +ridge +rifle +right +rigid +ring +riot +ripple +risk +ritual +rival +river +road +roast +robot +robust +rocket +romance +roof +rookie +room +rose +rotate +rough +round +route +royal +rubber +rude +rug +rule +run +runway +rural +sad +saddle +sadness +safe +sail +salad +salmon +salon +salt +salute +same +sample +sand +satisfy +satoshi +sauce +sausage +save +say +scale +scan +scare +scatter +scene +scheme +school +science +scissors +scorpion +scout +scrap +screen +script +scrub +sea +search +season +seat +second +secret +section +security +seed +seek +segment +select +sell +seminar +senior +sense +sentence +series +service +session +settle +setup +seven +shadow +shaft +shallow +share +shed +shell +sheriff +shield +shift +shine +ship +shiver +shock +shoe +shoot +shop +short +shoulder +shove +shrimp +shrug +shuffle +shy +sibling +sick +side +siege +sight +sign +silent +silk +silly +silver +similar +simple +since +sing +siren +sister +situate +six +size +skate +sketch +ski +skill +skin +skirt +skull +slab +slam +sleep +slender +slice +slide +slight +slim +slogan +slot +slow +slush +small +smart +smile +smoke +smooth +snack +snake +snap +sniff +snow +soap +soccer +social +sock +soda +soft +solar +soldier +solid +solution +solve +someone +song +soon +sorry +sort +soul +sound +soup +source +south +space +spare +spatial +spawn +speak +special +speed +spell +spend +sphere +spice +spider +spike +spin +spirit +split +spoil +sponsor +spoon +sport +spot +spray +spread +spring +spy +square +squeeze +squirrel +stable +stadium +staff +stage +stairs +stamp +stand +start +state +stay +steak +steel +stem +step +stereo +stick +still +sting +stock +stomach +stone +stool +story +stove +strategy +street +strike +strong +struggle +student +stuff +stumble +style +subject +submit +subway +success +such +sudden +suffer +sugar +suggest +suit +summer +sun +sunny +sunset +super +supply +supreme +sure +surface +surge +surprise +surround +survey +suspect +sustain +swallow +swamp +swap +swarm +swear +sweet +swift +swim +swing +switch +sword +symbol +symptom +syrup +system +table +tackle +tag +tail +talent +talk +tank +tape +target +task +taste +tattoo +taxi +teach +team +tell +ten +tenant +tennis +tent +term +test +text +thank +that +theme +then +theory +there +they +thing +this +thought +three +thrive +throw +thumb +thunder +ticket +tide +tiger +tilt +timber +time +tiny +tip +tired +tissue +title +toast +tobacco +today +toddler +toe +together +toilet +token +tomato +tomorrow +tone +tongue +tonight +tool +tooth +top +topic +topple +torch +tornado +tortoise +toss +total +tourist +toward +tower +town +toy +track +trade +traffic +tragic +train +transfer +trap +trash +travel +tray +treat +tree +trend +trial +tribe +trick +trigger +trim +trip +trophy +trouble +truck +true +truly +trumpet +trust +truth +try +tube +tuition +tumble +tuna +tunnel +turkey +turn +turtle +twelve +twenty +twice +twin +twist +two +type +typical +ugly +umbrella +unable +unaware +uncle +uncover +under +undo +unfair +unfold +unhappy +uniform +unique +unit +universe +unknown +unlock +until +unusual +unveil +update +upgrade +uphold +upon +upper +upset +urban +urge +usage +use +used +useful +useless +usual +utility +vacant +vacuum +vague +valid +valley +valve +van +vanish +vapor +various +vast +vault +vehicle +velvet +vendor +venture +venue +verb +verify +version +very +vessel +veteran +viable +vibrant +vicious +victory +video +view +village +vintage +violin +virtual +virus +visa +visit +visual +vital +vivid +vocal +voice +void +volcano +volume +vote +voyage +wage +wagon +wait +walk +wall +walnut +want +warfare +warm +warrior +wash +wasp +waste +water +wave +way +wealth +weapon +wear +weasel +weather +web +wedding +weekend +weird +welcome +west +wet +whale +what +wheat +wheel +when +where +whip +whisper +wide +width +wife +wild +will +win +window +wine +wing +wink +winner +winter +wire +wisdom +wise +wish +witness +wolf +woman +wonder +wood +wool +word +work +world +worry +worth +wrap +wreck +wrestle +wrist +write +wrong +yard +year +yellow +you +young +youth +zebra +zero +zone +zoo From e20cdfcbaeac42a42ac8ec62ed808001379d592b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 15:20:40 +0200 Subject: [PATCH 085/273] Cleanup wordcodec --- keys/wordcodec.go | 46 +++++++++++++++++++++++++----------------- keys/wordcodec_test.go | 10 ++++++--- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/keys/wordcodec.go b/keys/wordcodec.go index 3a750940b..b3e45e2c6 100644 --- a/keys/wordcodec.go +++ b/keys/wordcodec.go @@ -1,7 +1,6 @@ package keys import ( - "fmt" "io/ioutil" "math/big" "os" @@ -31,15 +30,7 @@ func NewCodec(words []string) (codec WordCodec, err error) { return codec, errors.Errorf("Bank must have %d words, found %d", BankSize, len(words)) } - b := map[string]int{} - for i, w := range words { - if _, ok := b[w]; ok { - return codec, errors.Errorf("Duplicate word in list: %s", w) - } - b[w] = i - } - - return WordCodec{words, b}, nil + return WordCodec{words: words}, nil } func LoadCodec(bank string) (codec WordCodec, err error) { @@ -111,7 +102,6 @@ func (c WordCodec) BytesToWords(data []byte) (words []string, err error) { rem := nRem.Int64() words = append(words, c.words[rem]) } - fmt.Println(words) return words, nil } @@ -128,25 +118,45 @@ func (c WordCodec) WordsToBytes(words []string) ([]byte, error) { // since we output words based on the remainder, the first word has the lowest // value... we must load them in reverse order for i := 1; i <= l; i++ { - w := words[l-i] - rem, ok := c.bytes[w] - if !ok { - return nil, errors.Errorf("Unrecognized word: %s", w) + rem, err := c.GetIndex(words[l-i]) + if err != nil { + return nil, err } nRem := big.NewInt(int64(rem)) nData.Mul(nData, n2048) nData.Add(nData, nRem) - fmt.Printf("+%d: %v\n", rem, nData) } // we copy into a slice of the expected size, so it is not shorter if there // are lots of leading 0s dataBytes := nData.Bytes() - fmt.Printf("%#v\n", dataBytes) outLen, _ := bytelenFromWords(len(words)) output := make([]byte, outLen) copy(output[outLen-len(dataBytes):], dataBytes) - fmt.Printf("%#v\n", output) return output, nil } + +// GetIndex finds the index of the words to create bytes +// Generates a map the first time it is loaded, to avoid needless +// computation when list is not used. +func (c WordCodec) GetIndex(word string) (int, error) { + // generate the first time + if c.bytes == nil { + b := map[string]int{} + for i, w := range c.words { + if _, ok := b[w]; ok { + return -1, errors.Errorf("Duplicate word in list: %s", w) + } + b[w] = i + } + c.bytes = b + } + + // get the index, or an error + rem, ok := c.bytes[word] + if !ok { + return -1, errors.Errorf("Unrecognized word: %s", word) + } + return rem, nil +} diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index b75bc9661..e96912072 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -54,12 +54,16 @@ func TestEncodeDecode(t *testing.T) { require.Nil(err, "%+v", err) cases := [][]byte{ - // {7, 8, 9}, // TODO: 3 words -> 3 or 4 bytes - // {12, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes - {1, 2, 3, 4, 5}, // normal + // {7, 8, 9}, // TODO: 3 words -> 3 or 4 bytes + {12, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes + {0, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes, detect leading 0 + {1, 2, 3, 4, 5}, // normal + // {0, 0, 0, 0, 122, 23, 82, 195}, // leading 0s (8 chars, unclear) {0, 0, 0, 0, 5, 22, 123, 55, 22}, // leading 0s (9 chars, clear) {22, 44, 55, 1, 13, 0, 0, 0, 0}, // trailing 0s (9 chars, clear) {0, 5, 253, 2, 0}, // leading and trailing zeros + {255, 196, 172, 234, 192, 255}, // big numbers + // {255, 196, 172, 1, 234, 192, 255}, // big numbers, two length choices // others? } From 55a25f0f6233557212c1b2c0cbd3ae40600b259b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 15:49:17 +0200 Subject: [PATCH 086/273] Add first pass of ecc checksuming --- keys/ecc.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ keys/ecc_test.go | 52 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 keys/ecc.go create mode 100644 keys/ecc_test.go diff --git a/keys/ecc.go b/keys/ecc.go new file mode 100644 index 000000000..ff16345d3 --- /dev/null +++ b/keys/ecc.go @@ -0,0 +1,56 @@ +package keys + +import ( + "encoding/binary" + "errors" + "hash/crc32" +) + +// ECC is used for anything that calculates an error-correcting code +type ECC interface { + // AddECC calculates an error-correcting code for the input + // returns an output with the code appended + AddECC([]byte) []byte + + // CheckECC verifies if the ECC is proper on the input and returns + // the data with the code removed, or an error + CheckECC([]byte) ([]byte, error) +} + +// NoECC is a no-op placeholder, kind of useless... except for tests +type NoECC struct{} + +var _ ECC = NoECC{} + +func (_ NoECC) AddECC(input []byte) []byte { return input } +func (_ NoECC) CheckECC(input []byte) ([]byte, error) { return input, nil } + +// CRC32 does the ieee crc32 polynomial check +type CRC32 struct{} + +var _ ECC = CRC32{} + +func (_ CRC32) AddECC(input []byte) []byte { + // get crc and convert to some bytes... + crc := crc32.ChecksumIEEE(input) + check := make([]byte, 4) + binary.BigEndian.PutUint32(check, crc) + + // append it to the input + output := append(input, check...) + return output +} + +func (_ CRC32) CheckECC(input []byte) ([]byte, error) { + if len(input) <= 4 { + return nil, errors.New("input too short, no checksum present") + } + cut := len(input) - 4 + data, check := input[:cut], input[cut:] + crc := binary.BigEndian.Uint32(check) + calc := crc32.ChecksumIEEE(data) + if crc != calc { + return nil, errors.New("Checksum does not match") + } + return data, nil +} diff --git a/keys/ecc_test.go b/keys/ecc_test.go new file mode 100644 index 000000000..f58bc7a9c --- /dev/null +++ b/keys/ecc_test.go @@ -0,0 +1,52 @@ +package keys + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + cmn "github.com/tendermint/tmlibs/common" +) + +// TestECCPasses makes sure that the AddECC/CheckECC methods are symetric +func TestECCPasses(t *testing.T) { + assert := assert.New(t) + + checks := []ECC{NoECC{}, CRC32{}} + + for _, check := range checks { + for i := 0; i < 2000; i++ { + numBytes := cmn.RandInt()%60 + 1 + data := cmn.RandBytes(numBytes) + + checked := check.AddECC(data) + res, err := check.CheckECC(checked) + if assert.Nil(err, "%v: %+v", check, err) { + assert.Equal(data, res, "%v", check) + } + } + } +} + +// TestECCFails makes sure random data will (usually) fail the checksum +func TestECCFails(t *testing.T) { + assert := assert.New(t) + + checks := []ECC{CRC32{}} + + attempts := 2000 + + for _, check := range checks { + failed := 0 + for i := 0; i < attempts; i++ { + numBytes := cmn.RandInt()%60 + 1 + data := cmn.RandBytes(numBytes) + _, err := check.CheckECC(data) + if err != nil { + failed += 1 + } + } + // we allow up to 1 falsely accepted checksums, as there are random matches + assert.InDelta(attempts, failed, 1, "%v", check) + } +} From ce6b08761ed3970ba46e82b632816ba03776314f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 15:56:12 +0200 Subject: [PATCH 087/273] Improve crc32 --- keys/ecc.go | 35 ++++++++++++++++++++++++++--------- keys/ecc_test.go | 5 +++-- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/keys/ecc.go b/keys/ecc.go index ff16345d3..ba754d525 100644 --- a/keys/ecc.go +++ b/keys/ecc.go @@ -26,14 +26,19 @@ func (_ NoECC) AddECC(input []byte) []byte { return input } func (_ NoECC) CheckECC(input []byte) ([]byte, error) { return input, nil } // CRC32 does the ieee crc32 polynomial check -type CRC32 struct{} +type CRC32 struct { + Poly uint32 + table *crc32.Table +} + +var _ ECC = &CRC32{} -var _ ECC = CRC32{} +func (c *CRC32) AddECC(input []byte) []byte { + table := c.getTable() -func (_ CRC32) AddECC(input []byte) []byte { // get crc and convert to some bytes... - crc := crc32.ChecksumIEEE(input) - check := make([]byte, 4) + crc := crc32.Checksum(input, table) + check := make([]byte, crc32.Size) binary.BigEndian.PutUint32(check, crc) // append it to the input @@ -41,16 +46,28 @@ func (_ CRC32) AddECC(input []byte) []byte { return output } -func (_ CRC32) CheckECC(input []byte) ([]byte, error) { - if len(input) <= 4 { +func (c *CRC32) CheckECC(input []byte) ([]byte, error) { + table := c.getTable() + + if len(input) <= crc32.Size { return nil, errors.New("input too short, no checksum present") } - cut := len(input) - 4 + cut := len(input) - crc32.Size data, check := input[:cut], input[cut:] crc := binary.BigEndian.Uint32(check) - calc := crc32.ChecksumIEEE(data) + calc := crc32.Checksum(data, table) if crc != calc { return nil, errors.New("Checksum does not match") } return data, nil } + +func (c *CRC32) getTable() *crc32.Table { + if c.table == nil { + if c.Poly == 0 { + c.Poly = crc32.IEEE + } + c.table = crc32.MakeTable(c.Poly) + } + return c.table +} diff --git a/keys/ecc_test.go b/keys/ecc_test.go index f58bc7a9c..a85d4ddd7 100644 --- a/keys/ecc_test.go +++ b/keys/ecc_test.go @@ -1,6 +1,7 @@ package keys import ( + "hash/crc32" "testing" "github.com/stretchr/testify/assert" @@ -12,7 +13,7 @@ import ( func TestECCPasses(t *testing.T) { assert := assert.New(t) - checks := []ECC{NoECC{}, CRC32{}} + checks := []ECC{NoECC{}, &CRC32{}, &CRC32{Poly: crc32.Castagnoli}} for _, check := range checks { for i := 0; i < 2000; i++ { @@ -32,7 +33,7 @@ func TestECCPasses(t *testing.T) { func TestECCFails(t *testing.T) { assert := assert.New(t) - checks := []ECC{CRC32{}} + checks := []ECC{&CRC32{}, &CRC32{Poly: crc32.Castagnoli}} attempts := 2000 From 0b0e994cd1ca63c386e8d2cda8aec9188a5834a6 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 16:02:47 +0200 Subject: [PATCH 088/273] Add crc64, constructors --- keys/ecc.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ keys/ecc_test.go | 20 +++++++++++--- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/keys/ecc.go b/keys/ecc.go index ba754d525..96590cd91 100644 --- a/keys/ecc.go +++ b/keys/ecc.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "errors" "hash/crc32" + "hash/crc64" ) // ECC is used for anything that calculates an error-correcting code @@ -33,6 +34,18 @@ type CRC32 struct { var _ ECC = &CRC32{} +func NewIEEECRC32() *CRC32 { + return &CRC32{Poly: crc32.IEEE} +} + +func NewCastagnoliCRC32() *CRC32 { + return &CRC32{Poly: crc32.Castagnoli} +} + +func NewKoopmanCRC32() *CRC32 { + return &CRC32{Poly: crc32.Koopman} +} + func (c *CRC32) AddECC(input []byte) []byte { table := c.getTable() @@ -71,3 +84,58 @@ func (c *CRC32) getTable() *crc32.Table { } return c.table } + +// CRC64 does the ieee crc64 polynomial check +type CRC64 struct { + Poly uint64 + table *crc64.Table +} + +var _ ECC = &CRC64{} + +func NewISOCRC64() *CRC64 { + return &CRC64{Poly: crc64.ISO} +} + +func NewECMACRC64() *CRC64 { + return &CRC64{Poly: crc64.ECMA} +} + +func (c *CRC64) AddECC(input []byte) []byte { + table := c.getTable() + + // get crc and convert to some bytes... + crc := crc64.Checksum(input, table) + check := make([]byte, crc64.Size) + binary.BigEndian.PutUint64(check, crc) + + // append it to the input + output := append(input, check...) + return output +} + +func (c *CRC64) CheckECC(input []byte) ([]byte, error) { + table := c.getTable() + + if len(input) <= crc64.Size { + return nil, errors.New("input too short, no checksum present") + } + cut := len(input) - crc64.Size + data, check := input[:cut], input[cut:] + crc := binary.BigEndian.Uint64(check) + calc := crc64.Checksum(data, table) + if crc != calc { + return nil, errors.New("Checksum does not match") + } + return data, nil +} + +func (c *CRC64) getTable() *crc64.Table { + if c.table == nil { + if c.Poly == 0 { + c.Poly = crc64.ISO + } + c.table = crc64.MakeTable(c.Poly) + } + return c.table +} diff --git a/keys/ecc_test.go b/keys/ecc_test.go index a85d4ddd7..334c49423 100644 --- a/keys/ecc_test.go +++ b/keys/ecc_test.go @@ -1,7 +1,6 @@ package keys import ( - "hash/crc32" "testing" "github.com/stretchr/testify/assert" @@ -13,7 +12,14 @@ import ( func TestECCPasses(t *testing.T) { assert := assert.New(t) - checks := []ECC{NoECC{}, &CRC32{}, &CRC32{Poly: crc32.Castagnoli}} + checks := []ECC{ + NoECC{}, + NewIEEECRC32(), + NewCastagnoliCRC32(), + NewKoopmanCRC32(), + NewISOCRC64(), + NewECMACRC64(), + } for _, check := range checks { for i := 0; i < 2000; i++ { @@ -22,7 +28,7 @@ func TestECCPasses(t *testing.T) { checked := check.AddECC(data) res, err := check.CheckECC(checked) - if assert.Nil(err, "%v: %+v", check, err) { + if assert.Nil(err, "%#v: %+v", check, err) { assert.Equal(data, res, "%v", check) } } @@ -33,7 +39,13 @@ func TestECCPasses(t *testing.T) { func TestECCFails(t *testing.T) { assert := assert.New(t) - checks := []ECC{&CRC32{}, &CRC32{Poly: crc32.Castagnoli}} + checks := []ECC{ + NewIEEECRC32(), + NewCastagnoliCRC32(), + NewKoopmanCRC32(), + NewISOCRC64(), + NewECMACRC64(), + } attempts := 2000 From ad029d1293fbec4b687b9b4c5ac63b9e76d9e89b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 16:10:15 +0200 Subject: [PATCH 089/273] Integrate ecc into word-byte codec --- keys/wordcodec.go | 39 ++++++++++++++++++++++++++------------- keys/wordcodec_test.go | 20 ++++++++++---------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/keys/wordcodec.go b/keys/wordcodec.go index b3e45e2c6..7778b9b53 100644 --- a/keys/wordcodec.go +++ b/keys/wordcodec.go @@ -21,6 +21,7 @@ type Codec interface { type WordCodec struct { words []string bytes map[string]int + check ECC } var _ Codec = WordCodec{} @@ -30,7 +31,13 @@ func NewCodec(words []string) (codec WordCodec, err error) { return codec, errors.Errorf("Bank must have %d words, found %d", BankSize, len(words)) } - return WordCodec{words: words}, nil + res := WordCodec{ + words: words, + // TODO: configure this outside??? + check: NewIEEECRC32(), + } + + return res, nil } func LoadCodec(bank string) (codec WordCodec, err error) { @@ -70,6 +77,7 @@ func getData(filename string) (string, error) { // given this many bytes, we will produce this many words func wordlenFromBytes(numBytes int) int { + // 2048 words per bank, which is 2^11. // 8 bits per byte, and we add +10 so it rounds up return (8*numBytes + 10) / 11 } @@ -88,8 +96,9 @@ func bytelenFromWords(numWords int) (length int, maybeShorter bool) { } // TODO: add checksum -func (c WordCodec) BytesToWords(data []byte) (words []string, err error) { - // 2048 words per bank, which is 2^11. +func (c WordCodec) BytesToWords(raw []byte) (words []string, err error) { + // always add a checksum to the data + data := c.check.AddECC(raw) numWords := wordlenFromBytes(len(data)) n2048 := big.NewInt(2048) @@ -106,12 +115,6 @@ func (c WordCodec) BytesToWords(data []byte) (words []string, err error) { } func (c WordCodec) WordsToBytes(words []string) ([]byte, error) { - // // 2048 words per bank, which is 2^11. - // numWords := (8*len(dest) + 10) / 11 - // if numWords != len(words) { - // return errors.New(Fmt("Expected %v words for %v dest bytes", numWords, len(dest))) - // } - l := len(words) n2048 := big.NewInt(2048) nData := big.NewInt(0) @@ -131,10 +134,20 @@ func (c WordCodec) WordsToBytes(words []string) ([]byte, error) { // are lots of leading 0s dataBytes := nData.Bytes() - outLen, _ := bytelenFromWords(len(words)) - output := make([]byte, outLen) - copy(output[outLen-len(dataBytes):], dataBytes) - return output, nil + // copy into the container we have with the expected size + outLen, flex := bytelenFromWords(len(words)) + toCheck := make([]byte, outLen) + copy(toCheck[outLen-len(dataBytes):], dataBytes) + + // validate the checksum... + output, err := c.check.CheckECC(toCheck) + if flex && err != nil { + // if flex, try again one shorter.... + toCheck = toCheck[1:] + output, err = c.check.CheckECC(toCheck) + } + + return output, err } // GetIndex finds the index of the words to create bytes diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index e96912072..e650eb0dd 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -54,16 +54,16 @@ func TestEncodeDecode(t *testing.T) { require.Nil(err, "%+v", err) cases := [][]byte{ - // {7, 8, 9}, // TODO: 3 words -> 3 or 4 bytes - {12, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes - {0, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes, detect leading 0 - {1, 2, 3, 4, 5}, // normal - // {0, 0, 0, 0, 122, 23, 82, 195}, // leading 0s (8 chars, unclear) - {0, 0, 0, 0, 5, 22, 123, 55, 22}, // leading 0s (9 chars, clear) - {22, 44, 55, 1, 13, 0, 0, 0, 0}, // trailing 0s (9 chars, clear) - {0, 5, 253, 2, 0}, // leading and trailing zeros - {255, 196, 172, 234, 192, 255}, // big numbers - // {255, 196, 172, 1, 234, 192, 255}, // big numbers, two length choices + {7, 8, 9}, // TODO: 3 words -> 3 or 4 bytes + {12, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes + {0, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes, detect leading 0 + {1, 2, 3, 4, 5}, // normal + {0, 0, 0, 0, 122, 23, 82, 195}, // leading 0s (8 chars, unclear) + {0, 0, 0, 0, 5, 22, 123, 55, 22}, // leading 0s (9 chars, clear) + {22, 44, 55, 1, 13, 0, 0, 0, 0}, // trailing 0s (9 chars, clear) + {0, 5, 253, 2, 0}, // leading and trailing zeros + {255, 196, 172, 234, 192, 255}, // big numbers + {255, 196, 172, 1, 234, 192, 255}, // big numbers, two length choices // others? } From 65c880e7533b8150df406f8761087506b8d88f91 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 16:32:33 +0200 Subject: [PATCH 090/273] Test validation of word banks upon load --- keys/wordcodec.go | 8 ++++++- keys/wordcodec_test.go | 48 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/keys/wordcodec.go b/keys/wordcodec.go index 7778b9b53..c69f7ae1d 100644 --- a/keys/wordcodec.go +++ b/keys/wordcodec.go @@ -109,7 +109,13 @@ func (c WordCodec) BytesToWords(raw []byte) (words []string, err error) { for i := 0; i < numWords; i++ { nData.DivMod(nData, n2048, nRem) rem := nRem.Int64() - words = append(words, c.words[rem]) + w := c.words[rem] + // double-check bank on generation... + _, err := c.GetIndex(w) + if err != nil { + return nil, err + } + words = append(words, w) } return words, nil } diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index e650eb0dd..40ac24f42 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -5,6 +5,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + cmn "github.com/tendermint/tmlibs/common" ) func TestLengthCalc(t *testing.T) { @@ -80,7 +82,51 @@ func TestEncodeDecode(t *testing.T) { } func TestCheckInvalidLists(t *testing.T) { - // assert, require := assert.New(t), require.New(t) + assert := assert.New(t) + + trivial := []string{"abc", "def"} + short := make([]string, 1234) + long := make([]string, BankSize+1) + right := make([]string, BankSize) + dups := make([]string, BankSize) + + for _, list := range [][]string{short, long, right, dups} { + for i := range list { + list[i] = cmn.RandStr(8) + } + } + // create one single duplicate + dups[192] = dups[782] + + cases := []struct { + words []string + loadable bool + valid bool + }{ + {trivial, false, false}, + {short, false, false}, + {long, false, false}, + {dups, true, false}, // we only check dups on first use... + {right, true, true}, + } + + for i, tc := range cases { + codec, err := NewCodec(tc.words) + if !tc.loadable { + assert.NotNil(err, "%d", i) + } else if assert.Nil(err, "%d: %+v", i, err) { + data := cmn.RandBytes(32) + w, err := codec.BytesToWords(data) + if tc.valid { + assert.Nil(err, "%d: %+v", i, err) + b, err := codec.WordsToBytes(w) + assert.Nil(err, "%d: %+v", i, err) + assert.Equal(data, b) + } else { + assert.NotNil(err, "%d", i) + } + } + } } From 2c0d52f4b5a70a798bea3d2c7a203d9664eb1240 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 16:52:04 +0200 Subject: [PATCH 091/273] Add typo detector test, fix panics --- keys/wordcodec.go | 8 ++++++++ keys/wordcodec_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/keys/wordcodec.go b/keys/wordcodec.go index c69f7ae1d..5ac32f812 100644 --- a/keys/wordcodec.go +++ b/keys/wordcodec.go @@ -122,6 +122,11 @@ func (c WordCodec) BytesToWords(raw []byte) (words []string, err error) { func (c WordCodec) WordsToBytes(words []string) ([]byte, error) { l := len(words) + + if l == 0 { + return nil, errors.New("Didn't provide any words") + } + n2048 := big.NewInt(2048) nData := big.NewInt(0) // since we output words based on the remainder, the first word has the lowest @@ -143,6 +148,9 @@ func (c WordCodec) WordsToBytes(words []string) ([]byte, error) { // copy into the container we have with the expected size outLen, flex := bytelenFromWords(len(words)) toCheck := make([]byte, outLen) + if len(dataBytes) > outLen { + return nil, errors.New("Invalid data, could not have been generated by this codec") + } copy(toCheck[outLen-len(dataBytes):], dataBytes) // validate the checksum... diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index 40ac24f42..b9496a0ef 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -130,6 +130,52 @@ func TestCheckInvalidLists(t *testing.T) { } +func getRandWord(c WordCodec) string { + idx := cmn.RandInt() % BankSize + return c.words[idx] +} + +func getDiffWord(c WordCodec, not string) string { + w := getRandWord(c) + if w == not { + w = getRandWord(c) + } + return w +} + func TestCheckTypoDetection(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + banks := []string{"english"} + + for _, bank := range banks { + codec, err := LoadCodec(bank) + require.Nil(err, "%s: %+v", bank, err) + for i := 0; i < 10; i++ { + numBytes := cmn.RandInt()%60 + 1 + data := cmn.RandBytes(numBytes) + + words, err := codec.BytesToWords(data) + assert.Nil(err, "%s: %+v", bank, err) + good, err := codec.WordsToBytes(words) + assert.Nil(err, "%s: %+v", bank, err) + assert.Equal(data, good, bank) + + // now try some tweaks... + cut := words[1:] + _, err = codec.WordsToBytes(cut) + assert.NotNil(err, "%s: %s", bank, words) + + // swap a word within the bank, should fails + words[3] = getDiffWord(codec, words[3]) + _, err = codec.WordsToBytes(words) + assert.NotNil(err, "%s: %s", bank, words) + + // put a random word here, must fail + words[3] = cmn.RandStr(10) + _, err = codec.WordsToBytes(words) + assert.NotNil(err, "%s: %s", bank, words) + } + } } From 1e978ba8381f25c39df1ac4a3fad18e8cd0fa38a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 16:53:07 +0200 Subject: [PATCH 092/273] Import multiple language wordbanks, test them --- keys/wordcodec_test.go | 2 +- keys/wordlist/chinese_simplified.txt | 2048 ++++++++++++++++++++++++++ keys/wordlist/japanese.txt | 2048 ++++++++++++++++++++++++++ keys/wordlist/spanish.txt | 2048 ++++++++++++++++++++++++++ 4 files changed, 6145 insertions(+), 1 deletion(-) create mode 100644 keys/wordlist/chinese_simplified.txt create mode 100644 keys/wordlist/japanese.txt create mode 100644 keys/wordlist/spanish.txt diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index b9496a0ef..c3a5a2cac 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -146,7 +146,7 @@ func getDiffWord(c WordCodec, not string) string { func TestCheckTypoDetection(t *testing.T) { assert, require := assert.New(t), require.New(t) - banks := []string{"english"} + banks := []string{"english", "spanish", "japanese", "chinese_simplified"} for _, bank := range banks { codec, err := LoadCodec(bank) diff --git a/keys/wordlist/chinese_simplified.txt b/keys/wordlist/chinese_simplified.txt new file mode 100644 index 000000000..b90f1ed85 --- /dev/null +++ b/keys/wordlist/chinese_simplified.txt @@ -0,0 +1,2048 @@ +的 +一 +是 +在 +不 +了 +有 +和 +人 +这 +中 +大 +为 +上 +个 +国 +我 +以 +要 +他 +时 +来 +用 +们 +生 +到 +作 +地 +于 +出 +就 +分 +对 +成 +会 +可 +主 +发 +年 +动 +同 +工 +也 +能 +下 +过 +子 +说 +产 +种 +面 +而 +方 +后 +多 +定 +行 +学 +法 +所 +民 +得 +经 +十 +三 +之 +进 +着 +等 +部 +度 +家 +电 +力 +里 +如 +水 +化 +高 +自 +二 +理 +起 +小 +物 +现 +实 +加 +量 +都 +两 +体 +制 +机 +当 +使 +点 +从 +业 +本 +去 +把 +性 +好 +应 +开 +它 +合 +还 +因 +由 +其 +些 +然 +前 +外 +天 +政 +四 +日 +那 +社 +义 +事 +平 +形 +相 +全 +表 +间 +样 +与 +关 +各 +重 +新 +线 +内 +数 +正 +心 +反 +你 +明 +看 +原 +又 +么 +利 +比 +或 +但 +质 +气 +第 +向 +道 +命 +此 +变 +条 +只 +没 +结 +解 +问 +意 +建 +月 +公 +无 +系 +军 +很 +情 +者 +最 +立 +代 +想 +已 +通 +并 +提 +直 +题 +党 +程 +展 +五 +果 +料 +象 +员 +革 +位 +入 +常 +文 +总 +次 +品 +式 +活 +设 +及 +管 +特 +件 +长 +求 +老 +头 +基 +资 +边 +流 +路 +级 +少 +图 +山 +统 +接 +知 +较 +将 +组 +见 +计 +别 +她 +手 +角 +期 +根 +论 +运 +农 +指 +几 +九 +区 +强 +放 +决 +西 +被 +干 +做 +必 +战 +先 +回 +则 +任 +取 +据 +处 +队 +南 +给 +色 +光 +门 +即 +保 +治 +北 +造 +百 +规 +热 +领 +七 +海 +口 +东 +导 +器 +压 +志 +世 +金 +增 +争 +济 +阶 +油 +思 +术 +极 +交 +受 +联 +什 +认 +六 +共 +权 +收 +证 +改 +清 +美 +再 +采 +转 +更 +单 +风 +切 +打 +白 +教 +速 +花 +带 +安 +场 +身 +车 +例 +真 +务 +具 +万 +每 +目 +至 +达 +走 +积 +示 +议 +声 +报 +斗 +完 +类 +八 +离 +华 +名 +确 +才 +科 +张 +信 +马 +节 +话 +米 +整 +空 +元 +况 +今 +集 +温 +传 +土 +许 +步 +群 +广 +石 +记 +需 +段 +研 +界 +拉 +林 +律 +叫 +且 +究 +观 +越 +织 +装 +影 +算 +低 +持 +音 +众 +书 +布 +复 +容 +儿 +须 +际 +商 +非 +验 +连 +断 +深 +难 +近 +矿 +千 +周 +委 +素 +技 +备 +半 +办 +青 +省 +列 +习 +响 +约 +支 +般 +史 +感 +劳 +便 +团 +往 +酸 +历 +市 +克 +何 +除 +消 +构 +府 +称 +太 +准 +精 +值 +号 +率 +族 +维 +划 +选 +标 +写 +存 +候 +毛 +亲 +快 +效 +斯 +院 +查 +江 +型 +眼 +王 +按 +格 +养 +易 +置 +派 +层 +片 +始 +却 +专 +状 +育 +厂 +京 +识 +适 +属 +圆 +包 +火 +住 +调 +满 +县 +局 +照 +参 +红 +细 +引 +听 +该 +铁 +价 +严 +首 +底 +液 +官 +德 +随 +病 +苏 +失 +尔 +死 +讲 +配 +女 +黄 +推 +显 +谈 +罪 +神 +艺 +呢 +席 +含 +企 +望 +密 +批 +营 +项 +防 +举 +球 +英 +氧 +势 +告 +李 +台 +落 +木 +帮 +轮 +破 +亚 +师 +围 +注 +远 +字 +材 +排 +供 +河 +态 +封 +另 +施 +减 +树 +溶 +怎 +止 +案 +言 +士 +均 +武 +固 +叶 +鱼 +波 +视 +仅 +费 +紧 +爱 +左 +章 +早 +朝 +害 +续 +轻 +服 +试 +食 +充 +兵 +源 +判 +护 +司 +足 +某 +练 +差 +致 +板 +田 +降 +黑 +犯 +负 +击 +范 +继 +兴 +似 +余 +坚 +曲 +输 +修 +故 +城 +夫 +够 +送 +笔 +船 +占 +右 +财 +吃 +富 +春 +职 +觉 +汉 +画 +功 +巴 +跟 +虽 +杂 +飞 +检 +吸 +助 +升 +阳 +互 +初 +创 +抗 +考 +投 +坏 +策 +古 +径 +换 +未 +跑 +留 +钢 +曾 +端 +责 +站 +简 +述 +钱 +副 +尽 +帝 +射 +草 +冲 +承 +独 +令 +限 +阿 +宣 +环 +双 +请 +超 +微 +让 +控 +州 +良 +轴 +找 +否 +纪 +益 +依 +优 +顶 +础 +载 +倒 +房 +突 +坐 +粉 +敌 +略 +客 +袁 +冷 +胜 +绝 +析 +块 +剂 +测 +丝 +协 +诉 +念 +陈 +仍 +罗 +盐 +友 +洋 +错 +苦 +夜 +刑 +移 +频 +逐 +靠 +混 +母 +短 +皮 +终 +聚 +汽 +村 +云 +哪 +既 +距 +卫 +停 +烈 +央 +察 +烧 +迅 +境 +若 +印 +洲 +刻 +括 +激 +孔 +搞 +甚 +室 +待 +核 +校 +散 +侵 +吧 +甲 +游 +久 +菜 +味 +旧 +模 +湖 +货 +损 +预 +阻 +毫 +普 +稳 +乙 +妈 +植 +息 +扩 +银 +语 +挥 +酒 +守 +拿 +序 +纸 +医 +缺 +雨 +吗 +针 +刘 +啊 +急 +唱 +误 +训 +愿 +审 +附 +获 +茶 +鲜 +粮 +斤 +孩 +脱 +硫 +肥 +善 +龙 +演 +父 +渐 +血 +欢 +械 +掌 +歌 +沙 +刚 +攻 +谓 +盾 +讨 +晚 +粒 +乱 +燃 +矛 +乎 +杀 +药 +宁 +鲁 +贵 +钟 +煤 +读 +班 +伯 +香 +介 +迫 +句 +丰 +培 +握 +兰 +担 +弦 +蛋 +沉 +假 +穿 +执 +答 +乐 +谁 +顺 +烟 +缩 +征 +脸 +喜 +松 +脚 +困 +异 +免 +背 +星 +福 +买 +染 +井 +概 +慢 +怕 +磁 +倍 +祖 +皇 +促 +静 +补 +评 +翻 +肉 +践 +尼 +衣 +宽 +扬 +棉 +希 +伤 +操 +垂 +秋 +宜 +氢 +套 +督 +振 +架 +亮 +末 +宪 +庆 +编 +牛 +触 +映 +雷 +销 +诗 +座 +居 +抓 +裂 +胞 +呼 +娘 +景 +威 +绿 +晶 +厚 +盟 +衡 +鸡 +孙 +延 +危 +胶 +屋 +乡 +临 +陆 +顾 +掉 +呀 +灯 +岁 +措 +束 +耐 +剧 +玉 +赵 +跳 +哥 +季 +课 +凯 +胡 +额 +款 +绍 +卷 +齐 +伟 +蒸 +殖 +永 +宗 +苗 +川 +炉 +岩 +弱 +零 +杨 +奏 +沿 +露 +杆 +探 +滑 +镇 +饭 +浓 +航 +怀 +赶 +库 +夺 +伊 +灵 +税 +途 +灭 +赛 +归 +召 +鼓 +播 +盘 +裁 +险 +康 +唯 +录 +菌 +纯 +借 +糖 +盖 +横 +符 +私 +努 +堂 +域 +枪 +润 +幅 +哈 +竟 +熟 +虫 +泽 +脑 +壤 +碳 +欧 +遍 +侧 +寨 +敢 +彻 +虑 +斜 +薄 +庭 +纳 +弹 +饲 +伸 +折 +麦 +湿 +暗 +荷 +瓦 +塞 +床 +筑 +恶 +户 +访 +塔 +奇 +透 +梁 +刀 +旋 +迹 +卡 +氯 +遇 +份 +毒 +泥 +退 +洗 +摆 +灰 +彩 +卖 +耗 +夏 +择 +忙 +铜 +献 +硬 +予 +繁 +圈 +雪 +函 +亦 +抽 +篇 +阵 +阴 +丁 +尺 +追 +堆 +雄 +迎 +泛 +爸 +楼 +避 +谋 +吨 +野 +猪 +旗 +累 +偏 +典 +馆 +索 +秦 +脂 +潮 +爷 +豆 +忽 +托 +惊 +塑 +遗 +愈 +朱 +替 +纤 +粗 +倾 +尚 +痛 +楚 +谢 +奋 +购 +磨 +君 +池 +旁 +碎 +骨 +监 +捕 +弟 +暴 +割 +贯 +殊 +释 +词 +亡 +壁 +顿 +宝 +午 +尘 +闻 +揭 +炮 +残 +冬 +桥 +妇 +警 +综 +招 +吴 +付 +浮 +遭 +徐 +您 +摇 +谷 +赞 +箱 +隔 +订 +男 +吹 +园 +纷 +唐 +败 +宋 +玻 +巨 +耕 +坦 +荣 +闭 +湾 +键 +凡 +驻 +锅 +救 +恩 +剥 +凝 +碱 +齿 +截 +炼 +麻 +纺 +禁 +废 +盛 +版 +缓 +净 +睛 +昌 +婚 +涉 +筒 +嘴 +插 +岸 +朗 +庄 +街 +藏 +姑 +贸 +腐 +奴 +啦 +惯 +乘 +伙 +恢 +匀 +纱 +扎 +辩 +耳 +彪 +臣 +亿 +璃 +抵 +脉 +秀 +萨 +俄 +网 +舞 +店 +喷 +纵 +寸 +汗 +挂 +洪 +贺 +闪 +柬 +爆 +烯 +津 +稻 +墙 +软 +勇 +像 +滚 +厘 +蒙 +芳 +肯 +坡 +柱 +荡 +腿 +仪 +旅 +尾 +轧 +冰 +贡 +登 +黎 +削 +钻 +勒 +逃 +障 +氨 +郭 +峰 +币 +港 +伏 +轨 +亩 +毕 +擦 +莫 +刺 +浪 +秘 +援 +株 +健 +售 +股 +岛 +甘 +泡 +睡 +童 +铸 +汤 +阀 +休 +汇 +舍 +牧 +绕 +炸 +哲 +磷 +绩 +朋 +淡 +尖 +启 +陷 +柴 +呈 +徒 +颜 +泪 +稍 +忘 +泵 +蓝 +拖 +洞 +授 +镜 +辛 +壮 +锋 +贫 +虚 +弯 +摩 +泰 +幼 +廷 +尊 +窗 +纲 +弄 +隶 +疑 +氏 +宫 +姐 +震 +瑞 +怪 +尤 +琴 +循 +描 +膜 +违 +夹 +腰 +缘 +珠 +穷 +森 +枝 +竹 +沟 +催 +绳 +忆 +邦 +剩 +幸 +浆 +栏 +拥 +牙 +贮 +礼 +滤 +钠 +纹 +罢 +拍 +咱 +喊 +袖 +埃 +勤 +罚 +焦 +潜 +伍 +墨 +欲 +缝 +姓 +刊 +饱 +仿 +奖 +铝 +鬼 +丽 +跨 +默 +挖 +链 +扫 +喝 +袋 +炭 +污 +幕 +诸 +弧 +励 +梅 +奶 +洁 +灾 +舟 +鉴 +苯 +讼 +抱 +毁 +懂 +寒 +智 +埔 +寄 +届 +跃 +渡 +挑 +丹 +艰 +贝 +碰 +拔 +爹 +戴 +码 +梦 +芽 +熔 +赤 +渔 +哭 +敬 +颗 +奔 +铅 +仲 +虎 +稀 +妹 +乏 +珍 +申 +桌 +遵 +允 +隆 +螺 +仓 +魏 +锐 +晓 +氮 +兼 +隐 +碍 +赫 +拨 +忠 +肃 +缸 +牵 +抢 +博 +巧 +壳 +兄 +杜 +讯 +诚 +碧 +祥 +柯 +页 +巡 +矩 +悲 +灌 +龄 +伦 +票 +寻 +桂 +铺 +圣 +恐 +恰 +郑 +趣 +抬 +荒 +腾 +贴 +柔 +滴 +猛 +阔 +辆 +妻 +填 +撤 +储 +签 +闹 +扰 +紫 +砂 +递 +戏 +吊 +陶 +伐 +喂 +疗 +瓶 +婆 +抚 +臂 +摸 +忍 +虾 +蜡 +邻 +胸 +巩 +挤 +偶 +弃 +槽 +劲 +乳 +邓 +吉 +仁 +烂 +砖 +租 +乌 +舰 +伴 +瓜 +浅 +丙 +暂 +燥 +橡 +柳 +迷 +暖 +牌 +秧 +胆 +详 +簧 +踏 +瓷 +谱 +呆 +宾 +糊 +洛 +辉 +愤 +竞 +隙 +怒 +粘 +乃 +绪 +肩 +籍 +敏 +涂 +熙 +皆 +侦 +悬 +掘 +享 +纠 +醒 +狂 +锁 +淀 +恨 +牲 +霸 +爬 +赏 +逆 +玩 +陵 +祝 +秒 +浙 +貌 +役 +彼 +悉 +鸭 +趋 +凤 +晨 +畜 +辈 +秩 +卵 +署 +梯 +炎 +滩 +棋 +驱 +筛 +峡 +冒 +啥 +寿 +译 +浸 +泉 +帽 +迟 +硅 +疆 +贷 +漏 +稿 +冠 +嫩 +胁 +芯 +牢 +叛 +蚀 +奥 +鸣 +岭 +羊 +凭 +串 +塘 +绘 +酵 +融 +盆 +锡 +庙 +筹 +冻 +辅 +摄 +袭 +筋 +拒 +僚 +旱 +钾 +鸟 +漆 +沈 +眉 +疏 +添 +棒 +穗 +硝 +韩 +逼 +扭 +侨 +凉 +挺 +碗 +栽 +炒 +杯 +患 +馏 +劝 +豪 +辽 +勃 +鸿 +旦 +吏 +拜 +狗 +埋 +辊 +掩 +饮 +搬 +骂 +辞 +勾 +扣 +估 +蒋 +绒 +雾 +丈 +朵 +姆 +拟 +宇 +辑 +陕 +雕 +偿 +蓄 +崇 +剪 +倡 +厅 +咬 +驶 +薯 +刷 +斥 +番 +赋 +奉 +佛 +浇 +漫 +曼 +扇 +钙 +桃 +扶 +仔 +返 +俗 +亏 +腔 +鞋 +棱 +覆 +框 +悄 +叔 +撞 +骗 +勘 +旺 +沸 +孤 +吐 +孟 +渠 +屈 +疾 +妙 +惜 +仰 +狠 +胀 +谐 +抛 +霉 +桑 +岗 +嘛 +衰 +盗 +渗 +脏 +赖 +涌 +甜 +曹 +阅 +肌 +哩 +厉 +烃 +纬 +毅 +昨 +伪 +症 +煮 +叹 +钉 +搭 +茎 +笼 +酷 +偷 +弓 +锥 +恒 +杰 +坑 +鼻 +翼 +纶 +叙 +狱 +逮 +罐 +络 +棚 +抑 +膨 +蔬 +寺 +骤 +穆 +冶 +枯 +册 +尸 +凸 +绅 +坯 +牺 +焰 +轰 +欣 +晋 +瘦 +御 +锭 +锦 +丧 +旬 +锻 +垄 +搜 +扑 +邀 +亭 +酯 +迈 +舒 +脆 +酶 +闲 +忧 +酚 +顽 +羽 +涨 +卸 +仗 +陪 +辟 +惩 +杭 +姚 +肚 +捉 +飘 +漂 +昆 +欺 +吾 +郎 +烷 +汁 +呵 +饰 +萧 +雅 +邮 +迁 +燕 +撒 +姻 +赴 +宴 +烦 +债 +帐 +斑 +铃 +旨 +醇 +董 +饼 +雏 +姿 +拌 +傅 +腹 +妥 +揉 +贤 +拆 +歪 +葡 +胺 +丢 +浩 +徽 +昂 +垫 +挡 +览 +贪 +慰 +缴 +汪 +慌 +冯 +诺 +姜 +谊 +凶 +劣 +诬 +耀 +昏 +躺 +盈 +骑 +乔 +溪 +丛 +卢 +抹 +闷 +咨 +刮 +驾 +缆 +悟 +摘 +铒 +掷 +颇 +幻 +柄 +惠 +惨 +佳 +仇 +腊 +窝 +涤 +剑 +瞧 +堡 +泼 +葱 +罩 +霍 +捞 +胎 +苍 +滨 +俩 +捅 +湘 +砍 +霞 +邵 +萄 +疯 +淮 +遂 +熊 +粪 +烘 +宿 +档 +戈 +驳 +嫂 +裕 +徙 +箭 +捐 +肠 +撑 +晒 +辨 +殿 +莲 +摊 +搅 +酱 +屏 +疫 +哀 +蔡 +堵 +沫 +皱 +畅 +叠 +阁 +莱 +敲 +辖 +钩 +痕 +坝 +巷 +饿 +祸 +丘 +玄 +溜 +曰 +逻 +彭 +尝 +卿 +妨 +艇 +吞 +韦 +怨 +矮 +歇 diff --git a/keys/wordlist/japanese.txt b/keys/wordlist/japanese.txt new file mode 100644 index 000000000..c4c9dca4e --- /dev/null +++ b/keys/wordlist/japanese.txt @@ -0,0 +1,2048 @@ +あいこくしん +あいさつ +あいだ +あおぞら +あかちゃん +あきる +あけがた +あける +あこがれる +あさい +あさひ +あしあと +あじわう +あずかる +あずき +あそぶ +あたえる +あたためる +あたりまえ +あたる +あつい +あつかう +あっしゅく +あつまり +あつめる +あてな +あてはまる +あひる +あぶら +あぶる +あふれる +あまい +あまど +あまやかす +あまり +あみもの +あめりか +あやまる +あゆむ +あらいぐま +あらし +あらすじ +あらためる +あらゆる +あらわす +ありがとう +あわせる +あわてる +あんい +あんがい +あんこ +あんぜん +あんてい +あんない +あんまり +いいだす +いおん +いがい +いがく +いきおい +いきなり +いきもの +いきる +いくじ +いくぶん +いけばな +いけん +いこう +いこく +いこつ +いさましい +いさん +いしき +いじゅう +いじょう +いじわる +いずみ +いずれ +いせい +いせえび +いせかい +いせき +いぜん +いそうろう +いそがしい +いだい +いだく +いたずら +いたみ +いたりあ +いちおう +いちじ +いちど +いちば +いちぶ +いちりゅう +いつか +いっしゅん +いっせい +いっそう +いったん +いっち +いってい +いっぽう +いてざ +いてん +いどう +いとこ +いない +いなか +いねむり +いのち +いのる +いはつ +いばる +いはん +いびき +いひん +いふく +いへん +いほう +いみん +いもうと +いもたれ +いもり +いやがる +いやす +いよかん +いよく +いらい +いらすと +いりぐち +いりょう +いれい +いれもの +いれる +いろえんぴつ +いわい +いわう +いわかん +いわば +いわゆる +いんげんまめ +いんさつ +いんしょう +いんよう +うえき +うえる +うおざ +うがい +うかぶ +うかべる +うきわ +うくらいな +うくれれ +うけたまわる +うけつけ +うけとる +うけもつ +うける +うごかす +うごく +うこん +うさぎ +うしなう +うしろがみ +うすい +うすぎ +うすぐらい +うすめる +うせつ +うちあわせ +うちがわ +うちき +うちゅう +うっかり +うつくしい +うったえる +うつる +うどん +うなぎ +うなじ +うなずく +うなる +うねる +うのう +うぶげ +うぶごえ +うまれる +うめる +うもう +うやまう +うよく +うらがえす +うらぐち +うらない +うりあげ +うりきれ +うるさい +うれしい +うれゆき +うれる +うろこ +うわき +うわさ +うんこう +うんちん +うんてん +うんどう +えいえん +えいが +えいきょう +えいご +えいせい +えいぶん +えいよう +えいわ +えおり +えがお +えがく +えきたい +えくせる +えしゃく +えすて +えつらん +えのぐ +えほうまき +えほん +えまき +えもじ +えもの +えらい +えらぶ +えりあ +えんえん +えんかい +えんぎ +えんげき +えんしゅう +えんぜつ +えんそく +えんちょう +えんとつ +おいかける +おいこす +おいしい +おいつく +おうえん +おうさま +おうじ +おうせつ +おうたい +おうふく +おうべい +おうよう +おえる +おおい +おおう +おおどおり +おおや +おおよそ +おかえり +おかず +おがむ +おかわり +おぎなう +おきる +おくさま +おくじょう +おくりがな +おくる +おくれる +おこす +おこなう +おこる +おさえる +おさない +おさめる +おしいれ +おしえる +おじぎ +おじさん +おしゃれ +おそらく +おそわる +おたがい +おたく +おだやか +おちつく +おっと +おつり +おでかけ +おとしもの +おとなしい +おどり +おどろかす +おばさん +おまいり +おめでとう +おもいで +おもう +おもたい +おもちゃ +おやつ +おやゆび +およぼす +おらんだ +おろす +おんがく +おんけい +おんしゃ +おんせん +おんだん +おんちゅう +おんどけい +かあつ +かいが +がいき +がいけん +がいこう +かいさつ +かいしゃ +かいすいよく +かいぜん +かいぞうど +かいつう +かいてん +かいとう +かいふく +がいへき +かいほう +かいよう +がいらい +かいわ +かえる +かおり +かかえる +かがく +かがし +かがみ +かくご +かくとく +かざる +がぞう +かたい +かたち +がちょう +がっきゅう +がっこう +がっさん +がっしょう +かなざわし +かのう +がはく +かぶか +かほう +かほご +かまう +かまぼこ +かめれおん +かゆい +かようび +からい +かるい +かろう +かわく +かわら +がんか +かんけい +かんこう +かんしゃ +かんそう +かんたん +かんち +がんばる +きあい +きあつ +きいろ +ぎいん +きうい +きうん +きえる +きおう +きおく +きおち +きおん +きかい +きかく +きかんしゃ +ききて +きくばり +きくらげ +きけんせい +きこう +きこえる +きこく +きさい +きさく +きさま +きさらぎ +ぎじかがく +ぎしき +ぎじたいけん +ぎじにってい +ぎじゅつしゃ +きすう +きせい +きせき +きせつ +きそう +きぞく +きぞん +きたえる +きちょう +きつえん +ぎっちり +きつつき +きつね +きてい +きどう +きどく +きない +きなが +きなこ +きぬごし +きねん +きのう +きのした +きはく +きびしい +きひん +きふく +きぶん +きぼう +きほん +きまる +きみつ +きむずかしい +きめる +きもだめし +きもち +きもの +きゃく +きやく +ぎゅうにく +きよう +きょうりゅう +きらい +きらく +きりん +きれい +きれつ +きろく +ぎろん +きわめる +ぎんいろ +きんかくじ +きんじょ +きんようび +ぐあい +くいず +くうかん +くうき +くうぐん +くうこう +ぐうせい +くうそう +ぐうたら +くうふく +くうぼ +くかん +くきょう +くげん +ぐこう +くさい +くさき +くさばな +くさる +くしゃみ +くしょう +くすのき +くすりゆび +くせげ +くせん +ぐたいてき +くださる +くたびれる +くちこみ +くちさき +くつした +ぐっすり +くつろぐ +くとうてん +くどく +くなん +くねくね +くのう +くふう +くみあわせ +くみたてる +くめる +くやくしょ +くらす +くらべる +くるま +くれる +くろう +くわしい +ぐんかん +ぐんしょく +ぐんたい +ぐんて +けあな +けいかく +けいけん +けいこ +けいさつ +げいじゅつ +けいたい +げいのうじん +けいれき +けいろ +けおとす +けおりもの +げきか +げきげん +げきだん +げきちん +げきとつ +げきは +げきやく +げこう +げこくじょう +げざい +けさき +げざん +けしき +けしごむ +けしょう +げすと +けたば +けちゃっぷ +けちらす +けつあつ +けつい +けつえき +けっこん +けつじょ +けっせき +けってい +けつまつ +げつようび +げつれい +けつろん +げどく +けとばす +けとる +けなげ +けなす +けなみ +けぬき +げねつ +けねん +けはい +げひん +けぶかい +げぼく +けまり +けみかる +けむし +けむり +けもの +けらい +けろけろ +けわしい +けんい +けんえつ +けんお +けんか +げんき +けんげん +けんこう +けんさく +けんしゅう +けんすう +げんそう +けんちく +けんてい +けんとう +けんない +けんにん +げんぶつ +けんま +けんみん +けんめい +けんらん +けんり +こあくま +こいぬ +こいびと +ごうい +こうえん +こうおん +こうかん +ごうきゅう +ごうけい +こうこう +こうさい +こうじ +こうすい +ごうせい +こうそく +こうたい +こうちゃ +こうつう +こうてい +こうどう +こうない +こうはい +ごうほう +ごうまん +こうもく +こうりつ +こえる +こおり +ごかい +ごがつ +ごかん +こくご +こくさい +こくとう +こくない +こくはく +こぐま +こけい +こける +ここのか +こころ +こさめ +こしつ +こすう +こせい +こせき +こぜん +こそだて +こたい +こたえる +こたつ +こちょう +こっか +こつこつ +こつばん +こつぶ +こてい +こてん +ことがら +ことし +ことば +ことり +こなごな +こねこね +このまま +このみ +このよ +ごはん +こひつじ +こふう +こふん +こぼれる +ごまあぶら +こまかい +ごますり +こまつな +こまる +こむぎこ +こもじ +こもち +こもの +こもん +こやく +こやま +こゆう +こゆび +こよい +こよう +こりる +これくしょん +ころっけ +こわもて +こわれる +こんいん +こんかい +こんき +こんしゅう +こんすい +こんだて +こんとん +こんなん +こんびに +こんぽん +こんまけ +こんや +こんれい +こんわく +ざいえき +さいかい +さいきん +ざいげん +ざいこ +さいしょ +さいせい +ざいたく +ざいちゅう +さいてき +ざいりょう +さうな +さかいし +さがす +さかな +さかみち +さがる +さぎょう +さくし +さくひん +さくら +さこく +さこつ +さずかる +ざせき +さたん +さつえい +ざつおん +ざっか +ざつがく +さっきょく +ざっし +さつじん +ざっそう +さつたば +さつまいも +さてい +さといも +さとう +さとおや +さとし +さとる +さのう +さばく +さびしい +さべつ +さほう +さほど +さます +さみしい +さみだれ +さむけ +さめる +さやえんどう +さゆう +さよう +さよく +さらだ +ざるそば +さわやか +さわる +さんいん +さんか +さんきゃく +さんこう +さんさい +ざんしょ +さんすう +さんせい +さんそ +さんち +さんま +さんみ +さんらん +しあい +しあげ +しあさって +しあわせ +しいく +しいん +しうち +しえい +しおけ +しかい +しかく +じかん +しごと +しすう +じだい +したうけ +したぎ +したて +したみ +しちょう +しちりん +しっかり +しつじ +しつもん +してい +してき +してつ +じてん +じどう +しなぎれ +しなもの +しなん +しねま +しねん +しのぐ +しのぶ +しはい +しばかり +しはつ +しはらい +しはん +しひょう +しふく +じぶん +しへい +しほう +しほん +しまう +しまる +しみん +しむける +じむしょ +しめい +しめる +しもん +しゃいん +しゃうん +しゃおん +じゃがいも +しやくしょ +しゃくほう +しゃけん +しゃこ +しゃざい +しゃしん +しゃせん +しゃそう +しゃたい +しゃちょう +しゃっきん +じゃま +しゃりん +しゃれい +じゆう +じゅうしょ +しゅくはく +じゅしん +しゅっせき +しゅみ +しゅらば +じゅんばん +しょうかい +しょくたく +しょっけん +しょどう +しょもつ +しらせる +しらべる +しんか +しんこう +じんじゃ +しんせいじ +しんちく +しんりん +すあげ +すあし +すあな +ずあん +すいえい +すいか +すいとう +ずいぶん +すいようび +すうがく +すうじつ +すうせん +すおどり +すきま +すくう +すくない +すける +すごい +すこし +ずさん +すずしい +すすむ +すすめる +すっかり +ずっしり +ずっと +すてき +すてる +すねる +すのこ +すはだ +すばらしい +ずひょう +ずぶぬれ +すぶり +すふれ +すべて +すべる +ずほう +すぼん +すまい +すめし +すもう +すやき +すらすら +するめ +すれちがう +すろっと +すわる +すんぜん +すんぽう +せあぶら +せいかつ +せいげん +せいじ +せいよう +せおう +せかいかん +せきにん +せきむ +せきゆ +せきらんうん +せけん +せこう +せすじ +せたい +せたけ +せっかく +せっきゃく +ぜっく +せっけん +せっこつ +せっさたくま +せつぞく +せつだん +せつでん +せっぱん +せつび +せつぶん +せつめい +せつりつ +せなか +せのび +せはば +せびろ +せぼね +せまい +せまる +せめる +せもたれ +せりふ +ぜんあく +せんい +せんえい +せんか +せんきょ +せんく +せんげん +ぜんご +せんさい +せんしゅ +せんすい +せんせい +せんぞ +せんたく +せんちょう +せんてい +せんとう +せんぬき +せんねん +せんぱい +ぜんぶ +ぜんぽう +せんむ +せんめんじょ +せんもん +せんやく +せんゆう +せんよう +ぜんら +ぜんりゃく +せんれい +せんろ +そあく +そいとげる +そいね +そうがんきょう +そうき +そうご +そうしん +そうだん +そうなん +そうび +そうめん +そうり +そえもの +そえん +そがい +そげき +そこう +そこそこ +そざい +そしな +そせい +そせん +そそぐ +そだてる +そつう +そつえん +そっかん +そつぎょう +そっけつ +そっこう +そっせん +そっと +そとがわ +そとづら +そなえる +そなた +そふぼ +そぼく +そぼろ +そまつ +そまる +そむく +そむりえ +そめる +そもそも +そよかぜ +そらまめ +そろう +そんかい +そんけい +そんざい +そんしつ +そんぞく +そんちょう +ぞんび +ぞんぶん +そんみん +たあい +たいいん +たいうん +たいえき +たいおう +だいがく +たいき +たいぐう +たいけん +たいこ +たいざい +だいじょうぶ +だいすき +たいせつ +たいそう +だいたい +たいちょう +たいてい +だいどころ +たいない +たいねつ +たいのう +たいはん +だいひょう +たいふう +たいへん +たいほ +たいまつばな +たいみんぐ +たいむ +たいめん +たいやき +たいよう +たいら +たいりょく +たいる +たいわん +たうえ +たえる +たおす +たおる +たおれる +たかい +たかね +たきび +たくさん +たこく +たこやき +たさい +たしざん +だじゃれ +たすける +たずさわる +たそがれ +たたかう +たたく +ただしい +たたみ +たちばな +だっかい +だっきゃく +だっこ +だっしゅつ +だったい +たてる +たとえる +たなばた +たにん +たぬき +たのしみ +たはつ +たぶん +たべる +たぼう +たまご +たまる +だむる +ためいき +ためす +ためる +たもつ +たやすい +たよる +たらす +たりきほんがん +たりょう +たりる +たると +たれる +たれんと +たろっと +たわむれる +だんあつ +たんい +たんおん +たんか +たんき +たんけん +たんご +たんさん +たんじょうび +だんせい +たんそく +たんたい +だんち +たんてい +たんとう +だんな +たんにん +だんねつ +たんのう +たんぴん +だんぼう +たんまつ +たんめい +だんれつ +だんろ +だんわ +ちあい +ちあん +ちいき +ちいさい +ちえん +ちかい +ちから +ちきゅう +ちきん +ちけいず +ちけん +ちこく +ちさい +ちしき +ちしりょう +ちせい +ちそう +ちたい +ちたん +ちちおや +ちつじょ +ちてき +ちてん +ちぬき +ちぬり +ちのう +ちひょう +ちへいせん +ちほう +ちまた +ちみつ +ちみどろ +ちめいど +ちゃんこなべ +ちゅうい +ちゆりょく +ちょうし +ちょさくけん +ちらし +ちらみ +ちりがみ +ちりょう +ちるど +ちわわ +ちんたい +ちんもく +ついか +ついたち +つうか +つうじょう +つうはん +つうわ +つかう +つかれる +つくね +つくる +つけね +つける +つごう +つたえる +つづく +つつじ +つつむ +つとめる +つながる +つなみ +つねづね +つのる +つぶす +つまらない +つまる +つみき +つめたい +つもり +つもる +つよい +つるぼ +つるみく +つわもの +つわり +てあし +てあて +てあみ +ていおん +ていか +ていき +ていけい +ていこく +ていさつ +ていし +ていせい +ていたい +ていど +ていねい +ていひょう +ていへん +ていぼう +てうち +ておくれ +てきとう +てくび +でこぼこ +てさぎょう +てさげ +てすり +てそう +てちがい +てちょう +てつがく +てつづき +でっぱ +てつぼう +てつや +でぬかえ +てぬき +てぬぐい +てのひら +てはい +てぶくろ +てふだ +てほどき +てほん +てまえ +てまきずし +てみじか +てみやげ +てらす +てれび +てわけ +てわたし +でんあつ +てんいん +てんかい +てんき +てんぐ +てんけん +てんごく +てんさい +てんし +てんすう +でんち +てんてき +てんとう +てんない +てんぷら +てんぼうだい +てんめつ +てんらんかい +でんりょく +でんわ +どあい +といれ +どうかん +とうきゅう +どうぐ +とうし +とうむぎ +とおい +とおか +とおく +とおす +とおる +とかい +とかす +ときおり +ときどき +とくい +とくしゅう +とくてん +とくに +とくべつ +とけい +とける +とこや +とさか +としょかん +とそう +とたん +とちゅう +とっきゅう +とっくん +とつぜん +とつにゅう +とどける +ととのえる +とない +となえる +となり +とのさま +とばす +どぶがわ +とほう +とまる +とめる +ともだち +ともる +どようび +とらえる +とんかつ +どんぶり +ないかく +ないこう +ないしょ +ないす +ないせん +ないそう +なおす +ながい +なくす +なげる +なこうど +なさけ +なたでここ +なっとう +なつやすみ +ななおし +なにごと +なにもの +なにわ +なのか +なふだ +なまいき +なまえ +なまみ +なみだ +なめらか +なめる +なやむ +ならう +ならび +ならぶ +なれる +なわとび +なわばり +にあう +にいがた +にうけ +におい +にかい +にがて +にきび +にくしみ +にくまん +にげる +にさんかたんそ +にしき +にせもの +にちじょう +にちようび +にっか +にっき +にっけい +にっこう +にっさん +にっしょく +にっすう +にっせき +にってい +になう +にほん +にまめ +にもつ +にやり +にゅういん +にりんしゃ +にわとり +にんい +にんか +にんき +にんげん +にんしき +にんずう +にんそう +にんたい +にんち +にんてい +にんにく +にんぷ +にんまり +にんむ +にんめい +にんよう +ぬいくぎ +ぬかす +ぬぐいとる +ぬぐう +ぬくもり +ぬすむ +ぬまえび +ぬめり +ぬらす +ぬんちゃく +ねあげ +ねいき +ねいる +ねいろ +ねぐせ +ねくたい +ねくら +ねこぜ +ねこむ +ねさげ +ねすごす +ねそべる +ねだん +ねつい +ねっしん +ねつぞう +ねったいぎょ +ねぶそく +ねふだ +ねぼう +ねほりはほり +ねまき +ねまわし +ねみみ +ねむい +ねむたい +ねもと +ねらう +ねわざ +ねんいり +ねんおし +ねんかん +ねんきん +ねんぐ +ねんざ +ねんし +ねんちゃく +ねんど +ねんぴ +ねんぶつ +ねんまつ +ねんりょう +ねんれい +のいず +のおづま +のがす +のきなみ +のこぎり +のこす +のこる +のせる +のぞく +のぞむ +のたまう +のちほど +のっく +のばす +のはら +のべる +のぼる +のみもの +のやま +のらいぬ +のらねこ +のりもの +のりゆき +のれん +のんき +ばあい +はあく +ばあさん +ばいか +ばいく +はいけん +はいご +はいしん +はいすい +はいせん +はいそう +はいち +ばいばい +はいれつ +はえる +はおる +はかい +ばかり +はかる +はくしゅ +はけん +はこぶ +はさみ +はさん +はしご +ばしょ +はしる +はせる +ぱそこん +はそん +はたん +はちみつ +はつおん +はっかく +はづき +はっきり +はっくつ +はっけん +はっこう +はっさん +はっしん +はったつ +はっちゅう +はってん +はっぴょう +はっぽう +はなす +はなび +はにかむ +はぶらし +はみがき +はむかう +はめつ +はやい +はやし +はらう +はろうぃん +はわい +はんい +はんえい +はんおん +はんかく +はんきょう +ばんぐみ +はんこ +はんしゃ +はんすう +はんだん +ぱんち +ぱんつ +はんてい +はんとし +はんのう +はんぱ +はんぶん +はんぺん +はんぼうき +はんめい +はんらん +はんろん +ひいき +ひうん +ひえる +ひかく +ひかり +ひかる +ひかん +ひくい +ひけつ +ひこうき +ひこく +ひさい +ひさしぶり +ひさん +びじゅつかん +ひしょ +ひそか +ひそむ +ひたむき +ひだり +ひたる +ひつぎ +ひっこし +ひっし +ひつじゅひん +ひっす +ひつぜん +ぴったり +ぴっちり +ひつよう +ひてい +ひとごみ +ひなまつり +ひなん +ひねる +ひはん +ひびく +ひひょう +ひほう +ひまわり +ひまん +ひみつ +ひめい +ひめじし +ひやけ +ひやす +ひよう +びょうき +ひらがな +ひらく +ひりつ +ひりょう +ひるま +ひるやすみ +ひれい +ひろい +ひろう +ひろき +ひろゆき +ひんかく +ひんけつ +ひんこん +ひんしゅ +ひんそう +ぴんち +ひんぱん +びんぼう +ふあん +ふいうち +ふうけい +ふうせん +ぷうたろう +ふうとう +ふうふ +ふえる +ふおん +ふかい +ふきん +ふくざつ +ふくぶくろ +ふこう +ふさい +ふしぎ +ふじみ +ふすま +ふせい +ふせぐ +ふそく +ぶたにく +ふたん +ふちょう +ふつう +ふつか +ふっかつ +ふっき +ふっこく +ぶどう +ふとる +ふとん +ふのう +ふはい +ふひょう +ふへん +ふまん +ふみん +ふめつ +ふめん +ふよう +ふりこ +ふりる +ふるい +ふんいき +ぶんがく +ぶんぐ +ふんしつ +ぶんせき +ふんそう +ぶんぽう +へいあん +へいおん +へいがい +へいき +へいげん +へいこう +へいさ +へいしゃ +へいせつ +へいそ +へいたく +へいてん +へいねつ +へいわ +へきが +へこむ +べにいろ +べにしょうが +へらす +へんかん +べんきょう +べんごし +へんさい +へんたい +べんり +ほあん +ほいく +ぼうぎょ +ほうこく +ほうそう +ほうほう +ほうもん +ほうりつ +ほえる +ほおん +ほかん +ほきょう +ぼきん +ほくろ +ほけつ +ほけん +ほこう +ほこる +ほしい +ほしつ +ほしゅ +ほしょう +ほせい +ほそい +ほそく +ほたて +ほたる +ぽちぶくろ +ほっきょく +ほっさ +ほったん +ほとんど +ほめる +ほんい +ほんき +ほんけ +ほんしつ +ほんやく +まいにち +まかい +まかせる +まがる +まける +まこと +まさつ +まじめ +ますく +まぜる +まつり +まとめ +まなぶ +まぬけ +まねく +まほう +まもる +まゆげ +まよう +まろやか +まわす +まわり +まわる +まんが +まんきつ +まんぞく +まんなか +みいら +みうち +みえる +みがく +みかた +みかん +みけん +みこん +みじかい +みすい +みすえる +みせる +みっか +みつかる +みつける +みてい +みとめる +みなと +みなみかさい +みねらる +みのう +みのがす +みほん +みもと +みやげ +みらい +みりょく +みわく +みんか +みんぞく +むいか +むえき +むえん +むかい +むかう +むかえ +むかし +むぎちゃ +むける +むげん +むさぼる +むしあつい +むしば +むじゅん +むしろ +むすう +むすこ +むすぶ +むすめ +むせる +むせん +むちゅう +むなしい +むのう +むやみ +むよう +むらさき +むりょう +むろん +めいあん +めいうん +めいえん +めいかく +めいきょく +めいさい +めいし +めいそう +めいぶつ +めいれい +めいわく +めぐまれる +めざす +めした +めずらしい +めだつ +めまい +めやす +めんきょ +めんせき +めんどう +もうしあげる +もうどうけん +もえる +もくし +もくてき +もくようび +もちろん +もどる +もらう +もんく +もんだい +やおや +やける +やさい +やさしい +やすい +やすたろう +やすみ +やせる +やそう +やたい +やちん +やっと +やっぱり +やぶる +やめる +ややこしい +やよい +やわらかい +ゆうき +ゆうびんきょく +ゆうべ +ゆうめい +ゆけつ +ゆしゅつ +ゆせん +ゆそう +ゆたか +ゆちゃく +ゆでる +ゆにゅう +ゆびわ +ゆらい +ゆれる +ようい +ようか +ようきゅう +ようじ +ようす +ようちえん +よかぜ +よかん +よきん +よくせい +よくぼう +よけい +よごれる +よさん +よしゅう +よそう +よそく +よっか +よてい +よどがわく +よねつ +よやく +よゆう +よろこぶ +よろしい +らいう +らくがき +らくご +らくさつ +らくだ +らしんばん +らせん +らぞく +らたい +らっか +られつ +りえき +りかい +りきさく +りきせつ +りくぐん +りくつ +りけん +りこう +りせい +りそう +りそく +りてん +りねん +りゆう +りゅうがく +りよう +りょうり +りょかん +りょくちゃ +りょこう +りりく +りれき +りろん +りんご +るいけい +るいさい +るいじ +るいせき +るすばん +るりがわら +れいかん +れいぎ +れいせい +れいぞうこ +れいとう +れいぼう +れきし +れきだい +れんあい +れんけい +れんこん +れんさい +れんしゅう +れんぞく +れんらく +ろうか +ろうご +ろうじん +ろうそく +ろくが +ろこつ +ろじうら +ろしゅつ +ろせん +ろてん +ろめん +ろれつ +ろんぎ +ろんぱ +ろんぶん +ろんり +わかす +わかめ +わかやま +わかれる +わしつ +わじまし +わすれもの +わらう +われる diff --git a/keys/wordlist/spanish.txt b/keys/wordlist/spanish.txt new file mode 100644 index 000000000..d0900c2c7 --- /dev/null +++ b/keys/wordlist/spanish.txt @@ -0,0 +1,2048 @@ +ábaco +abdomen +abeja +abierto +abogado +abono +aborto +abrazo +abrir +abuelo +abuso +acabar +academia +acceso +acción +aceite +acelga +acento +aceptar +ácido +aclarar +acné +acoger +acoso +activo +acto +actriz +actuar +acudir +acuerdo +acusar +adicto +admitir +adoptar +adorno +aduana +adulto +aéreo +afectar +afición +afinar +afirmar +ágil +agitar +agonía +agosto +agotar +agregar +agrio +agua +agudo +águila +aguja +ahogo +ahorro +aire +aislar +ajedrez +ajeno +ajuste +alacrán +alambre +alarma +alba +álbum +alcalde +aldea +alegre +alejar +alerta +aleta +alfiler +alga +algodón +aliado +aliento +alivio +alma +almeja +almíbar +altar +alteza +altivo +alto +altura +alumno +alzar +amable +amante +amapola +amargo +amasar +ámbar +ámbito +ameno +amigo +amistad +amor +amparo +amplio +ancho +anciano +ancla +andar +andén +anemia +ángulo +anillo +ánimo +anís +anotar +antena +antiguo +antojo +anual +anular +anuncio +añadir +añejo +año +apagar +aparato +apetito +apio +aplicar +apodo +aporte +apoyo +aprender +aprobar +apuesta +apuro +arado +araña +arar +árbitro +árbol +arbusto +archivo +arco +arder +ardilla +arduo +área +árido +aries +armonía +arnés +aroma +arpa +arpón +arreglo +arroz +arruga +arte +artista +asa +asado +asalto +ascenso +asegurar +aseo +asesor +asiento +asilo +asistir +asno +asombro +áspero +astilla +astro +astuto +asumir +asunto +atajo +ataque +atar +atento +ateo +ático +atleta +átomo +atraer +atroz +atún +audaz +audio +auge +aula +aumento +ausente +autor +aval +avance +avaro +ave +avellana +avena +avestruz +avión +aviso +ayer +ayuda +ayuno +azafrán +azar +azote +azúcar +azufre +azul +baba +babor +bache +bahía +baile +bajar +balanza +balcón +balde +bambú +banco +banda +baño +barba +barco +barniz +barro +báscula +bastón +basura +batalla +batería +batir +batuta +baúl +bazar +bebé +bebida +bello +besar +beso +bestia +bicho +bien +bingo +blanco +bloque +blusa +boa +bobina +bobo +boca +bocina +boda +bodega +boina +bola +bolero +bolsa +bomba +bondad +bonito +bono +bonsái +borde +borrar +bosque +bote +botín +bóveda +bozal +bravo +brazo +brecha +breve +brillo +brinco +brisa +broca +broma +bronce +brote +bruja +brusco +bruto +buceo +bucle +bueno +buey +bufanda +bufón +búho +buitre +bulto +burbuja +burla +burro +buscar +butaca +buzón +caballo +cabeza +cabina +cabra +cacao +cadáver +cadena +caer +café +caída +caimán +caja +cajón +cal +calamar +calcio +caldo +calidad +calle +calma +calor +calvo +cama +cambio +camello +camino +campo +cáncer +candil +canela +canguro +canica +canto +caña +cañón +caoba +caos +capaz +capitán +capote +captar +capucha +cara +carbón +cárcel +careta +carga +cariño +carne +carpeta +carro +carta +casa +casco +casero +caspa +castor +catorce +catre +caudal +causa +cazo +cebolla +ceder +cedro +celda +célebre +celoso +célula +cemento +ceniza +centro +cerca +cerdo +cereza +cero +cerrar +certeza +césped +cetro +chacal +chaleco +champú +chancla +chapa +charla +chico +chiste +chivo +choque +choza +chuleta +chupar +ciclón +ciego +cielo +cien +cierto +cifra +cigarro +cima +cinco +cine +cinta +ciprés +circo +ciruela +cisne +cita +ciudad +clamor +clan +claro +clase +clave +cliente +clima +clínica +cobre +cocción +cochino +cocina +coco +código +codo +cofre +coger +cohete +cojín +cojo +cola +colcha +colegio +colgar +colina +collar +colmo +columna +combate +comer +comida +cómodo +compra +conde +conejo +conga +conocer +consejo +contar +copa +copia +corazón +corbata +corcho +cordón +corona +correr +coser +cosmos +costa +cráneo +cráter +crear +crecer +creído +crema +cría +crimen +cripta +crisis +cromo +crónica +croqueta +crudo +cruz +cuadro +cuarto +cuatro +cubo +cubrir +cuchara +cuello +cuento +cuerda +cuesta +cueva +cuidar +culebra +culpa +culto +cumbre +cumplir +cuna +cuneta +cuota +cupón +cúpula +curar +curioso +curso +curva +cutis +dama +danza +dar +dardo +dátil +deber +débil +década +decir +dedo +defensa +definir +dejar +delfín +delgado +delito +demora +denso +dental +deporte +derecho +derrota +desayuno +deseo +desfile +desnudo +destino +desvío +detalle +detener +deuda +día +diablo +diadema +diamante +diana +diario +dibujo +dictar +diente +dieta +diez +difícil +digno +dilema +diluir +dinero +directo +dirigir +disco +diseño +disfraz +diva +divino +doble +doce +dolor +domingo +don +donar +dorado +dormir +dorso +dos +dosis +dragón +droga +ducha +duda +duelo +dueño +dulce +dúo +duque +durar +dureza +duro +ébano +ebrio +echar +eco +ecuador +edad +edición +edificio +editor +educar +efecto +eficaz +eje +ejemplo +elefante +elegir +elemento +elevar +elipse +élite +elixir +elogio +eludir +embudo +emitir +emoción +empate +empeño +empleo +empresa +enano +encargo +enchufe +encía +enemigo +enero +enfado +enfermo +engaño +enigma +enlace +enorme +enredo +ensayo +enseñar +entero +entrar +envase +envío +época +equipo +erizo +escala +escena +escolar +escribir +escudo +esencia +esfera +esfuerzo +espada +espejo +espía +esposa +espuma +esquí +estar +este +estilo +estufa +etapa +eterno +ética +etnia +evadir +evaluar +evento +evitar +exacto +examen +exceso +excusa +exento +exigir +exilio +existir +éxito +experto +explicar +exponer +extremo +fábrica +fábula +fachada +fácil +factor +faena +faja +falda +fallo +falso +faltar +fama +familia +famoso +faraón +farmacia +farol +farsa +fase +fatiga +fauna +favor +fax +febrero +fecha +feliz +feo +feria +feroz +fértil +fervor +festín +fiable +fianza +fiar +fibra +ficción +ficha +fideo +fiebre +fiel +fiera +fiesta +figura +fijar +fijo +fila +filete +filial +filtro +fin +finca +fingir +finito +firma +flaco +flauta +flecha +flor +flota +fluir +flujo +flúor +fobia +foca +fogata +fogón +folio +folleto +fondo +forma +forro +fortuna +forzar +fosa +foto +fracaso +frágil +franja +frase +fraude +freír +freno +fresa +frío +frito +fruta +fuego +fuente +fuerza +fuga +fumar +función +funda +furgón +furia +fusil +fútbol +futuro +gacela +gafas +gaita +gajo +gala +galería +gallo +gamba +ganar +gancho +ganga +ganso +garaje +garza +gasolina +gastar +gato +gavilán +gemelo +gemir +gen +género +genio +gente +geranio +gerente +germen +gesto +gigante +gimnasio +girar +giro +glaciar +globo +gloria +gol +golfo +goloso +golpe +goma +gordo +gorila +gorra +gota +goteo +gozar +grada +gráfico +grano +grasa +gratis +grave +grieta +grillo +gripe +gris +grito +grosor +grúa +grueso +grumo +grupo +guante +guapo +guardia +guerra +guía +guiño +guion +guiso +guitarra +gusano +gustar +haber +hábil +hablar +hacer +hacha +hada +hallar +hamaca +harina +haz +hazaña +hebilla +hebra +hecho +helado +helio +hembra +herir +hermano +héroe +hervir +hielo +hierro +hígado +higiene +hijo +himno +historia +hocico +hogar +hoguera +hoja +hombre +hongo +honor +honra +hora +hormiga +horno +hostil +hoyo +hueco +huelga +huerta +hueso +huevo +huida +huir +humano +húmedo +humilde +humo +hundir +huracán +hurto +icono +ideal +idioma +ídolo +iglesia +iglú +igual +ilegal +ilusión +imagen +imán +imitar +impar +imperio +imponer +impulso +incapaz +índice +inerte +infiel +informe +ingenio +inicio +inmenso +inmune +innato +insecto +instante +interés +íntimo +intuir +inútil +invierno +ira +iris +ironía +isla +islote +jabalí +jabón +jamón +jarabe +jardín +jarra +jaula +jazmín +jefe +jeringa +jinete +jornada +joroba +joven +joya +juerga +jueves +juez +jugador +jugo +juguete +juicio +junco +jungla +junio +juntar +júpiter +jurar +justo +juvenil +juzgar +kilo +koala +labio +lacio +lacra +lado +ladrón +lagarto +lágrima +laguna +laico +lamer +lámina +lámpara +lana +lancha +langosta +lanza +lápiz +largo +larva +lástima +lata +látex +latir +laurel +lavar +lazo +leal +lección +leche +lector +leer +legión +legumbre +lejano +lengua +lento +leña +león +leopardo +lesión +letal +letra +leve +leyenda +libertad +libro +licor +líder +lidiar +lienzo +liga +ligero +lima +límite +limón +limpio +lince +lindo +línea +lingote +lino +linterna +líquido +liso +lista +litera +litio +litro +llaga +llama +llanto +llave +llegar +llenar +llevar +llorar +llover +lluvia +lobo +loción +loco +locura +lógica +logro +lombriz +lomo +lonja +lote +lucha +lucir +lugar +lujo +luna +lunes +lupa +lustro +luto +luz +maceta +macho +madera +madre +maduro +maestro +mafia +magia +mago +maíz +maldad +maleta +malla +malo +mamá +mambo +mamut +manco +mando +manejar +manga +maniquí +manjar +mano +manso +manta +mañana +mapa +máquina +mar +marco +marea +marfil +margen +marido +mármol +marrón +martes +marzo +masa +máscara +masivo +matar +materia +matiz +matriz +máximo +mayor +mazorca +mecha +medalla +medio +médula +mejilla +mejor +melena +melón +memoria +menor +mensaje +mente +menú +mercado +merengue +mérito +mes +mesón +meta +meter +método +metro +mezcla +miedo +miel +miembro +miga +mil +milagro +militar +millón +mimo +mina +minero +mínimo +minuto +miope +mirar +misa +miseria +misil +mismo +mitad +mito +mochila +moción +moda +modelo +moho +mojar +molde +moler +molino +momento +momia +monarca +moneda +monja +monto +moño +morada +morder +moreno +morir +morro +morsa +mortal +mosca +mostrar +motivo +mover +móvil +mozo +mucho +mudar +mueble +muela +muerte +muestra +mugre +mujer +mula +muleta +multa +mundo +muñeca +mural +muro +músculo +museo +musgo +música +muslo +nácar +nación +nadar +naipe +naranja +nariz +narrar +nasal +natal +nativo +natural +náusea +naval +nave +navidad +necio +néctar +negar +negocio +negro +neón +nervio +neto +neutro +nevar +nevera +nicho +nido +niebla +nieto +niñez +niño +nítido +nivel +nobleza +noche +nómina +noria +norma +norte +nota +noticia +novato +novela +novio +nube +nuca +núcleo +nudillo +nudo +nuera +nueve +nuez +nulo +número +nutria +oasis +obeso +obispo +objeto +obra +obrero +observar +obtener +obvio +oca +ocaso +océano +ochenta +ocho +ocio +ocre +octavo +octubre +oculto +ocupar +ocurrir +odiar +odio +odisea +oeste +ofensa +oferta +oficio +ofrecer +ogro +oído +oír +ojo +ola +oleada +olfato +olivo +olla +olmo +olor +olvido +ombligo +onda +onza +opaco +opción +ópera +opinar +oponer +optar +óptica +opuesto +oración +orador +oral +órbita +orca +orden +oreja +órgano +orgía +orgullo +oriente +origen +orilla +oro +orquesta +oruga +osadía +oscuro +osezno +oso +ostra +otoño +otro +oveja +óvulo +óxido +oxígeno +oyente +ozono +pacto +padre +paella +página +pago +país +pájaro +palabra +palco +paleta +pálido +palma +paloma +palpar +pan +panal +pánico +pantera +pañuelo +papá +papel +papilla +paquete +parar +parcela +pared +parir +paro +párpado +parque +párrafo +parte +pasar +paseo +pasión +paso +pasta +pata +patio +patria +pausa +pauta +pavo +payaso +peatón +pecado +pecera +pecho +pedal +pedir +pegar +peine +pelar +peldaño +pelea +peligro +pellejo +pelo +peluca +pena +pensar +peñón +peón +peor +pepino +pequeño +pera +percha +perder +pereza +perfil +perico +perla +permiso +perro +persona +pesa +pesca +pésimo +pestaña +pétalo +petróleo +pez +pezuña +picar +pichón +pie +piedra +pierna +pieza +pijama +pilar +piloto +pimienta +pino +pintor +pinza +piña +piojo +pipa +pirata +pisar +piscina +piso +pista +pitón +pizca +placa +plan +plata +playa +plaza +pleito +pleno +plomo +pluma +plural +pobre +poco +poder +podio +poema +poesía +poeta +polen +policía +pollo +polvo +pomada +pomelo +pomo +pompa +poner +porción +portal +posada +poseer +posible +poste +potencia +potro +pozo +prado +precoz +pregunta +premio +prensa +preso +previo +primo +príncipe +prisión +privar +proa +probar +proceso +producto +proeza +profesor +programa +prole +promesa +pronto +propio +próximo +prueba +público +puchero +pudor +pueblo +puerta +puesto +pulga +pulir +pulmón +pulpo +pulso +puma +punto +puñal +puño +pupa +pupila +puré +quedar +queja +quemar +querer +queso +quieto +química +quince +quitar +rábano +rabia +rabo +ración +radical +raíz +rama +rampa +rancho +rango +rapaz +rápido +rapto +rasgo +raspa +rato +rayo +raza +razón +reacción +realidad +rebaño +rebote +recaer +receta +rechazo +recoger +recreo +recto +recurso +red +redondo +reducir +reflejo +reforma +refrán +refugio +regalo +regir +regla +regreso +rehén +reino +reír +reja +relato +relevo +relieve +relleno +reloj +remar +remedio +remo +rencor +rendir +renta +reparto +repetir +reposo +reptil +res +rescate +resina +respeto +resto +resumen +retiro +retorno +retrato +reunir +revés +revista +rey +rezar +rico +riego +rienda +riesgo +rifa +rígido +rigor +rincón +riñón +río +riqueza +risa +ritmo +rito +rizo +roble +roce +rociar +rodar +rodeo +rodilla +roer +rojizo +rojo +romero +romper +ron +ronco +ronda +ropa +ropero +rosa +rosca +rostro +rotar +rubí +rubor +rudo +rueda +rugir +ruido +ruina +ruleta +rulo +rumbo +rumor +ruptura +ruta +rutina +sábado +saber +sabio +sable +sacar +sagaz +sagrado +sala +saldo +salero +salir +salmón +salón +salsa +salto +salud +salvar +samba +sanción +sandía +sanear +sangre +sanidad +sano +santo +sapo +saque +sardina +sartén +sastre +satán +sauna +saxofón +sección +seco +secreto +secta +sed +seguir +seis +sello +selva +semana +semilla +senda +sensor +señal +señor +separar +sepia +sequía +ser +serie +sermón +servir +sesenta +sesión +seta +setenta +severo +sexo +sexto +sidra +siesta +siete +siglo +signo +sílaba +silbar +silencio +silla +símbolo +simio +sirena +sistema +sitio +situar +sobre +socio +sodio +sol +solapa +soldado +soledad +sólido +soltar +solución +sombra +sondeo +sonido +sonoro +sonrisa +sopa +soplar +soporte +sordo +sorpresa +sorteo +sostén +sótano +suave +subir +suceso +sudor +suegra +suelo +sueño +suerte +sufrir +sujeto +sultán +sumar +superar +suplir +suponer +supremo +sur +surco +sureño +surgir +susto +sutil +tabaco +tabique +tabla +tabú +taco +tacto +tajo +talar +talco +talento +talla +talón +tamaño +tambor +tango +tanque +tapa +tapete +tapia +tapón +taquilla +tarde +tarea +tarifa +tarjeta +tarot +tarro +tarta +tatuaje +tauro +taza +tazón +teatro +techo +tecla +técnica +tejado +tejer +tejido +tela +teléfono +tema +temor +templo +tenaz +tender +tener +tenis +tenso +teoría +terapia +terco +término +ternura +terror +tesis +tesoro +testigo +tetera +texto +tez +tibio +tiburón +tiempo +tienda +tierra +tieso +tigre +tijera +tilde +timbre +tímido +timo +tinta +tío +típico +tipo +tira +tirón +titán +títere +título +tiza +toalla +tobillo +tocar +tocino +todo +toga +toldo +tomar +tono +tonto +topar +tope +toque +tórax +torero +tormenta +torneo +toro +torpedo +torre +torso +tortuga +tos +tosco +toser +tóxico +trabajo +tractor +traer +tráfico +trago +traje +tramo +trance +trato +trauma +trazar +trébol +tregua +treinta +tren +trepar +tres +tribu +trigo +tripa +triste +triunfo +trofeo +trompa +tronco +tropa +trote +trozo +truco +trueno +trufa +tubería +tubo +tuerto +tumba +tumor +túnel +túnica +turbina +turismo +turno +tutor +ubicar +úlcera +umbral +unidad +unir +universo +uno +untar +uña +urbano +urbe +urgente +urna +usar +usuario +útil +utopía +uva +vaca +vacío +vacuna +vagar +vago +vaina +vajilla +vale +válido +valle +valor +válvula +vampiro +vara +variar +varón +vaso +vecino +vector +vehículo +veinte +vejez +vela +velero +veloz +vena +vencer +venda +veneno +vengar +venir +venta +venus +ver +verano +verbo +verde +vereda +verja +verso +verter +vía +viaje +vibrar +vicio +víctima +vida +vídeo +vidrio +viejo +viernes +vigor +vil +villa +vinagre +vino +viñedo +violín +viral +virgo +virtud +visor +víspera +vista +vitamina +viudo +vivaz +vivero +vivir +vivo +volcán +volumen +volver +voraz +votar +voto +voz +vuelo +vulgar +yacer +yate +yegua +yema +yerno +yeso +yodo +yoga +yogur +zafiro +zanja +zapato +zarza +zona +zorro +zumo +zurdo From daab270ff71646ded0dc8337021aa2fa8814079d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 17:02:28 +0200 Subject: [PATCH 093/273] First obvious speedup --- keys/wordcodec.go | 14 +++++++------- keys/wordcodec_test.go | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/keys/wordcodec.go b/keys/wordcodec.go index 5ac32f812..d4c7bce2a 100644 --- a/keys/wordcodec.go +++ b/keys/wordcodec.go @@ -24,14 +24,14 @@ type WordCodec struct { check ECC } -var _ Codec = WordCodec{} +var _ Codec = &WordCodec{} -func NewCodec(words []string) (codec WordCodec, err error) { +func NewCodec(words []string) (codec *WordCodec, err error) { if len(words) != BankSize { return codec, errors.Errorf("Bank must have %d words, found %d", BankSize, len(words)) } - res := WordCodec{ + res := &WordCodec{ words: words, // TODO: configure this outside??? check: NewIEEECRC32(), @@ -40,7 +40,7 @@ func NewCodec(words []string) (codec WordCodec, err error) { return res, nil } -func LoadCodec(bank string) (codec WordCodec, err error) { +func LoadCodec(bank string) (codec *WordCodec, err error) { words, err := loadBank(bank) if err != nil { return codec, err @@ -96,7 +96,7 @@ func bytelenFromWords(numWords int) (length int, maybeShorter bool) { } // TODO: add checksum -func (c WordCodec) BytesToWords(raw []byte) (words []string, err error) { +func (c *WordCodec) BytesToWords(raw []byte) (words []string, err error) { // always add a checksum to the data data := c.check.AddECC(raw) numWords := wordlenFromBytes(len(data)) @@ -120,7 +120,7 @@ func (c WordCodec) BytesToWords(raw []byte) (words []string, err error) { return words, nil } -func (c WordCodec) WordsToBytes(words []string) ([]byte, error) { +func (c *WordCodec) WordsToBytes(words []string) ([]byte, error) { l := len(words) if l == 0 { @@ -167,7 +167,7 @@ func (c WordCodec) WordsToBytes(words []string) ([]byte, error) { // GetIndex finds the index of the words to create bytes // Generates a map the first time it is loaded, to avoid needless // computation when list is not used. -func (c WordCodec) GetIndex(word string) (int, error) { +func (c *WordCodec) GetIndex(word string) (int, error) { // generate the first time if c.bytes == nil { b := map[string]int{} diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index c3a5a2cac..3bdec110f 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -130,12 +130,12 @@ func TestCheckInvalidLists(t *testing.T) { } -func getRandWord(c WordCodec) string { +func getRandWord(c *WordCodec) string { idx := cmn.RandInt() % BankSize return c.words[idx] } -func getDiffWord(c WordCodec, not string) string { +func getDiffWord(c *WordCodec, not string) string { w := getRandWord(c) if w == not { w = getRandWord(c) @@ -151,7 +151,7 @@ func TestCheckTypoDetection(t *testing.T) { for _, bank := range banks { codec, err := LoadCodec(bank) require.Nil(err, "%s: %+v", bank, err) - for i := 0; i < 10; i++ { + for i := 0; i < 1000; i++ { numBytes := cmn.RandInt()%60 + 1 data := cmn.RandBytes(numBytes) @@ -177,5 +177,34 @@ func TestCheckTypoDetection(t *testing.T) { assert.NotNil(err, "%s: %s", bank, words) } } +} + +func warmupCodec(bank string) *WordCodec { + codec, err := LoadCodec(bank) + if err != nil { + panic(err) + } + _, err = codec.GetIndex(codec.words[123]) + if err != nil { + panic(err) + } + return codec +} +func BenchmarkWordGeneration(b *testing.B) { + // banks := []string{"english", "spanish", "japanese", "chinese_simplified"} + bank := "english" + + codec := warmupCodec(bank) + b.ResetTimer() + + numBytes := 32 + data := cmn.RandBytes(numBytes) + + for i := 1; i <= b.N; i++ { + _, err := codec.BytesToWords(data) + if err != nil { + panic(err) + } + } } From 1e15c8f75b599f6f3032d1c10efccd78e7bea3f3 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 17:13:10 +0200 Subject: [PATCH 094/273] Extend wordcodec benchmarks --- keys/wordcodec_test.go | 30 ---------------- keys/wordcodecbench_test.go | 68 +++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 30 deletions(-) create mode 100644 keys/wordcodecbench_test.go diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index 3bdec110f..1ae97d8a7 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -178,33 +178,3 @@ func TestCheckTypoDetection(t *testing.T) { } } } - -func warmupCodec(bank string) *WordCodec { - codec, err := LoadCodec(bank) - if err != nil { - panic(err) - } - _, err = codec.GetIndex(codec.words[123]) - if err != nil { - panic(err) - } - return codec -} - -func BenchmarkWordGeneration(b *testing.B) { - // banks := []string{"english", "spanish", "japanese", "chinese_simplified"} - bank := "english" - - codec := warmupCodec(bank) - b.ResetTimer() - - numBytes := 32 - data := cmn.RandBytes(numBytes) - - for i := 1; i <= b.N; i++ { - _, err := codec.BytesToWords(data) - if err != nil { - panic(err) - } - } -} diff --git a/keys/wordcodecbench_test.go b/keys/wordcodecbench_test.go new file mode 100644 index 000000000..e100a443a --- /dev/null +++ b/keys/wordcodecbench_test.go @@ -0,0 +1,68 @@ +package keys + +import ( + "testing" + + cmn "github.com/tendermint/tmlibs/common" +) + +func warmupCodec(bank string) *WordCodec { + codec, err := LoadCodec(bank) + if err != nil { + panic(err) + } + _, err = codec.GetIndex(codec.words[123]) + if err != nil { + panic(err) + } + return codec +} + +func BenchmarkCodec(b *testing.B) { + banks := []string{"english", "spanish", "japanese", "chinese_simplified"} + + for _, bank := range banks { + b.Run(bank, func(sub *testing.B) { + codec := warmupCodec(bank) + sub.ResetTimer() + benchSuite(sub, codec) + }) + } +} + +func benchSuite(b *testing.B, codec *WordCodec) { + b.Run("to_words", func(sub *testing.B) { + benchMakeWords(sub, codec) + }) + b.Run("to_bytes", func(sub *testing.B) { + benchParseWords(sub, codec) + }) +} + +func benchMakeWords(b *testing.B, codec *WordCodec) { + numBytes := 32 + data := cmn.RandBytes(numBytes) + for i := 1; i <= b.N; i++ { + _, err := codec.BytesToWords(data) + if err != nil { + panic(err) + } + } +} + +func benchParseWords(b *testing.B, codec *WordCodec) { + // generate a valid test string to parse + numBytes := 32 + data := cmn.RandBytes(numBytes) + words, err := codec.BytesToWords(data) + if err != nil { + panic(err) + } + + for i := 1; i <= b.N; i++ { + _, err := codec.WordsToBytes(words) + if err != nil { + panic(err) + } + } +} From 878c8b3a876286d78aa96699f122b2a490f6ba23 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 17:51:25 +0200 Subject: [PATCH 095/273] Removed obsolete file --- keys/Makefile | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 keys/Makefile diff --git a/keys/Makefile b/keys/Makefile deleted file mode 100644 index 63eb70787..000000000 --- a/keys/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -GOTOOLS = \ - github.com/mitchellh/gox \ - github.com/Masterminds/glide - -.PHONEY: all test install get_vendor_deps ensure_tools - -all: install test - -test: - go test `glide novendor` - -install: - go install ./cmd/keys - -get_vendor_deps: ensure_tools - @rm -rf vendor/ - @echo "--> Running glide install" - @glide install - -ensure_tools: - go get $(GOTOOLS) - From 56200e167a9e3158a0a3287082029e64c10807e3 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 18:03:17 +0200 Subject: [PATCH 096/273] Use go-bindata to embed wordlist in a binary --- Makefile | 8 +- keys/wordcodec.go | 40 ++--- keys/wordlist/wordlist.go | 308 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 334 insertions(+), 22 deletions(-) create mode 100644 keys/wordlist/wordlist.go diff --git a/Makefile b/Makefile index e40d0e6ff..537b6396f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ -.PHONEY: all docs test install get_vendor_deps ensure_tools codegen +.PHONEY: all docs test install get_vendor_deps ensure_tools codegen wordlist GOTOOLS = \ - github.com/Masterminds/glide + github.com/Masterminds/glide \ + github.com/jteeuwen/go-bindata/go-bindata REPO:=github.com/tendermint/go-crypto docs: @@ -35,6 +36,9 @@ get_vendor_deps: ensure_tools ensure_tools: go get $(GOTOOLS) +wordlist: + go-bindata -ignore ".*\.go" -o keys/wordlist/wordlist.go -pkg "wordlist" keys/wordlist/... + prepgen: install go install ./vendor/github.com/btcsuite/btcutil/base58 go install ./vendor/github.com/stretchr/testify/assert diff --git a/keys/wordcodec.go b/keys/wordcodec.go index d4c7bce2a..f66d1e983 100644 --- a/keys/wordcodec.go +++ b/keys/wordcodec.go @@ -1,12 +1,12 @@ package keys import ( - "io/ioutil" "math/big" - "os" "strings" "github.com/pkg/errors" + + "github.com/tendermint/go-crypto/keys/wordlist" ) const BankSize = 2048 @@ -50,30 +50,30 @@ func LoadCodec(bank string) (codec *WordCodec, err error) { // loadBank opens a wordlist file and returns all words inside func loadBank(bank string) ([]string, error) { - filename := "wordlist/" + bank + ".txt" - words, err := getData(filename) + filename := "keys/wordlist/" + bank + ".txt" + words, err := wordlist.Asset(filename) if err != nil { return nil, err } - wordsAll := strings.Split(strings.TrimSpace(words), "\n") + wordsAll := strings.Split(strings.TrimSpace(string(words)), "\n") return wordsAll, nil } -// TODO: read from go-bind assets -func getData(filename string) (string, error) { - f, err := os.Open(filename) - if err != nil { - return "", errors.WithStack(err) - } - defer f.Close() - - data, err := ioutil.ReadAll(f) - if err != nil { - return "", errors.WithStack(err) - } - - return string(data), nil -} +// // TODO: read from go-bind assets +// func getData(filename string) (string, error) { +// f, err := os.Open(filename) +// if err != nil { +// return "", errors.WithStack(err) +// } +// defer f.Close() + +// data, err := ioutil.ReadAll(f) +// if err != nil { +// return "", errors.WithStack(err) +// } + +// return string(data), nil +// } // given this many bytes, we will produce this many words func wordlenFromBytes(numBytes int) int { diff --git a/keys/wordlist/wordlist.go b/keys/wordlist/wordlist.go new file mode 100644 index 000000000..97ddb2369 --- /dev/null +++ b/keys/wordlist/wordlist.go @@ -0,0 +1,308 @@ +// Code generated by go-bindata. +// sources: +// keys/wordlist/chinese_simplified.txt +// keys/wordlist/english.txt +// keys/wordlist/japanese.txt +// keys/wordlist/spanish.txt +// DO NOT EDIT! + +package wordlist + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindataFileInfo) Name() string { + return fi.name +} +func (fi bindataFileInfo) Size() int64 { + return fi.size +} +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} +func (fi bindataFileInfo) IsDir() bool { + return false +} +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _keysWordlistChinese_simplifiedTxt = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x1c\x97\x55\x76\xeb\x30\x14\x45\xff\xf7\xa8\xc3\xcc\x49\xc3\x69\x98\xda\x86\xd9\x0e\x4c\xc6\xf7\x4a\x9a\xc5\x5b\x7e\x7f\x5d\x5d\x6d\x6c\x45\x07\xf6\x31\xdd\x04\xc1\x3d\x82\xb6\x77\x48\x7f\x45\x70\x2f\x12\x78\x29\xb4\x9f\x45\x6a\x05\x02\xcf\xc3\x7e\x3a\x04\xf7\x0d\x32\x5b\x12\xdc\x3d\x82\x7b\x8e\xe0\xfe\x83\xf4\x5e\x68\xa6\x4a\xe0\xcf\xb1\x8b\x28\x81\xdf\x44\x5b\x57\x74\x30\xc7\x34\x56\x04\xfe\x1f\xa6\x31\x44\x32\x7b\x82\x57\x1f\xe9\xef\x09\xbc\x12\x92\xf6\x90\xfd\x01\xc9\xa4\x90\xdd\x03\xcd\x54\x08\x9e\x5d\xa4\xbc\x23\xb8\xfb\x48\xb9\x8a\x3c\xce\x48\x6e\x85\x54\x0a\xc8\x6d\x4e\xf0\x18\x62\xe3\x2f\x82\x7b\x1e\xfb\x49\x23\x9b\x0a\x76\x77\x26\xf0\x96\x98\x65\x11\x37\x98\x60\x23\x05\xb4\xf9\x40\x2a\x25\x64\xd6\x45\xb6\x5d\xec\xb8\x80\x6c\x16\xe8\xe9\x0b\xcd\x46\xd0\x7d\x15\x79\xb7\x30\x7e\x19\x29\x46\x09\xee\x59\x82\x47\xf8\x99\x3d\xcc\x20\x82\xd9\x64\x71\xf1\x15\xe2\x2d\x90\xed\x15\xd3\xb8\x20\xb9\x1e\x2e\x5d\x40\x16\x31\x74\x7f\x46\x0a\x4d\xdc\x6f\x1b\x9b\xfe\x21\xf0\x0a\x98\x4a\x0a\x7b\xb9\x21\xfb\x32\x26\xbb\xc6\x94\xf6\xc8\xf6\x1b\xc9\x8d\x70\xe9\x32\xee\xff\x7b\xcf\x08\x5e\x75\x24\x73\x45\xfb\x1e\xf2\xaa\x13\xbc\x3e\x98\xd8\x83\xc0\x2f\x11\xdc\xbb\x68\xff\x0f\x29\xf9\x68\x2e\x87\x46\x96\xc8\xfc\x85\x78\x0d\xe4\x19\x41\xb6\x71\xa4\x92\xc1\x7e\xda\x48\x6f\x84\x69\x1c\x90\xe4\x95\xc0\xeb\x61\x12\x57\x24\x5b\x44\x66\x4d\x64\xb6\x46\x1b\x1f\xa4\xd7\x43\x5b\x73\x5c\x6c\x8a\x99\xbd\x09\x1e\x59\x02\x2f\x8f\x3c\x4e\xc8\x6b\x82\xe9\xdd\x91\xe4\x0a\x3b\x5e\xe1\x5a\x67\x74\x74\x23\xb8\x97\x90\xe4\x09\xa9\x24\x70\xe9\x22\xda\xdc\x63\xbc\x0f\x92\x4a\xa2\x5f\x7b\x74\x33\x45\x3e\x71\xa4\x5c\x24\x78\x8d\xd0\x76\x09\xd3\xcf\x23\xa5\x21\x52\xce\x10\x3c\x32\x48\x66\x8d\xee\x1a\x68\xa6\x49\xf0\x4a\x61\xcf\x2b\x74\xdf\xc0\xfc\xfd\x21\x95\x2a\x2e\x5a\x47\xaa\x2f\x74\x33\x43\xca\x6d\x74\x30\x46\xca\x3f\xe8\x71\x8c\xf1\xeb\xd8\xe5\x14\xd7\xda\xa2\x89\x32\xe2\x7b\x68\x3f\x83\x24\xff\xd0\xd6\x08\x73\xf2\x91\x54\x0f\x79\x67\xd0\x78\x12\x1b\x49\xa2\xfd\x08\xe6\x37\x4f\xe0\x4f\xd1\xf8\x09\xb9\x1d\x71\x91\x2e\xf2\xb8\xa2\xe5\x0a\xa6\x77\xc6\x4d\xda\x48\xb2\x8b\x59\xe5\x91\xc3\x17\x81\xd7\x40\xbf\xfb\x68\xb3\x83\x3d\x8c\x91\x6a\x1b\x37\x58\x13\xbc\x8a\x48\x72\x8e\xdc\xef\x68\x33\x8d\x46\x7c\xf4\x6f\x8c\xd4\xa3\xc8\xb3\x8c\x9e\x7d\xec\xf6\x8d\x94\x73\x98\xed\x18\x93\x0d\xef\xee\x8a\xfb\xfa\xa0\x87\x18\x36\x12\x45\x66\x67\x64\xe8\x61\x2f\x09\xec\xfb\x81\x5e\xa2\xd8\xdb\x0e\xe3\x2d\x91\x50\x7b\xbd\x37\x72\x38\x60\xfc\x21\x5a\x9a\x63\x86\x73\xec\x3b\x8e\xec\x53\x18\x3f\x81\x5d\x46\xb1\xdb\x31\x92\xf9\x45\xe6\x0f\x34\x9b\xc7\x2e\x6b\x68\x7f\x88\x8e\x1e\xd8\x6d\xe8\xc7\x0a\x92\xea\xa3\x85\x34\x92\x1e\x11\x3c\x06\x48\xc1\x43\x9e\x1e\xda\x78\x23\xa9\x13\x76\xfe\xc1\x4e\x7e\x91\xc7\x11\x89\x76\x91\x4f\x12\xcd\x84\xdf\x43\x06\xe9\x7d\x23\x99\x0e\x81\x1f\x7a\xad\x89\x16\xb7\xc8\x2c\x81\x6b\x0f\x91\x62\xe8\x8d\x0e\x36\x7b\x44\x92\x59\x5c\x6b\x85\x14\x4f\x04\x9f\x01\x7a\xf4\x91\x42\x0b\x17\x19\x61\x3a\x6f\xec\x32\x81\x89\x6f\x70\x93\x14\xc1\x3d\x8e\x86\x1e\x28\x4f\x09\xee\x7d\x64\xf7\x44\x3a\x2b\xa4\x94\x47\x3e\x2d\x82\x7b\x13\x97\xae\x22\x93\x6f\x02\x2f\x8b\x5e\x4a\xb8\xf6\x15\x3d\x3e\xd0\xc8\x00\xed\xef\xd0\xef\x28\x81\x17\xea\xa2\x85\x8d\x36\x08\xfc\x08\x76\x3b\x43\x92\x1b\x24\x79\x40\x07\x71\xb4\x71\xc5\xee\xa2\x68\xe3\x81\xde\x93\x98\x77\x09\x49\x15\x71\xe9\x34\xf6\xf5\x87\xf6\xce\x48\xf1\x0b\x37\x2d\x21\x99\x34\x9a\xad\x63\x3a\x2f\xf4\xab\x83\x8b\x0c\xb1\xb9\x03\x72\x0f\xbd\x9d\x45\xfa\x1e\xd6\xfb\xc5\xbe\x16\x04\xef\x3c\xa6\x3f\x44\x72\x63\x24\x19\x7a\x21\x8d\xee\xca\x98\xde\x16\x9b\x3e\x61\xdf\x6f\xec\x65\x8f\x59\xee\x30\x33\x0f\xbb\xdd\x22\xd3\x3d\x9a\x9b\xa3\xcd\x16\xb2\x2d\x60\x0e\x3e\x92\xfc\xc5\x2c\x7c\xa4\x58\x42\x2a\x45\xcc\x78\x8b\x66\x8b\x98\x65\x15\x79\x8e\x08\x3e\x63\xdc\xfa\x0f\x9b\x8b\x61\x77\x03\xcc\xe1\x84\x7e\x9d\x31\x6b\x0f\x49\xc6\x91\xd4\x85\xc0\xcf\xe1\x7a\x29\xf4\xbe\x26\x78\x8e\x90\xfe\x10\xbb\xbd\xa3\x9b\x39\xe6\x3d\x43\x1e\x1f\xcc\xf0\x84\xdd\xee\x71\xfd\x08\xba\xbd\x60\x46\x0d\xcc\x57\x01\xcd\x67\xd1\xef\x16\xf2\xce\x23\xe5\x5f\x82\x7b\x03\xb3\xbe\x62\x97\x31\xec\x35\x87\xf1\xd3\xd8\x69\x12\x79\x1d\x30\xdb\x16\xc1\xab\x84\x16\xa2\xb8\xe1\x89\xe0\xd9\x22\x78\x2c\x90\x7b\x1c\x99\x15\x91\xed\x03\x49\x7c\x70\x63\x1f\xd7\x49\x22\x5f\x29\xdc\xe0\x1b\xf7\x53\xc0\x7e\xbe\xd1\xe6\x06\xbd\x1d\x70\xdd\x37\xf6\x53\xc5\x0c\x3f\x48\x31\x8e\x54\x57\xc8\xb2\x81\x39\x8f\xd0\x5c\x04\x99\xa5\x91\x62\x0e\xc9\x7d\xe3\x06\x35\x4c\x3f\x8a\x64\xc2\x67\x8d\x90\x7a\x11\xe3\x2d\xd0\xc6\x0e\x9b\xf9\x43\xca\x47\x34\x11\xde\xc3\x89\xe0\x1d\xe6\xd8\x04\x79\x47\x70\xc9\x3b\x52\x4a\x21\xf7\x18\x92\xcc\x13\xbc\xbe\x70\x9d\x19\x7a\xcd\xa0\xdf\x09\xc4\xeb\x63\x96\x7b\x64\xf6\x83\xa4\x53\x98\xe3\x1b\x89\x3c\x91\xf2\x0d\x53\x4a\xa3\xad\x32\xc6\x3f\x23\x99\x1a\x2e\x92\x45\x47\x69\x24\xd5\x41\x36\x6d\x24\xd2\x41\x77\x3d\x02\xef\x88\x7c\x7e\xd1\xaf\x0c\xda\xdc\xe1\x3a\x13\x74\x38\x47\x0f\x43\xe4\x3b\xd4\xc7\x13\x53\xca\xa3\x85\xf0\xff\x9f\x48\xd2\x47\xdb\x75\xcc\x6b\x8b\x9e\x43\x5f\xc7\x30\xd9\x34\xb2\xcc\x23\xc5\x33\xc1\xbd\x8e\xc9\x5d\xb1\xb1\x23\x52\x8a\x11\x78\x7f\xd8\x5d\x0a\x17\x89\x21\x87\x6f\xa4\x9f\x42\x0a\x49\x4c\xf4\x97\xe0\x55\xc6\xee\xe3\xa8\x3f\x46\x4a\x1f\xe4\x10\xc1\x24\x97\x48\x39\x86\xf1\x26\x18\x3f\x85\x3c\xbf\x90\x4a\xf8\x19\x73\x5c\x3d\xec\xdb\x50\xa7\x73\xdc\xa2\x89\x78\x5f\xe8\xf5\x88\x6c\xdb\xc8\xfb\x86\xeb\x96\x31\xad\x24\x36\x5f\x46\x66\x07\x64\xdf\x40\x37\x61\x7e\x1d\x71\xc9\x22\x32\x3f\xe1\xfc\x04\x5a\x5a\xa1\xed\x37\x76\x9f\xc1\xbc\x7e\x30\xf3\x6f\x6c\xd6\x43\xaa\x13\x24\xec\xfc\xca\x2f\xc1\x33\x8a\xf6\x7b\xc8\x2e\x85\x66\x1f\xd8\xca\x1c\x37\x7e\xe0\xda\x47\x82\xfb\x1b\x53\x89\x63\xf3\x07\x74\xbf\x44\x72\x1f\xa4\x9a\x43\x07\x25\xa4\xbc\xc7\x56\x5e\x68\x7f\x85\xdc\xb7\xd8\xd7\x16\x33\x0a\x3b\xbb\x8b\xdc\xc3\x1c\x3a\xa3\xa7\x15\xf6\xd3\x47\x36\x2d\x74\x50\x41\x4b\x35\x82\x77\x0f\x3d\x9e\xd0\x30\x4f\xf7\x51\xa4\xbc\x40\x9b\x2f\x24\x5d\x46\x47\x55\xd4\xbb\xa2\x91\x12\xba\x99\xa0\xe3\x0c\x76\x15\x41\xa6\xbf\xc8\x20\x8d\x6e\x16\x48\xcf\x43\xca\x57\xdc\xe1\x89\x9e\x26\xd8\x65\x8a\xc0\x4f\x62\xcf\x0f\xcc\x79\x89\xc9\x1c\x90\xdb\x02\xf3\x3b\x42\x5b\x6b\xb4\x3f\x40\xb6\x27\x8c\xbf\xc1\xbe\x7c\xb4\x5f\xc4\xee\xc2\x0c\x19\x22\xc9\x24\x92\xbc\xa0\x5e\x05\xc9\xcc\xd0\x5c\x98\x4f\x77\xec\xf5\x84\x0e\x2b\x18\x3f\x8e\xdc\xc2\x8c\x38\xa3\x83\x0f\xa6\xb1\xc7\x75\x8a\x38\xbf\x8a\xc9\xed\xb0\xe7\x21\x92\xf6\xb1\x85\x38\xc6\x5f\x22\xc9\x33\xc1\xf3\x49\xf0\xea\x20\x83\x2e\xda\x3b\x62\xdf\x75\x82\xcf\x16\xfd\x4a\x22\xc3\x90\x5d\x7e\x91\xd9\x10\x17\x89\x62\xfe\x1a\xd8\xcc\x03\x29\x8e\x90\xf2\x09\x7b\x9e\x20\x95\x38\xb2\x2b\xa0\xed\x39\x36\x5a\xc0\x2e\xb3\xe8\x21\x8b\x69\xf8\x48\x6e\x88\xdc\xce\xd8\xdb\x10\x1b\xe6\xde\x20\x86\x9b\x7e\xa3\xd3\x08\x52\xb9\x23\xb9\x35\x52\x4c\xe3\xda\x27\x02\xaf\x86\x64\x06\x48\xa6\x87\xe6\x5a\xd8\x48\x1c\xcd\x7d\x21\x83\x32\x66\xd3\x44\xca\x33\xe4\x9d\x40\x8b\x13\xb4\xff\x83\xbd\x55\x31\x61\x8e\xd6\x26\x68\xef\x8d\xf9\x0d\xcf\x37\xc5\xfc\x76\x30\xdb\x08\xf6\xb3\xc7\xd5\x0e\x48\x76\x87\xec\x5f\xc8\x7d\x80\xec\x13\xd8\x62\x16\x49\x1d\xd1\xec\x07\x93\xff\x23\xf0\x67\xb8\x4e\x05\xd7\xfe\x20\xdb\x29\xa6\xb4\x43\xca\x05\xec\xee\x86\xbd\x26\x91\xf7\x16\xbb\x5d\xa3\xa5\x25\x72\x0b\xf5\xb8\xc3\xbe\xce\x68\xf6\x8d\x54\x16\x18\xef\x07\xd3\xcb\x11\xbc\x07\x04\xcf\x36\x6e\x7c\xc5\x8c\x23\xd8\xd7\x0b\x89\xd4\xd0\xcc\x07\xf3\x13\x45\x06\x15\xcc\x31\x8b\x7e\x15\x30\x5f\x73\x64\x3b\xc1\x4e\xa2\x48\xea\x86\x8d\xf7\x31\xfe\x00\xfd\xae\x20\x83\x16\x92\x8d\xa1\x97\x3c\x41\xf8\xce\xc5\x32\x76\x97\x45\x3e\x17\x5c\x27\x43\xe0\x17\x31\xaf\x16\xa6\x57\x41\xca\x79\xf4\x9c\xc7\x35\x3a\xd8\xfc\x02\x99\xf5\x91\x4c\x15\xb3\xf4\x71\x93\x2a\x2e\x52\xc1\x0d\x46\xe8\xed\x86\xee\x8a\x98\xe1\x06\xd3\xdd\x62\xfc\x0c\x36\xda\x45\x0f\xe1\x9d\x54\x09\xbc\x2a\x52\xff\x41\x5b\x13\xec\x2d\x7c\xe6\x2f\x12\xed\x63\xe2\x19\x64\xb6\x45\x76\x43\x4c\x7c\x89\xfd\x24\x91\x49\xe8\xaf\x39\x52\xdc\xa3\xe7\x23\x92\xf1\xd1\xfc\x1f\xfa\x89\x20\x9b\x06\x5a\xf9\xc6\x34\x42\xde\x0d\xef\x2b\x89\x8e\xee\xe8\x68\x8c\x7e\x4d\x09\xde\x17\xa4\xb2\xc4\x34\x8e\xe8\xfd\x4e\xf0\x48\x62\xcb\x7d\xa4\x7a\x42\x5b\x4b\x74\x35\x46\x1f\x4d\xec\x79\x89\x16\x87\xb8\x49\xc8\x01\x3e\xba\xfb\x45\x3b\x5b\xcc\xea\x44\xf0\xe8\x20\x8b\x0c\x3a\x2b\xa2\xd1\x1d\x9a\x5d\xe3\xea\x61\x0f\x6f\xd0\xc2\x1c\x97\xac\x21\xdb\x0c\x9a\xff\x20\x5e\x19\xe3\xdd\x91\x82\x8f\x79\x7a\xb8\x5e\xc8\xf0\x2d\x5c\x2d\x64\xc3\x36\xf2\x15\xb2\xed\x1c\x69\x1c\xb0\xbb\x1d\x76\xbb\x41\x13\xa1\x0e\xc6\xb8\x4e\x02\x5b\xba\x61\x0b\x57\xdc\xb1\x8f\x39\x6e\xd1\xe6\x0c\xd9\xac\xb1\x89\x03\x66\xfc\x8b\x8d\xcd\x91\x66\x02\xf7\xee\xa0\xcf\x06\x26\xe4\xe9\x7b\x05\x3b\x8e\xa0\x7f\x13\x74\xb2\x47\x4b\x05\x74\x53\x40\x8f\x1d\x24\xd3\x45\x1b\x3e\x76\x5f\xc7\xf4\xde\xd8\xed\x0a\xed\x74\x31\xc7\x1a\xc1\xe3\x80\x49\xc7\x31\xc3\x1e\xc1\xa3\x84\x0e\x22\xd8\xe2\x0e\xd9\x46\x71\xc7\x28\xf6\x7c\xc1\xd5\x86\x98\xe4\x0c\xbb\xf3\x31\xe5\x0d\xc1\x73\x87\x5b\x84\xec\x14\x6e\x86\x5f\xa4\x3c\x27\xb8\xef\x91\xe1\x03\x2d\x87\xec\xb0\x47\xf3\x49\xe4\xb9\xc0\xf6\xf2\xe8\x31\x8b\x44\xd3\x98\xf5\x07\xcd\x2e\x31\x9b\x06\xc1\xa3\x82\xdd\x47\x71\x63\x0f\x13\x1f\x62\x9e\x6b\xe4\x1d\xc5\x26\xee\x48\xb3\x8f\x0e\xde\xd8\x44\x17\xe9\xed\x91\x67\xd8\x77\x45\x6c\x3c\xf4\xfb\x10\xb3\x28\x13\x3c\xf6\xe8\xb0\x4e\x10\x66\x7e\xb8\x49\x92\x13\x34\xf2\x85\x99\x46\x91\x48\x11\x33\x6f\x62\xba\x69\x82\x4f\x1c\x37\xe8\x60\xc7\x73\xec\x2e\x81\xf9\xf8\xd8\x58\x16\x7b\xbb\x20\xfb\x27\x76\x3c\x45\xb6\x2f\x34\xfb\x87\x4e\xb3\xc8\xbd\x40\xf0\x9c\xa1\xf5\x22\xf2\x1d\xc3\x84\x3d\xb6\xed\xa3\xfb\x09\x32\x6f\x61\x06\x53\xb4\x10\x72\x5a\xb8\x3b\xb6\x68\xff\x17\xd9\xfe\x20\x5e\x0a\xf3\x6c\x62\xb2\x3d\xec\x72\x81\xb6\x47\xb8\xde\x0d\xd7\x88\x60\x77\x2d\x24\x64\xdf\x43\x12\xcd\xd5\xb1\xd3\x18\x36\xfe\x8d\x54\x9f\xc8\xaa\x8d\x76\x76\xc8\x2a\x8a\xf1\x3f\x68\xe7\x8a\x94\xba\x98\xde\x10\x3b\x1e\xe3\xee\x63\x64\xd3\x41\xfc\x2b\x52\x3c\x60\xe3\x57\xe4\x90\x27\x78\x8c\x09\xee\x67\x5c\x27\x85\x1b\xbf\xd1\x52\x16\xa9\x46\x30\xd1\x1d\x72\x8c\xa2\xa5\x1f\x74\x30\xc4\x46\x2a\x48\xf8\x9d\x97\xb2\xd8\xcb\x05\x7b\x3b\x21\xf5\x39\xb2\x99\x62\x77\x6f\x24\xbd\xc3\xc6\xc7\xb8\xc9\x00\xfd\x7b\x63\xfc\x22\x52\xbc\xe1\x5e\xe1\x1e\x1d\x62\x6b\x77\x74\xdb\x44\xf7\x77\x64\xdb\xc2\xe6\x5b\xc8\x6d\x80\x89\x65\x91\xe3\x1a\x79\x1e\x70\xbd\x70\xef\xae\x90\x79\x19\x3d\x7e\x70\xfd\x23\x3a\x48\xa1\xa5\x09\xea\x57\x71\x5f\x69\xdc\x7c\x83\x5e\xea\xd8\xcc\x0f\x1a\x89\x60\x2f\x57\xc4\xab\x23\x33\x8f\xe0\x99\xc3\x44\x2f\x98\x55\x09\x17\x69\x60\xa2\x1b\xec\xa5\x87\xbc\x6a\x48\xf9\x0f\xf7\xac\xa3\xb5\x0d\xa6\xd7\xc6\x4e\xa3\xb8\xce\x1a\xf1\x6e\x48\x63\x87\xbc\xbe\xb0\xe5\x02\xc6\xdb\x21\x91\x21\xe6\xd4\xc4\xf4\x9a\xe8\xea\x07\xf3\xb7\xc0\x2c\xa3\x48\xee\x07\x19\xc5\x90\xe1\x10\xfd\xfe\x41\xaf\x0b\xe4\x91\x44\xea\x19\xcc\xef\x10\x93\x0a\x7b\xe2\x17\x3d\xbd\xb0\x89\x2a\x32\x9d\x61\x26\x27\xf4\x6f\x89\x8b\x16\x09\xde\x4b\x64\xb7\x42\xbf\x26\xc8\xcb\xc7\x76\xaa\x68\xb3\x8f\x6d\x86\xcc\xb5\xc1\x78\x27\xe4\xf9\xc0\xcd\x8f\x04\xcf\x3b\x9a\x6b\xe3\x42\x9e\x7b\x7c\xd0\x6e\x0b\x5b\xbc\x61\xea\x0b\x64\xfc\x8d\x78\x39\xcc\xa6\x8a\x46\xaf\x68\xe6\x86\xdd\x7e\x90\x71\x03\x99\xa7\x71\x91\x32\x1a\x66\x73\x26\x82\xb6\x42\x6f\x85\x9d\x37\x46\xf7\x3b\x5c\x34\x4d\xe0\xbf\xd0\x5d\x0d\x3d\xcd\x71\x91\x08\x7a\x6e\xa1\xd5\x14\x26\xba\x47\x5e\x61\xa7\x35\xb1\x91\x16\x32\x2b\xa3\xf9\x35\xf2\xe9\xe0\xea\x7d\x4c\x61\x8b\x19\xff\x11\x78\x19\xcc\x23\x8a\xf4\x33\xb8\x5e\xc8\x88\x2f\x82\xf0\x3d\x73\x2f\xcc\x2e\xec\xc3\x0b\xae\x1d\x32\x5b\xc8\x1c\xe1\xc6\x7a\x21\xa3\x14\xae\x97\xc0\x7e\x4a\xe8\xa9\x87\xc9\xdc\xd1\xf9\x13\x17\xfd\x60\xf7\x79\xa4\xb2\xc2\xa5\x4b\x98\x42\x98\xe3\x2d\xcc\x79\x87\x44\xcb\x48\xf2\x8e\x5b\xa4\x30\xe7\x09\x66\xb9\xc0\x26\x62\x68\xc8\x3e\xe1\x99\x0f\x29\xe4\x13\x7a\xae\x8d\xc6\x73\xc8\x38\xdc\xc4\x2d\x34\x91\x41\xfb\x07\xb4\xf7\xc1\x78\x33\xcc\xb1\x85\x44\xde\xc8\xbe\x8b\x69\xf5\xd0\x79\x17\xfb\xdf\x87\x79\xec\x79\x83\x99\x86\xb9\xda\x43\x0f\x21\xc3\x44\x31\x93\x12\xee\x67\x85\xe9\x55\xd1\xe2\x17\xf2\x1c\xa2\xdd\x33\x92\x3d\x62\xcf\x3b\x74\x9b\xc3\xa5\x73\xd8\x5d\x91\xc0\x1b\x23\xa1\x96\xc6\x61\xee\x86\xdd\x93\x41\xf6\x6d\x5c\xcb\x47\xcb\x1b\x4c\x6c\x8b\x6e\xf3\x48\xea\x0f\x1d\xcf\x91\x45\x1a\xbb\x59\x60\xfc\x27\x9a\xef\x21\x95\x33\x81\xdf\x46\x2f\x5b\x5c\x74\x83\xbc\x2b\x68\x6c\x85\x56\xd3\xd8\xfd\x0d\x7b\xf9\xc6\x6c\xc3\x5d\xd0\xc0\x6e\x27\x98\xc6\x0d\xa9\x3c\x90\x5e\xa8\x97\x50\xbb\x15\xec\x39\xec\xe3\x3c\xa6\xe4\x23\xb7\x15\x36\x12\x72\xc7\x02\x5b\x0c\xf7\xff\x06\x7d\xbc\x71\x8d\x2d\x92\x0e\xf7\x92\x8f\x6b\x24\xd1\xaf\x50\x3b\x6b\x24\x3b\x47\xd2\x03\xcc\xe4\x80\x7b\x7d\xd0\xcc\x0f\x26\xf6\xc4\x79\x3e\xc6\xf3\x30\x8b\x28\xe2\x0d\x31\xbd\x1e\x26\x9b\xc1\x3c\xeb\x48\x3a\x82\x19\xf4\xd0\x76\x01\x59\x77\xd1\x6b\x16\xb3\xa9\x21\xed\x33\x5a\xae\x21\xc7\x3b\xda\x0f\xb3\x2a\x81\x1d\xb7\xb0\xad\x32\xb2\xac\x62\xcf\x77\x6c\xb2\x82\xcc\xcf\xc8\xd7\x02\x8d\xef\x08\x1e\x6d\x82\x67\x07\x8d\x4e\x90\x42\x04\xe3\x1d\xd0\x6c\x09\xfb\x5e\x63\x23\x27\xe4\xf5\x83\x4d\x4f\x09\xbc\x0f\xa6\x16\x32\xd5\x05\x9b\xc8\x62\x96\x11\x6c\x65\x45\xf0\x49\x60\x5e\x55\x6c\x26\xf4\x44\x0b\x69\xde\x30\xde\x05\xd9\xdd\xd1\x43\x0b\x2d\xc4\xd0\xf3\x0f\xf6\xec\xe1\x5a\x3f\xe8\xf0\x0f\x93\x49\x61\xe2\x3b\xf4\x3c\xc7\xac\x7c\x64\xd2\xc1\xbe\x76\x48\x3e\x8d\xc4\xcb\xa8\xdf\x45\x4a\x6d\x6c\xad\x83\xcd\x9d\xb0\xb1\x1d\x32\x18\xa3\xc3\x03\xb6\x38\xc6\x26\x3f\x04\x7e\xa8\xd3\x24\xb2\x7f\x63\x5f\x4b\x24\xb5\xc7\x9e\xc7\x98\x8e\x8f\xf3\x4b\x48\x36\x87\xab\xf9\x48\x3e\xdc\x48\x71\x5c\x37\xcc\xfe\x15\x2e\xbe\x41\x4e\x7b\xe4\x1e\x45\xef\x3b\x82\x67\x19\xfb\x5a\x11\x78\x6b\x74\xf7\x85\xd6\x17\xd8\xd2\x2f\x92\xf1\xd0\xcb\x0f\x66\xd9\x46\xcb\x67\x74\xf4\x83\x44\xc3\xae\xdf\x62\x63\x63\xe4\xd8\xc3\x34\xda\xe8\x69\x8c\x19\x8c\x31\xbf\xe1\x8e\x09\xcf\x3c\xc3\xb5\x23\x04\xcf\x2a\x7a\x48\x63\x33\x45\x4c\x98\xdb\xfe\x17\x26\x76\x47\xea\x47\xcc\xf4\x86\xf1\x43\x56\xcf\xa3\xb7\x31\xb2\x6f\x22\x95\x70\xa3\xdd\xd0\xe1\x19\xa9\x66\x90\x77\x0d\x37\xe9\xa3\xa7\x1f\xcc\xaa\x88\x7c\xc2\x67\x5d\xb0\xf5\x01\x9a\x6f\xa2\xe7\x6f\xb4\x94\xc1\x7d\xf5\xb1\xef\x1e\x32\xdd\xe2\x1a\xa1\x9f\x7e\xb1\x9d\x2e\xf2\xdc\xa1\xd5\x35\x1a\x9e\xf5\xf1\x44\xfc\x1b\xb2\xcf\x61\x7e\x5a\x98\x70\x1b\x3e\x13\xb8\xee\x15\xd3\xac\xa2\xfb\x32\xb2\xfd\x45\x96\x15\x5c\x3f\x8d\xa9\x7e\xa3\x91\x1f\x64\x3f\xc3\x54\xce\xc8\xfb\x07\x2d\x97\xb1\xa9\x3e\xf6\x33\x40\x66\x0f\x6c\x72\x8f\x79\xb6\x31\xe5\x11\x66\x7d\x43\xa7\x5b\xf4\x7b\x80\xf9\x7d\xa0\xc7\x21\x12\xfb\xc3\xf8\x27\xe4\x93\xc2\xc5\x16\x48\x76\x8d\x3c\xee\xe8\x25\x85\x8e\xc2\x5c\x9b\x63\xb2\x1d\xec\x79\x8b\x99\x3d\xd1\x90\xa3\x6b\x23\x8c\xf7\xc0\xbc\x26\x68\xbe\x88\x84\xfc\xdd\xcc\x61\x27\x4d\x64\x18\x47\xf2\x33\xcc\xab\x8b\x49\x2c\xd0\x57\x9f\xe0\x59\x44\x26\x2b\xf4\xef\x88\x79\x0e\x90\x65\x1d\xc9\xe4\x70\xf3\x03\x81\xff\x41\xe6\x4d\x5c\x7d\x80\xfb\x7b\x12\xdc\x5f\xd8\xdb\x0a\x17\x7a\xbd\x10\xfe\xfe\x8d\x66\x7f\x91\xe6\x00\x3b\xc9\x63\x62\x1b\xf4\x30\x46\x1e\x5f\xd8\xdd\x1d\x79\x86\xfb\xef\x80\x4e\x92\xc8\xfc\x8a\x9e\xa3\x98\xe8\x1b\x9b\x19\xe2\xb2\x67\x6c\x3e\xe4\xbd\x27\x1a\xfe\xcd\x2e\x8a\xa6\x63\x48\x98\xe9\x1d\x0f\x19\x36\x90\x5d\x02\x39\xe4\xb0\xb7\x38\x7a\x1f\xa3\x85\x2a\xc1\xfd\x81\xcd\x86\x3a\x0d\xfd\x1e\xb2\x55\xc8\x7c\x0f\x34\x73\xc6\x8c\xa2\xe8\x64\x81\x0d\x33\x3c\xd5\xc0\x5e\x66\xe8\xbd\x81\xd4\x37\xe8\xd7\x1f\x6e\xd2\x42\xe6\x0d\x5c\x3d\x49\xe0\x1f\xb1\x9d\x12\x26\xdc\x8a\x8b\x07\xc1\xa3\x8c\x29\x17\x31\x8d\x13\x3a\x2e\xe0\xa2\x17\x24\x19\xc5\x75\x53\xd8\x6f\x8f\xc0\xaf\xe3\x36\x65\x5c\xa3\x82\x76\xea\xe8\x7e\x8b\x24\x9f\xb8\x6e\x05\x33\x29\x62\x2f\xbf\x68\x7e\x85\x7c\x46\xd8\x58\x1c\xf3\xbc\x63\xb2\x17\x34\x37\x41\x8a\x5d\xe4\xb6\x44\xa6\x27\x24\x99\x40\x07\x7d\xec\x76\x87\xdd\x75\x31\x93\x25\x66\x3e\x47\x87\x3b\xdc\xf8\x82\xdc\xc6\x98\xe1\x1a\x8d\x1d\x31\xd1\x02\xee\x9d\x20\x78\x2e\x30\xf3\x15\xb2\xf3\xd1\x71\x0c\x57\xf7\x90\xfe\x14\x8d\x56\xd0\xe8\x1e\x17\xaf\x62\xaf\x53\x34\xf7\x87\x2d\xd6\xb0\xc9\x37\xf6\x7c\x46\x87\x0d\xd4\x3f\x63\x0a\x3d\x5c\xbb\x81\x7d\xa7\x90\x85\x8f\x8c\x7f\xd1\xda\x0c\x89\xad\x30\x9b\x37\xae\xf5\x40\xb3\x7b\xcc\xf9\x17\x33\x8a\xe1\xfe\x6f\xa6\x32\x52\xc9\xe1\x3a\x57\x82\x67\x05\x69\xc6\x30\xcd\x16\xa6\x7e\x45\xd6\x29\x34\xd7\xc5\xa6\x63\x68\xf5\x8e\x7c\x8a\xd8\xce\x1b\xdb\x1f\xe3\x62\x3e\x36\x7e\x47\x6e\x6b\xb4\x30\x43\xa2\x57\xe4\x19\x47\x97\x2f\x24\x77\x24\x78\x9c\x70\xb1\x3a\x52\xc9\x12\xf8\x51\x4c\x3c\x86\x19\x35\x31\xcb\x21\xc1\xa3\x80\xcd\xec\x09\x9e\x67\x4c\xbd\x8f\x5e\x92\x04\xf7\x0e\xda\x8d\x61\xd2\x73\x74\x1d\xe6\xd7\x09\xfb\xb9\xa1\xdd\x90\x2f\x0b\x98\xe5\x12\x1b\x4f\x61\x77\x0b\xcc\x7e\x89\xbd\x97\x31\xf5\x1b\x76\x7f\x40\xaa\x29\x64\xfb\xc6\x9c\x72\xe8\xb9\x87\x7d\x67\xd1\xc4\x0c\xf3\xfb\x8d\xeb\x76\xd0\x48\x0d\x73\x6c\x13\x3c\xc2\x2d\xfe\x83\x8d\xad\x31\x87\x22\xfa\x55\x46\xaf\x31\x4c\xaa\x83\xe9\xa6\x08\xde\x0b\x34\xf6\x87\x96\xda\x04\xde\x2f\xc6\x1b\xe1\x52\x35\x4c\x3e\x86\x6b\x44\xd1\x5b\x04\x8d\xae\x30\xd9\x23\xae\x7f\xc7\x64\xfe\xb0\x97\x32\x2e\x92\xc2\x94\xd6\xb8\xce\x05\x33\x1f\x60\x96\x35\xf4\xd2\xc1\x1e\x0b\xc8\xeb\x81\xbc\x9e\x68\x2c\x8b\xbb\x6f\xb0\xd7\x3c\x92\x9e\xa1\x9d\x15\xe6\x7f\x1e\x65\x30\xcb\x90\x63\x2e\x98\xd7\x11\x9d\xec\x30\xb1\x12\x1a\x66\xde\x34\x8f\x5b\x1f\x30\x9b\x1e\x72\x1a\x23\xa9\x1a\x12\xee\xd9\xdd\x07\xbb\xab\xa2\x97\x3b\x7a\x0a\xf9\xfd\x85\xfd\x0c\x31\xe3\x24\xa6\x99\xc2\x9e\x6f\xe8\xb3\x8c\x59\x7d\x90\xd4\x08\xf9\x5d\x63\xe3\x51\x6c\x6e\x87\xc9\x4e\x90\x72\x0f\xdb\x8d\x20\xf3\x39\xee\x3e\x45\x8e\x1b\xcc\x3b\x87\xa4\x37\x04\xf7\x23\x32\x6e\x63\xfc\x36\x2e\x79\xc1\x7e\x17\x31\xbd\x14\xae\x31\x46\xbc\x0e\x66\xf3\x40\x52\x3e\x36\xdc\x9b\xd5\x04\x76\xb2\xc1\x6c\xf2\x68\xbe\x86\xc4\xbb\x68\xeb\x80\xab\xbd\x71\xf7\x21\xfa\x4c\xa1\xc7\x0c\xa6\x9f\xc5\x34\xcb\xe8\xcd\x47\xa7\x35\xcc\xba\x85\x19\x0f\x70\xc3\x35\x2e\xf2\x44\xb3\x1b\x82\xf7\x0a\x49\x67\xd1\x82\x87\x99\xb4\xd0\xd1\x0b\x13\xab\xa1\x83\x1d\x1a\x9b\xe2\x16\x65\x24\x37\xc0\x1e\x7e\xb0\xef\x17\x92\x8f\xe3\xee\x1f\xb4\xb5\x40\x2a\x61\x46\xf6\x31\x21\xa7\x0f\xf3\xd8\x77\x0e\x0d\xef\x63\xbe\x45\x2b\x7f\xb8\x9f\x18\xf6\xfd\x8d\xe4\xc3\x1c\x9b\x12\x3c\xf7\xd8\x5a\x1e\xe3\xd7\x70\xbd\x37\xc1\x3d\x64\xb0\x0b\xb2\x4c\xa1\xf9\x21\xb2\x4d\x63\xdf\x55\x5c\xe7\x0b\xd7\xfb\x42\x42\xee\xab\x27\x90\x73\x1a\xc9\xfe\x20\x91\x31\x52\x4a\x22\xb5\x3f\xdc\xfa\x8a\x6d\xee\x90\xcc\x0d\x6d\xce\x31\x5f\x3f\xd8\x4b\x1e\x99\x67\x09\x5e\x3d\xf4\x92\x46\x9f\xbf\x68\x2f\x3c\x67\x1a\x57\xeb\xa0\xe3\x38\x9a\xbd\x12\xf8\x0d\xec\xa7\x41\xf0\x69\x11\x78\x65\x6c\xb2\x81\xfb\xce\xa3\xd3\x03\x76\x91\x42\xc7\x29\x34\x96\x40\xca\x0d\xb4\xf6\x8d\xfb\x69\x21\xf9\x36\xda\xf2\xd0\xe3\x1d\xd9\xcc\x90\x4a\x05\xd9\x0c\xd1\xfb\x08\x39\x64\x30\xcd\x37\xb2\xe8\xa0\xf1\x3e\x81\xbf\xc7\xe4\x47\xd8\x78\x04\xbb\xaf\xa0\xb9\x1e\xae\x9f\x45\xc7\x55\x24\xe4\xcc\x76\x0f\x3b\xde\x63\x7a\x2d\xf4\xde\xc2\x26\xca\xd8\x4b\x13\xbd\x16\x30\x8d\x3e\xda\x7b\xe0\xda\x49\x6c\xac\x80\xd4\xd7\x48\x29\x8b\x89\xc7\x31\xde\x1f\xba\x4b\xa2\xed\x15\xc1\xf3\x07\xd3\x4a\x63\x92\x5b\xa4\xfc\xc0\xd5\xb2\x68\x65\x83\x2d\x94\x30\x7f\x4f\x5c\xf2\x86\x44\x6f\xc8\xb3\x8e\x6b\xcc\xd1\x68\x78\xa7\x7b\x64\x50\xc5\x3d\x7d\xcc\xe7\x89\xf1\xae\x48\xb9\x83\xc9\x1f\x70\x91\x2d\xe6\x55\xc1\xf8\x7d\x74\xda\x45\x73\x55\x6c\x6a\x85\x6d\xfc\x21\x3b\x0f\xf7\x33\xc3\xac\x53\x48\xea\x8a\x7e\xef\x90\x54\x01\x09\x77\x5a\xfa\x8e\xf1\x93\xc8\x20\xd4\xb8\x87\x49\xec\xb1\xaf\x3d\xfa\x37\x45\x3b\x79\x4c\x7b\x81\xbc\xc7\xb8\xc6\x06\xd7\x58\x10\xdc\x97\x68\xeb\x0f\xd7\xf0\x91\xef\x04\x5a\xe9\xa3\xd9\x2a\x2e\x16\x21\xf0\x36\xb8\xe4\x0e\xfb\xc9\x60\x33\x35\x6c\x22\x85\x4b\x5e\x71\xad\x23\xf2\x59\xe2\x92\x5d\xdc\xf8\x85\x79\xbf\xd0\xeb\x0a\x29\xde\x09\xfc\x16\xae\x13\x6a\x73\x88\xc6\xd7\xe8\x60\x83\x2c\xbb\xd8\x58\x17\x2d\x66\x71\xd3\x36\xfa\x8c\xa1\xed\x14\xfa\xe7\x21\x95\x37\x2e\x5e\xc2\xc4\x6f\xe8\x21\x8a\x54\x2f\xb8\xf9\x1e\x5b\x59\xe2\x7a\x49\x5c\x6c\x8b\xfd\x44\x31\xe9\x2f\xb4\x56\x43\x96\x3e\xf6\x72\x46\xb6\x67\x4c\x7c\x81\x44\x3c\xe4\x5e\x41\x9b\x55\x5c\x3d\x8e\xb6\x56\xb8\x54\x1a\x5b\x9d\xe2\xc2\xad\xd2\x0b\x39\xf6\x83\xe6\x0b\x48\x2c\x89\x4d\x3e\x90\xc5\x1c\x2d\x67\xb1\xe7\x19\x9a\x4f\xa1\x9b\x1f\x6c\x75\x8c\x8d\x7b\x04\xf7\x09\x7a\x59\x23\xe1\x99\xda\x31\xe4\xfb\x17\x2d\x8c\xb1\xcb\x0c\xf6\xfc\x83\xfe\x67\x98\x33\x7a\x08\x7f\x2e\x20\xa9\xb0\xd7\x3c\x64\xd9\xc7\xee\xc3\xec\xb8\x22\xb9\x70\x5f\xff\x61\xc3\x9d\xd6\x2e\x63\x43\x26\xef\x65\x70\x3f\x55\x82\x47\x03\xf5\x7e\x08\xee\x3d\xa4\x38\x41\x73\x0f\x5c\xeb\x86\xd4\x56\x48\x66\x8b\x5b\xbf\x31\x61\x5e\xc4\x86\x68\xb5\x8d\xab\xd7\xd0\xd2\x0d\x37\x49\x23\x0f\x1f\x1d\x26\xd0\xf8\x08\x8d\xaf\x08\x5e\x27\x02\x3f\x8d\x4d\x86\x8c\x36\x40\xaf\x33\x24\x5b\xc5\x7c\x2f\x91\xd1\x18\x3d\x3d\xb1\xd5\x03\xe6\xb5\xc6\xf5\x8b\x68\xf1\x1b\x1b\x2f\x61\xf3\x45\xd4\x0f\x39\x7c\x8d\x16\x93\xe8\xa3\x8d\x19\x15\x71\xfd\x6f\x5c\xec\x82\xad\x24\x30\xcd\x1d\x7a\x0b\xf7\x4d\xd8\x0b\x39\xcc\xf1\x07\x13\x6f\x23\xdb\x0f\x3a\x9e\xa2\x99\x0c\x6e\x7d\x42\x7e\x63\xd8\xe9\x17\xf2\xee\x60\xb6\x1b\xb4\x58\xc1\xc6\x46\x68\xad\x8a\x76\x6a\xd8\xf7\x0a\xdd\x7e\xb0\xa5\x23\x5a\xcd\xa1\x95\x24\x2e\x79\x40\x0e\x65\x4c\xf3\x17\xa9\x47\xb0\x61\xa6\x8e\x2e\xe8\xf1\x17\xd3\x3d\x60\xbe\x92\x48\x79\x84\x6b\x47\xb1\xa5\x03\xfa\x75\xc4\xbe\x9b\xb8\xda\x1a\xd3\x0a\x77\xd2\x00\xb9\xdd\x70\xf3\x0f\x66\x7e\x27\xb8\xb7\x31\xa5\x04\xea\x85\x5e\xdd\xe3\x22\x3e\xf2\xda\x20\xfb\x70\xdb\x7d\x90\xc5\x0a\x9b\x4d\x23\x95\x6f\xdc\x70\x81\x46\x56\x98\xe1\x16\xdd\xa4\xf9\x17\x00\x00\xff\xff\xbf\x1b\x72\xe3\x00\x20\x00\x00") + +func keysWordlistChinese_simplifiedTxtBytes() ([]byte, error) { + return bindataRead( + _keysWordlistChinese_simplifiedTxt, + "keys/wordlist/chinese_simplified.txt", + ) +} + +func keysWordlistChinese_simplifiedTxt() (*asset, error) { + bytes, err := keysWordlistChinese_simplifiedTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "keys/wordlist/chinese_simplified.txt", size: 8192, mode: os.FileMode(420), modTime: time.Unix(1497960590, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _keysWordlistEnglishTxt = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x2c\x5b\xdd\xbe\xbc\x2a\x08\xbd\xf7\x2d\xc9\xa8\xd8\xa3\xe2\x41\x9d\x76\xfb\xe9\xcf\x6f\xad\xfe\x17\x83\xe5\x07\x2a\x22\x2c\xcc\x91\x4d\xda\xee\x2d\xc9\x66\xc5\xe6\x93\x64\x2b\x9a\x64\xf3\x35\x41\xbf\x78\x1e\xda\xf0\x32\x3c\x36\x24\x33\x24\xf3\x7d\xc5\x9e\x64\x5b\x43\x93\xe4\xac\x63\x20\xb1\x9d\x95\x73\xf6\xf5\xa6\x6f\xf1\x65\x0a\x56\xd9\xf6\x24\xd9\xd7\x98\x96\x93\xe4\xff\x96\x05\x72\xc3\xd9\x18\xf5\xa7\x61\x2c\x79\x7a\x80\xc6\xcb\x75\x2e\x29\x49\x76\xe9\x33\xc9\xbe\xe3\x67\x99\x8f\x6f\xf9\xfe\xb3\x06\x5e\xab\x81\xae\x02\xfa\x95\x96\x15\xa9\x21\xd1\xf0\x0d\x3d\x1e\x87\x58\x20\x71\x0c\xfd\x08\xc1\x78\x4e\xb1\x96\xe4\x54\xfc\x30\xe6\x33\x54\x93\x5c\x2a\x7b\x12\xab\x89\x2d\x2c\xba\xc7\x4c\x62\x03\xd2\x29\x12\x35\x49\xd9\x16\x68\xf6\xcb\x4b\x92\xa2\x28\x2f\xa6\x2d\x49\xc1\x7b\xd1\x07\xd4\xef\x24\xa5\x3a\x06\x58\xbc\xa1\x71\xbf\x24\x49\x09\x95\x1d\x15\x86\x27\x29\x53\x23\x49\xb9\xe5\x19\x49\xaa\x4c\x5d\x81\xf4\xcf\xda\x99\xa4\xfa\x4b\x29\xcf\xba\x86\xee\x49\x9a\x94\x07\x1c\x5b\xbe\x20\xa8\x96\x8d\x23\x6f\x27\xf8\xb4\x13\x63\x6c\x67\x3c\x49\x9a\x55\x88\xae\x7d\x98\xd5\x7c\x51\x2a\xad\x51\xa0\xcd\xe7\xc5\x06\xe3\x66\x32\xb5\x35\x41\x6a\xff\x2d\xd4\xfa\x35\x85\x42\xb4\x27\x49\x17\xcc\xae\x7b\xf1\x13\x6f\x5d\x25\x90\x80\x6b\xef\x41\x35\xe9\x61\x25\x49\xe4\x0b\x84\xeb\x1b\x2a\x20\xe0\x19\x27\x38\x42\x6a\x51\x31\x81\xa8\x18\x77\xd4\x27\x49\xf8\x6a\xc8\x09\x0c\x1f\xa9\x62\x66\x11\xf6\xe5\x1b\xe4\x87\xbe\x63\xea\x41\x15\x89\x69\xac\x30\x6f\x8f\x4f\x92\x81\x5f\x57\x94\x8c\x21\x5c\xfc\x31\x94\x94\xf5\xc6\x58\x55\x93\x8c\x79\x55\x49\x32\xaf\xa2\x53\x93\x4c\xaf\x49\xe6\x94\xfc\x41\xa2\x18\xc0\x9c\x36\xd7\x8e\xb2\x7f\x0a\xbe\xfe\x29\xe3\xda\xa1\x57\xeb\xa4\x92\x71\x15\xd6\xa4\xd8\xd7\x74\x90\x55\x5b\x92\xaf\x06\x55\xe8\xeb\x59\x76\x47\x0a\xd5\xba\xe5\xa3\xa0\x41\xfa\x24\xb9\x75\x38\x86\x73\x1f\xab\x24\xb9\x3f\xb7\x40\x11\x7f\x6d\xa4\x4d\xb6\x27\x6d\x92\x2f\x2d\x1e\x78\xf0\x96\x36\xd9\x4f\x4d\x9b\x9c\x69\x93\x42\x85\xde\xa0\x6f\x0d\x15\x4b\x49\x9b\xd4\xcd\x3d\x6d\xd2\xa4\x09\x92\xa6\x68\xc9\x9f\x16\x54\x0a\xea\xf6\x06\xa1\xa2\xfa\x00\x83\x61\x19\xf4\xa3\x33\x6d\x32\x67\xd1\xb4\xa9\xe4\x0b\xb4\x81\xac\xf9\xa4\x4d\xb3\x60\xe3\x6e\x9a\x31\xdc\x4d\xf5\x48\x9b\x1e\x1e\x78\x3e\xc1\x52\x2f\xf9\xe2\xe5\xb2\xb6\xa7\x4d\x0b\xf7\xf7\xa6\x50\xf7\x4d\xcb\x4c\x9b\x36\xf2\x6c\x7a\x18\xde\x06\xc8\x0c\x01\xef\x09\x75\xdf\x74\xde\xaa\xe0\xf4\x38\x58\x58\x7e\x32\xc6\x62\x78\xfe\xe0\x81\xb9\xaf\xc6\x6d\x16\x78\x89\x79\xa5\xcd\xde\xe6\x05\x6b\xb7\x15\xd9\x15\xb4\x92\x36\x4e\xaa\x08\x3a\x2b\x2a\x28\x87\x81\xd8\x0a\x79\x15\x77\xd2\x31\xbc\x22\xe5\x04\xcb\x22\x01\xc3\x35\xae\xb4\x39\x16\x64\x73\x99\x69\xf3\xfd\x49\x9b\x5b\x49\x9b\xd7\x2d\x6d\xd8\xbc\x9b\xb7\x35\xd2\xe6\xfe\x01\x41\x37\x1e\x3b\x46\xe3\x81\xbd\xba\x39\xf5\x75\x83\x39\xdb\x7c\x42\xc9\xb6\x77\xcb\x6d\xfe\x9b\x36\x7f\xd2\x16\x92\x39\xc8\xe0\xc2\x84\x60\x60\x21\xa8\x1f\x14\x28\xcc\x02\xa8\xfe\xe1\xc5\x30\xc7\x30\x6a\x41\x18\x16\x21\xec\xbc\xd0\x9c\xdd\x85\x0d\x94\x7b\xce\x5e\x0c\x0f\x1f\x08\x34\xbc\xb1\xb1\xa3\xfb\x78\xf7\xf8\x16\x7e\xa3\x88\x73\x5c\x1b\x6c\xfc\xb6\x76\x4c\x70\xed\x27\xc6\xb3\x8e\x43\x8a\xa7\x6d\x59\xd9\xd3\xb6\xca\x06\xf2\x01\x29\x2c\x6e\x3b\x9b\xb4\x0f\x98\xad\xd8\xd1\xd1\x8a\xf3\x7d\x83\x20\x20\x97\x35\xac\x51\xe0\x6b\x80\xf3\xbb\x50\xeb\x21\xfd\xfb\x4b\x59\xb6\x0d\x9b\x24\xcb\x66\x0d\xb4\xe0\x39\xcf\x35\x52\x7e\xf3\x3f\x20\xa5\x80\xd4\x94\xa5\x6a\x08\x92\x9e\xb2\xa0\x41\x13\x14\xb5\xac\x4c\xf6\x07\xb4\x39\x4b\x1c\x2d\xdb\x57\xc0\xaa\x3d\xcc\xeb\xff\x3a\xe8\x36\xd9\xae\x4f\x61\xb7\x81\xdf\xc6\x2a\xb1\x83\x9c\x0e\xda\x75\x22\x09\x70\x0d\x3c\x0e\x34\x1e\x17\x88\x35\x54\x19\x93\xfc\xc6\x22\x3b\x54\x99\x52\xfc\x44\x9a\x51\x6d\xea\xe9\x6c\x3e\xdf\x8a\x0b\x4b\xf5\x6e\xa4\x2c\x8b\xc6\x24\x63\x91\xb3\x5a\xc1\xfa\x65\x2d\x8a\xfa\x5a\x61\xbd\xb3\xb6\x01\x49\x68\x9b\x8b\xb9\xa1\xe8\x47\xe3\x1d\xf6\x05\x3f\x94\x2f\x29\x1f\xd0\xda\xc9\xed\xa2\xcd\xcc\x97\xf8\x00\xed\x10\x78\xbe\x24\xde\xcc\x41\x3a\x53\xbe\x54\x3a\x68\x46\x5b\x55\xe6\xeb\x01\xc2\xe9\x5e\xd8\x9d\xf9\xb2\x0c\xf5\x81\xab\x46\x11\xf4\x20\x5f\x56\x9b\xa2\x86\xc3\x8d\xe6\xcb\x9d\x6d\xc3\x9b\xe5\x94\xaf\x95\xe1\x57\xf2\xb5\x1a\x18\xaf\x68\x29\xdb\x09\xf9\x5a\x6b\xf0\x5b\x29\x5b\x60\x53\x67\x9b\xf6\x07\xde\x00\x18\xd9\xbe\x56\x52\x2e\xf0\xad\xb9\x60\x60\x45\xc2\x8e\x07\xe9\x0d\x82\x27\xd8\xa2\x5c\x34\x3e\xa0\x5f\xcc\xaa\x60\x2f\xe4\x42\x47\x97\x8b\x1d\x07\x68\xdd\x40\x39\x98\x62\xe0\xe4\xac\x84\x35\x29\x1c\x6a\xf1\x79\x81\xae\x1d\xf4\x06\xd3\x85\x36\x0b\x3a\x55\xd6\xa0\xc0\xca\xe2\xfa\xb9\xbc\x14\xc2\xf0\xec\x6d\x21\xdd\x35\x65\x3f\x0e\x45\x82\x61\x3b\xd6\xc2\x4b\x81\xc3\xc9\x0e\x53\x9d\xbd\xc0\x03\x64\xaf\x9b\x35\x54\xab\x24\x07\xf0\x42\xf6\x8a\xb1\x79\xa5\x30\xbc\x76\x38\xd3\xec\x0d\xab\x8a\x74\x5f\x64\xd3\x0e\x8b\x8a\xf4\x24\xa0\xc9\xde\xda\xcb\xbf\x0d\x83\x79\xc9\xde\x66\x38\x7a\x6f\x5f\x83\x39\xc9\xb0\x40\xd9\x99\xd5\x3b\x6b\x74\x30\x0e\x68\x0c\xac\x74\x76\x2c\x86\x47\xbc\x7c\x38\xa5\x39\x39\x88\xc5\x59\xae\x36\xb1\xf4\xbe\xe0\xc3\xb3\xaf\x18\x4c\x06\xa7\x47\x81\xfb\xe3\x53\x53\x86\xc1\x02\xc5\xfe\xcf\x21\xc7\x04\xad\x20\x8d\x19\xd8\x20\x21\x94\x63\xc8\x5d\x40\xff\x9e\x94\x43\x59\x49\xe1\x3b\x73\xa8\x82\x87\xde\x29\xc3\xa4\x61\xa3\x85\x41\x4c\x61\xa3\x83\x02\x2e\xe4\x70\x3c\xc3\x76\xe6\x78\x47\x19\x7e\xef\x29\xc7\xca\x86\x79\xc5\x52\x52\xc3\x50\x63\x55\xee\xee\x58\x8d\x35\x17\xc7\x81\x8e\x9f\xc1\xed\xbe\x36\x4d\x79\x95\xb9\x20\x8d\xd5\xf1\x7b\x8d\x7b\x5e\x61\x8e\x8d\xb6\x22\xa8\x4c\xeb\xdf\x0e\x5b\x81\xbd\xb9\xc6\xc5\xad\xb5\x06\xcc\x77\x5e\x90\x01\x3d\xd3\x2e\x7b\xda\xa5\xc2\x50\xed\x30\x49\x3b\x1d\xf2\xfe\x82\xae\x5d\x68\x91\x77\x88\x63\xe7\xc6\x67\xe6\xdd\xd2\x2e\x4f\xda\xb1\x93\x77\xdd\x64\x2a\x92\xb0\x91\x76\xcd\x70\x5d\xbb\x66\xad\x1b\xea\x2a\xa0\x33\x92\x02\x2d\xda\x15\x8b\xc9\xea\x10\xe5\xc0\x03\x6b\x1d\xda\xf8\x72\xbc\xb5\x0e\x30\x27\x60\xdd\xb5\xb0\xa7\x62\x5f\x56\xac\x70\x2d\xbb\x56\x63\xf5\x66\x1c\x41\x23\x76\xda\xb5\xa1\x26\x31\xdd\xae\x5d\x59\xb1\xfb\x30\xbe\xce\x0b\x14\x28\x60\x57\x82\xb0\x5d\x47\x0e\xdb\xf8\xa0\x6c\x32\xec\x6c\x48\x3e\x20\x1d\x86\x69\xd7\x31\xc3\xd1\x64\x8a\xa1\xa7\x09\xc5\xdb\xf5\xab\xc5\x3b\x52\xd8\x8f\x5d\xbf\x50\xa9\xdd\xe4\x84\x0a\xed\x1c\x93\xc1\x50\xec\x48\xe3\x49\x3b\xab\x99\x0e\x45\x89\xce\xb4\xdb\x71\x60\x3a\x76\xd2\x88\xef\x76\x36\xd8\x90\xdd\x8a\xd6\x2a\x69\x37\x62\x9e\xdd\x9a\x0f\x59\x78\xa0\xc2\xef\x86\x61\xda\x78\xa1\xfc\x6e\xe3\x55\xe9\xdd\xc6\x2b\x4a\xc3\x2a\xd9\xa8\x36\x06\xd2\xd7\x87\xef\x36\x3a\x45\x68\x63\xbe\x4b\x0b\x49\x82\xcf\x97\x2b\x63\x5f\x0f\xe6\xfe\xfd\x3d\x69\x77\x86\x28\xbb\xe7\x45\xe3\xbd\xfb\x99\x76\x2f\x05\xa4\x5f\xd6\xd2\xee\x55\x98\x34\xae\xa2\xb7\x8f\xa2\x55\x63\x23\x12\x0c\xc4\x17\x94\x78\x07\x7e\xde\xb9\xb7\xf6\x90\xd3\x1b\x12\xcc\x2e\x84\x81\xd2\x1e\x72\xa7\x9d\x3b\xea\x8d\x78\xf6\x30\xd6\x35\x74\x18\xd6\x3e\xa0\x1d\x84\x8c\x20\xf1\x58\xa8\xfc\xa4\x7d\xe5\x4f\xda\x57\xdd\xd2\xbe\xa0\x31\xeb\xd5\x53\x60\xd9\x9d\x66\x6f\xe7\x4a\xdf\x12\x47\xda\x9f\x26\xb0\x57\x2a\x50\x69\x15\xc4\x11\x2a\x51\x1e\xd0\x06\x32\xaf\xa4\x32\x8c\x39\x63\x82\x3c\x49\xf3\xe5\x49\xf3\x0b\xd4\x34\x7b\xf3\xfa\x24\x05\x64\xe1\xe6\xd7\x7d\xc1\x33\x26\x3d\x68\x11\xf5\x3c\x93\x12\xc3\xa8\x11\x99\x68\xd9\xfc\x4e\x5a\x76\x3e\x6b\x9e\x81\x11\x14\x3d\xa5\x4d\xa4\x14\xaf\x16\xed\xd7\xbf\x8c\xaf\x40\xf2\x5a\x0c\x4c\xcb\xd0\xa4\x75\x93\xf8\x20\x01\x62\xd3\x0a\x8c\x85\x5c\x85\x1b\xd4\xea\x74\xbc\x5a\x7b\x71\x94\x76\x47\xb0\xa3\xb5\xcf\x27\x69\x23\x44\xd0\x06\xbc\x8f\x6d\xa0\x80\x39\x63\x20\x75\x58\x44\x6d\x8a\xc9\x34\x0d\xcc\xad\x1d\xd4\x00\x6d\x27\x8c\x80\xb6\x13\x7b\x50\xdb\x45\x6d\xd1\xf6\x03\xfe\xad\x60\x87\x69\xf3\x75\x5e\x49\x5b\x58\x66\x02\xd5\x80\x7f\x0f\x54\x84\x6d\xc0\x56\x7c\x5f\x02\xad\xb8\x4f\x34\x69\xb7\x01\x97\xa3\xff\x01\x63\xe8\x7f\xcb\x7a\x02\x06\xd2\x80\xde\x6a\xb0\x2c\x7c\x70\x46\x11\x90\x43\xac\x3e\x93\x8e\x2c\x68\x3e\x86\x3c\xa0\xca\x11\x8d\x49\xc1\x4f\x0d\x00\x27\x9d\x97\xe5\x91\x14\xda\xcc\x62\xb8\x61\xfd\xfa\x07\x8f\x5e\xbe\x9a\xf4\x97\x72\xf8\x95\x0a\xa7\xa0\xbf\x8c\xe9\xf5\xf7\x1f\xca\xd0\xdf\x4c\x91\xff\xe6\x82\x30\x49\x7f\x19\xda\xeb\xaf\xd2\x46\xea\xaf\x46\x36\x66\x5c\x02\xed\xd2\xdf\xcb\x36\xac\xff\xaf\x91\x19\xc5\xf2\xcb\x0c\x87\x52\xeb\x6f\x87\x85\xd2\x5f\xc6\x6e\xfa\xdb\x29\x8e\xdf\x5e\xb0\x6d\xf4\xb7\x3b\x79\xf5\x78\xc7\xc0\x10\x4d\x7f\x27\x64\xf1\x28\x7e\x40\xb4\xe9\x10\x60\xe4\x74\x60\xc1\x0f\x81\xb9\x7f\xd2\x01\xbb\x7a\x88\xb5\x09\x3a\xaf\x74\x00\x51\x1e\x02\x55\x39\x10\x28\x1c\x52\xa1\xc1\x07\x62\xea\x91\x0e\x69\xf8\x65\x64\xb4\x09\x85\x3e\x10\xa7\x1e\xf2\xfa\x81\x43\xc0\x06\xb6\xe7\x10\xea\xeb\x21\xd3\x10\xcc\x1e\x8c\x35\x0f\xf9\x7a\x40\x2c\x87\x0a\x5d\xcd\xa1\x5b\x2c\x98\xb2\x43\x77\x85\x3b\x06\x74\x38\x54\x77\x10\xbc\x55\x29\xc8\xc0\x0a\x1c\x3a\xa6\x7d\x59\x07\x3b\xf1\x20\xd0\x39\xf4\x4e\x87\xc1\x25\x1c\xf6\x06\xa0\x87\x69\xd9\xd3\x61\x27\xf9\x43\x9a\x87\x95\x0a\x32\x59\x0b\x8b\x7b\x20\xc2\xa1\x4f\x38\x8c\x0e\xe9\xb0\x06\x2b\x77\x18\xdb\x60\x42\x06\x98\x7e\xd8\xc8\xac\xce\x32\xbc\x4f\x22\xf6\xc3\x7e\xd3\x51\xe4\x04\x81\x88\x0a\x1c\xd9\x51\x30\xf9\x82\x29\xa6\xa3\x60\x1e\x85\x3b\xf7\x00\xd6\x3a\x8a\xb3\x14\x88\xeb\x28\xce\x2a\xdc\x5a\x47\x59\xb6\x83\x92\xc3\x93\x0e\x97\x9a\x0e\xcf\x90\xb5\x9f\xe9\x00\x8c\x3a\x1c\x33\x72\x9e\x8e\x1c\x08\xcb\x0e\xf7\x99\xde\xed\x85\x28\x73\xf0\x05\x81\xc9\x81\x20\x1f\x96\x03\xd6\xeb\x70\x98\xb5\xc3\x83\x61\xf3\xe1\x63\x90\x17\x51\xdc\xc1\x63\x84\xc3\x7f\xd3\x11\x72\x52\x4a\xc1\xa9\x84\xfe\xb7\x60\x43\x8e\x50\x8c\x28\x0c\xaa\x74\xc0\x0c\xa2\x10\x23\x0a\x67\x31\x50\xd2\xc1\x38\xe9\x08\x07\x5c\x3d\x62\x41\x44\x80\x1d\xc7\x6a\xf8\xb5\x27\x1d\x2b\x1a\xd5\x0d\x20\xfd\x58\x5c\xf4\x53\x18\x44\x31\xd8\x3e\xa5\xc8\xef\x83\x84\xe0\xfe\xc4\x18\x4e\xe9\xe9\x14\x1e\x10\x9c\x12\xdb\xbf\x14\x31\xd4\x29\x51\x2c\x23\xa1\x9d\x3b\x65\xe0\x87\xda\x13\x75\xa8\x71\xa7\x2c\x36\xf8\xd3\x74\xc2\x14\x49\x41\x6a\x6b\x20\x09\x66\x22\xde\x38\xb5\x2d\x28\xc0\xa9\xe3\x1d\xd4\x85\x09\x9d\x06\xb3\x79\xc2\x5f\x9c\x76\xc2\xa2\x9f\xaf\x82\x9c\x16\x72\x1c\x78\x8d\x92\x4e\x38\x8e\xb3\xc8\x0e\x02\xd5\x3c\x8b\x04\xe9\x18\xe9\x2c\xf0\x7f\x67\xb1\xda\x07\x52\xdf\x48\xbd\x82\x62\x8a\xc5\xd9\xda\xef\x74\x22\x9c\x3e\xa1\x18\xa7\xef\x3b\x14\xeb\xc4\x4a\x9f\x58\xe2\x93\xc1\xc3\xe9\xf0\x5a\x92\x4e\x1f\x5d\x0b\x92\x61\x3d\x9d\xf0\xcf\x2d\x9d\x10\xfe\x19\xb2\x81\x60\x14\x8c\x92\xcf\xe0\x14\x02\x16\xee\x64\xac\x7c\x86\x7c\x01\x03\xce\x50\x74\x15\x0a\x49\x86\xed\x20\x7a\x80\x22\xd7\x33\x17\x20\x7c\x75\xd0\x3b\x9d\xb1\xc0\x68\x41\x79\xce\xc5\xd1\x2d\x4e\x6d\x59\x41\xbe\x4d\x89\x74\xae\x96\xce\xa7\xa6\x4b\x60\xbd\x18\x75\x5d\x52\x8e\x74\x49\xad\x8a\xe7\x4a\x75\xbb\x60\xbc\x2e\xe9\xfd\x49\x17\xa2\x49\xe4\x04\x72\x62\x5c\xa0\x5f\xe8\x30\x82\x2f\x9e\x93\x5c\x72\x7f\xd2\x25\x7f\xac\x82\x08\xff\x52\x29\xf3\x42\x12\x13\xf4\xfb\xa4\x0b\x3e\xf3\xf2\x33\x5d\xaf\x7f\xbc\xb4\x14\x07\xad\xca\x97\x9e\x2e\x6d\xe9\xd2\xf0\x74\xd9\x0e\xe5\xb9\xec\xbc\xd2\x05\x10\x70\xc1\xda\x5d\xd6\xd3\x85\xfd\x7e\xd9\x98\x58\x98\xcb\xb7\x0d\x34\x03\x7b\x5c\x58\x88\xcb\x8b\x82\x18\x50\xe9\xf5\xee\xbf\x0b\x01\xcb\xe5\x8d\x75\x1c\x75\x3a\xde\xa3\x81\xc0\xc5\x5c\x74\x85\x97\x8f\x37\x90\xa6\x5a\x5d\x3e\x15\x8f\x0b\xc5\x30\x5b\xd7\xda\xd2\x05\x3d\xbd\x56\x95\x06\x0a\xcf\x7a\xad\x0a\x06\xab\xed\xa1\x3b\xd2\x13\xc3\xc2\x2a\x5c\x2b\x76\x56\x08\xe6\x40\x0a\x6b\x6c\x14\xea\xb3\x61\x29\x81\x04\x2d\x7b\x4b\xb6\xab\x24\x1e\x2b\x23\x48\x34\xb4\xb2\xb3\x21\xc8\xc1\xcc\xad\x00\x2a\x30\xa5\x21\x33\x02\x74\xab\x46\xdf\x67\xb5\x12\x2f\x5b\xad\xb0\x1f\x56\x3b\x3c\x9c\x55\x7a\x17\xab\xef\xc9\xa5\xd5\xbe\xe0\x1c\x0c\x91\x84\xb5\xd7\xbd\x59\x63\x20\x67\xed\x1f\xfc\xb6\xb6\xeb\x2f\xa8\x11\xcd\x58\x23\x8a\xb3\x06\x24\x15\x4f\xb2\x06\xef\x81\xa4\x58\x66\xea\x51\x93\xb5\x0b\xd6\xde\xda\xa5\x50\x49\x6b\x36\x81\x79\xad\xfd\x28\x2b\xfd\x2c\x36\xad\x2f\x47\x20\x59\x6b\xcd\xb3\x92\x53\x5f\xa0\xff\x2d\x63\x9d\x81\x70\xcb\xda\x78\x1b\x22\x2c\x44\x42\xa7\x69\x0d\x11\x0f\xd8\x4e\xce\x0e\xf8\x02\xda\x67\x6d\x7a\xb2\xf6\x7d\x9f\xbf\xc6\x4e\x5e\x4f\x6f\x01\xc1\x8e\x02\x79\xdb\xf0\xc2\x01\x8c\xb1\x34\xd9\xd4\x9a\x00\x75\x9f\xf4\xf3\x1e\x55\xfd\x08\x76\x4c\xfa\xe1\xef\xef\x2f\xfd\xa8\x14\x38\xce\x1f\x95\x06\x5a\xca\x93\x7e\xf4\xd6\x92\x7e\x7c\x4b\x3f\x08\x90\x7f\x00\x2a\x7e\x7c\x05\x94\x0a\xb0\xe8\x67\x01\x0f\xfe\x2c\x2c\xea\x0f\x62\xef\x9f\xc5\x53\xea\x9f\xd5\xcc\x03\xc9\x27\xf1\x10\xff\x23\xed\x94\x70\x4f\x1f\xec\xe9\x8f\x6a\x4f\x1f\x38\xc7\x85\xf4\x49\x1f\xcb\x9f\xf4\xb1\x1d\xbf\xc6\xf7\x86\xe7\x76\xee\x5e\xd3\x07\x70\xfe\x63\x13\xbf\x8c\xbd\xf2\xc1\x94\x3f\x36\x27\x9f\x6f\x4b\x9f\xa6\x9a\x3e\xcd\x0e\x50\x38\xae\x4f\xf3\x3b\x15\xd9\xf0\xd3\x02\xea\x91\x8a\xec\x00\xa3\x45\xf6\x27\x15\xf9\x68\x2a\x08\xf7\x8a\xb4\x73\x41\xb7\x8a\xf4\xe9\x78\x0f\xbe\x4c\x56\x9d\xd6\x52\x41\xdc\x07\xda\x00\xbc\x8b\x7c\x25\x15\x01\xfb\x1b\x65\xf7\x80\x33\x29\xf2\xb0\xfe\xdf\x93\x8a\x0a\xbb\x51\x39\x40\xa2\x81\x7e\x35\x01\x03\xc3\x7e\x17\x3d\x66\x2a\x7a\xa6\x57\xc1\x8b\x9e\x70\x5c\x45\x6d\xbc\xa5\xd5\xd1\x82\x59\xed\x9c\x17\x92\x91\x8a\x7a\x87\x91\x01\x8a\x65\x39\xcf\xe0\x0a\xe2\xb0\x54\x4c\x22\x15\x40\x8b\xf9\x20\x0d\xc0\x94\x62\x99\x3b\xa4\x40\x28\x05\x6e\xe2\xf5\xf1\xc5\x30\x71\xab\x1b\x08\x06\x8e\x28\xa3\x00\x8e\x14\xfb\x0f\x0e\x9e\x38\xb7\x18\x8f\xba\x10\x73\xa6\x62\x34\x6f\xc5\x85\xa4\xa5\xe2\x1b\x4d\x65\x71\x40\x0e\x02\x85\xe2\xa7\xe5\x54\xbc\x69\x79\x90\x9c\xa9\x38\x64\xe9\x18\x26\x72\x16\xda\x2e\xb8\x66\x3a\x95\xe2\x0f\x9a\xae\xfc\x79\x52\x59\x27\x71\x77\x59\x0c\x98\xcb\x6a\x42\x9a\xaf\x54\xd6\x2f\x76\x52\x79\x02\x08\xb7\x4a\xbe\xe0\x08\xab\xec\xa9\x0a\x3a\xac\x72\x36\x9d\xa9\x8a\x21\xc7\x4a\x62\x6c\x56\xe5\xc7\x23\x55\xac\x70\x95\x5a\x05\xd9\xc8\x6d\xe8\x05\xe1\x33\x76\x45\x95\x76\x3a\x28\x31\x77\x15\x7e\x39\xa9\x02\x80\x5c\x25\xb6\x37\xc9\x17\xe8\x49\x9e\xf1\x76\x1d\x1f\x76\x18\x61\x2f\xb7\xf1\x01\xc1\xe0\x28\x93\xca\x23\x43\x6c\xfc\x30\x32\x9c\x7c\x0b\xfb\x45\xf2\xd6\xf8\xb5\xba\x6a\xaa\xf0\xfb\x55\x65\xf7\x1b\x49\x03\xa1\x06\x54\xf8\xbe\xaa\x40\xe7\x98\xa2\xee\xe0\xa3\xbb\x49\xaa\x5a\x10\x09\x55\x2d\xa8\x40\x69\x55\xad\xd8\xd2\x00\x19\x9c\x87\xb6\x95\xaa\x46\x46\x16\xf4\xb8\xd2\x40\x55\x9e\x07\x56\xe0\xa4\x8a\x58\x82\x05\x93\x7c\xe7\xe5\x7b\xaa\xb6\xc3\xfc\x56\xdb\x1b\x95\xa4\x5a\xf9\x80\x50\x2f\xaa\x21\x76\xac\xd8\x91\xd5\xda\x3b\x76\x43\xbc\x5b\xad\x21\x42\xa8\x16\x92\xd9\x9a\x5e\xa5\xda\xc0\x92\x33\x06\xaf\x08\xb9\xb1\x0c\x98\xbe\xfd\x2a\x38\xfc\x72\x13\x54\xdf\x00\xe5\xaa\xef\x5a\x40\xe1\x02\xaa\x57\xfc\x60\x25\xab\x37\x43\x34\x58\xdf\xf8\xba\x7a\x7b\xa5\xeb\x0d\xf2\x74\x8c\x8a\x67\x62\xd5\xc9\x2b\x1a\x82\xdf\xea\xe3\xbf\x65\xd3\x53\x7d\xcf\xc6\xff\x45\x88\xd5\x5f\x4e\xab\xf1\x38\xa8\xf2\xfb\x40\x85\x16\x56\xff\x9a\xa6\xba\xb0\x62\xeb\x38\x50\xb8\x30\xa8\x55\xa6\xf5\xf2\xa4\xba\x06\x27\xb6\x86\x62\xd2\x6b\x5c\x3c\x7b\xaf\x6b\x40\x20\x30\x6b\x75\xf1\x13\x66\x7d\x86\x96\x03\x09\xd5\xbd\x3e\xf3\x4a\x4d\xb0\x79\x1a\x60\x62\x93\xfe\xb1\x96\xda\xfb\xd5\xab\xc9\x98\x4f\x6a\xc2\xc1\xb5\x37\xba\x68\x2a\x91\x9a\xe6\x4f\x6a\x08\x29\x9a\x9e\x32\xd9\x5c\x4f\x9e\x48\xb6\x7f\x41\x75\xd3\x7e\xe9\x9d\x9a\x06\x0b\x07\x4a\xf8\xe3\x37\xb3\xa6\x6b\x42\x2a\x8d\x01\x47\xd3\x7b\xa4\xa6\xbf\x33\x35\x98\xe7\x77\x65\x9b\x43\xb5\x9b\x23\xa2\x6b\x5e\x0d\x86\xb3\xb9\xef\xcc\x0c\xec\x95\xe6\x81\xd1\x3b\x2b\x4c\x79\xab\x4f\x92\x0b\x52\x6e\x88\xf2\xf0\x0a\xd3\x03\x33\xdb\x56\x2e\x1c\xfe\xbb\x7f\x1b\x8f\x1c\xdb\x9a\xc9\xe5\x93\x7c\xd3\x27\xf9\x46\xbf\xe8\x5b\xb1\x53\x93\x6f\x23\x63\xce\xbe\x0d\x4e\xc3\x37\xae\x8b\x6f\x5f\x1e\xdf\x79\xce\x2b\x92\x67\x6c\x09\xcf\xd3\xc1\xd3\x77\x8f\xe4\xc7\x81\x9f\xf2\x09\x43\xf0\x03\x0e\x00\x61\x87\x7f\xe4\x49\xc0\x41\x4e\x8b\xe5\xe5\xa9\xdd\x72\x72\x18\x38\x07\xec\xf5\x86\x1f\x04\xee\x8d\xe7\x70\xde\xca\x93\xbc\xa3\x7d\x47\x20\xee\xdd\xde\xe2\x4e\x08\xe1\x9d\xab\xe3\xef\xb7\x4b\x0f\x40\x46\x8f\x4c\x28\xf8\x9e\x2a\x79\xec\xd6\x60\x68\x3d\x4e\x8c\x34\x78\x80\xed\x61\x27\xe3\x36\x8f\x7e\x21\x7b\x4c\x9e\x14\xbc\x0a\xe9\x6b\x12\x5d\xf8\x9a\xef\x1b\xa0\x80\xaf\x49\xaf\xef\x08\x18\xfd\x8b\x11\x61\xf5\x80\x98\xfd\x06\x74\xf0\xdf\xe7\x44\x2e\x95\x2b\xf9\x1f\xe6\x42\xb8\xd3\x85\xbb\xb6\x63\x3b\xf3\xb0\xae\x4b\x01\xba\xee\x52\x6a\x42\x10\x2e\xa0\x5a\x40\x2d\x83\x72\x14\x5d\x3a\x69\x20\x9e\xee\xc2\xb3\xd2\x2e\xf1\x01\x09\xe7\xf3\x7c\x52\x87\x51\xeb\xb4\x66\x1d\x46\xac\xcb\xb4\xb7\x26\x4f\xac\x3b\x8d\x59\x4b\x9d\x5f\x41\x3a\xfc\x5b\x97\x87\x7b\xb7\x2b\x07\xa1\x02\x1d\xe0\x07\xe5\xae\x32\x84\x25\xc5\xb2\xb4\x04\xb1\x77\x6d\x82\xa8\xbe\x6b\xcb\x56\x52\x57\x87\xe9\xed\xca\x53\xef\xae\x71\x40\x63\xba\x06\x96\xb0\x6b\xc0\xe9\x75\x9d\xa9\x5f\x9c\xfe\xe5\xd3\x53\xbf\x78\x7a\xd2\xaf\x67\x18\x3c\x51\x37\x69\x9e\xba\x65\xce\xd6\x5e\x6f\xdb\x4d\x31\x1a\x3b\xf1\x53\x70\x01\xba\xec\x56\x30\x53\xf8\xbe\x6e\xde\x14\x7d\x5a\x47\xbd\x31\x31\x3b\xe3\xbc\xed\xef\x4f\x52\x7f\x65\x5a\x04\x3b\xad\x97\xf7\xe4\xae\x13\x59\xf1\x58\xb1\x17\xe2\xc8\x5e\x78\x34\xd6\xe1\xd3\x40\x4f\x10\x28\x4f\x77\xad\x20\x33\x75\x07\x9a\xef\x5e\x20\x12\x00\xf6\xee\xf0\xd2\xa9\x7b\xdb\x41\x9e\xd4\x1d\x9d\x7b\x5f\x6f\x95\xa0\x12\xf2\x00\xf7\xdf\xc3\xb0\x8d\xed\x06\xf8\x4c\x81\x10\xfe\xb9\xd8\x0e\xad\x81\x3c\xfd\x86\x7a\xbe\xa7\x61\x3d\x24\x73\xb7\xf6\x10\xec\xf8\x1e\xca\x1b\x16\x3d\xf4\x60\xb1\x62\xfd\x91\xf2\x2a\x48\x0f\x9d\x60\x11\xfa\x7d\x5f\xdf\xa6\xd0\xce\x1e\x56\xa1\xed\x3d\xec\x2d\xf1\x30\x56\x35\xae\x4c\xd8\x97\x02\x09\xfb\x03\x85\x91\xa9\x48\x79\xd2\xd4\xc3\xf7\x45\x4e\x7e\x60\x35\xc3\x79\x4c\xdc\xc3\x69\x16\x7a\x78\x75\x36\x76\x3f\x40\xfb\x3b\x91\x40\x24\x89\x41\xfa\xfc\x57\x6d\xed\xa0\x3c\xb5\xed\x6b\x43\x7c\xdd\xd7\xbe\xc3\x28\xf5\x85\x45\x5d\xa5\xa7\x17\xf2\xf7\x55\x69\x72\x3b\x61\x44\x5f\x1d\x2a\xb6\x10\xd4\xf5\x15\xef\x17\xb4\xbe\xde\x19\xac\xe0\x8e\xef\x34\x5b\x7d\x0d\x54\x9f\xa9\xaf\xbf\x3f\x48\xfa\x09\xa9\xb6\xa7\xff\x96\xf0\x12\xcd\x7f\x4b\xda\x5c\x15\x69\x60\x37\xfe\xb7\x74\x70\x6d\xfe\x5b\x40\xb0\x70\x3f\x20\x7f\xe9\xbf\x85\x29\x85\x6c\xb0\x1c\x21\x39\xc3\x67\x31\xf6\xe5\x77\x97\x90\x5d\x02\xd4\x3c\x05\x80\x0b\x03\xe2\x77\x91\x42\x80\xbc\x03\xd8\x34\x04\xc3\x0f\x69\x80\xc1\xaf\x2d\x0a\xe9\xb6\xa7\xc0\xb2\xf1\x3b\x42\xbc\x67\x09\x21\xb0\x1c\x21\x77\x0a\xf9\xf3\x48\xef\x2d\x14\x7e\x69\x44\x9c\x83\xce\x15\x48\x38\xf4\xfd\x12\x1c\xca\xef\xb1\xa1\x59\x61\x31\x43\x33\xd4\x3f\x34\x7b\xb0\x90\x5f\x46\x42\xb9\x6e\xa1\x07\x9d\x50\x28\x83\x9f\xd0\x03\x7b\x3e\xf4\x34\xb2\x3d\x43\x51\x76\x52\x69\x43\x7f\xde\xaa\x45\x7e\x41\xb9\x37\x42\x0b\xc2\x77\xde\x5d\x08\x25\x46\x0b\xfd\x07\x60\x42\x89\x2c\x42\xe9\x91\x43\xdb\xce\xcc\xa6\x77\xa2\x65\x0a\xa5\x95\x86\xa6\x1a\x0a\x3a\xd0\x51\xe8\xbb\x2b\x43\x79\x7b\x27\xf4\xbd\x70\x14\x3a\xf2\x62\xa2\x8c\x52\x43\x79\x55\x24\x74\xf8\x0a\x56\x1f\xdd\x1b\x07\x34\x56\x41\xc1\x7c\x9b\xcd\x78\xb9\xce\x15\xe8\x6a\xb5\x77\x66\xdf\x57\x7c\x5f\xe3\x60\x78\x36\x15\xd7\x33\xaf\x9a\xc2\x36\xfc\x36\x54\xc3\x26\xa1\x91\xe7\x46\x79\x3f\xea\x87\x1d\xe8\x9f\x2e\x17\x2e\x61\x4f\x3c\x9e\x0f\x73\xbc\xf3\x7e\x0d\xbf\xf1\x87\x11\x3f\x04\x4f\x0b\x83\x5f\x78\x02\x38\x3b\xf8\xb5\x32\x7c\x73\xd2\xc5\x17\x46\x6d\xe1\x95\x07\x39\xdc\x2c\xe1\xfe\x31\x3e\xd7\x14\xd0\xe2\x70\x86\xc7\xc1\x53\xea\xf7\x02\x4e\xc0\xdb\xa4\x20\xe0\x8e\xb5\x51\xe6\x08\x84\x63\x9d\x29\x00\x77\x62\x35\xfc\x6e\x79\x52\x2c\xc0\x87\x21\x3b\x7e\xf0\x2d\x43\x76\x46\xdf\x43\x0e\xbc\x18\x0a\x0b\x8b\x0b\xc2\x94\x21\xe5\xa5\x13\x04\xfd\x0c\xe0\x9d\xf1\x1e\x34\x0f\x44\xa1\x43\xa6\x8d\xe3\x41\xea\xe3\xb2\x34\x04\x2a\x35\x64\x11\x85\x0e\x38\x8e\x21\x4f\x1a\x19\x01\xf5\x80\x77\x18\x19\xca\x3d\xf2\x0b\x97\x47\xd6\x86\xb7\x4b\x2b\x13\x58\xc8\x91\x8d\xe7\xac\x23\xdb\x18\x1e\x23\x8d\xec\xc1\x0f\xe7\x23\xfb\x9a\x69\xe4\x90\x0e\x8a\x58\x73\xe4\xb0\xce\xbc\xb5\xa5\xa1\x82\x1f\x80\xfd\x78\xb7\xc5\xc0\xca\x0f\xcd\xb0\xc1\x43\x33\x74\x19\xb1\x38\x99\x69\x7e\x6d\xc4\x00\x26\x1b\xaa\x9f\x34\xf4\xa4\x8f\x1b\xfc\xa2\x81\xa4\xa4\x01\x0d\x96\x48\x43\x19\xf3\x0e\x86\x5d\xb0\xa7\xef\x18\x35\x4c\x07\x12\x7e\x2a\x1b\x3a\xc6\xcb\x9b\x01\xd6\xd0\xb9\x7a\x1a\xb0\xb7\x69\x5c\x8c\x05\xc6\x25\xc7\x04\xe5\x21\xce\xb8\x28\x8c\x0b\x03\xb8\xd8\xdb\xa5\x61\xc7\x91\xc6\xc5\xd3\xe3\x71\x19\x6b\x03\xd3\x8c\xcb\x3a\x08\xb4\x68\x5c\x08\xcb\xc6\xe5\xc8\x76\x47\x15\x47\x21\xb6\xcb\xb8\x7c\xf1\xb3\xcc\xb8\xb0\xe7\xc6\x15\x56\x51\x06\x8d\x18\xd7\x3a\xa0\xba\xe3\x7a\x12\x9c\x0d\xb4\x76\xc0\xb4\x11\xa3\x0c\x53\x2c\x1a\xd5\x9a\xdf\x0a\x87\x15\x8a\x03\xf1\xc2\x30\xd8\xad\x61\x85\xfd\x5b\x35\xd8\x83\x61\xaf\x2a\xf0\xeb\xf6\x78\xb9\x05\x26\x6b\x44\x33\x03\xfa\x0f\xb5\xb1\xdf\x34\xe0\x3b\xc6\x87\xaf\x3c\x1b\x48\xe3\x63\xf8\x61\xd6\x30\xe6\xe3\x63\x18\xfd\x07\xb6\x7e\x20\xb8\x1f\x45\x6a\x1a\x45\xb5\x83\xd2\x72\x0c\x7a\xd4\xc1\x93\xcd\xf1\x46\xbc\xa3\x18\x6a\x39\x60\xda\x80\xdb\x1f\x14\x2c\xcf\xb1\x47\x85\x15\x1c\x55\xc0\xb8\x22\x22\x19\xd5\x3f\xa4\x3e\xaf\x34\x1a\x8c\xf5\x68\x88\x61\x46\x83\x4e\x35\xca\x1e\xb0\x77\x38\xde\x3d\x67\xf4\xea\xfc\x92\x3d\x28\x73\xdf\x25\x0d\xc7\xaa\xd0\xd3\x0f\x2f\xbb\xb1\x4e\xb1\x1d\xf4\xbd\x30\x32\x78\x5e\x33\xbc\x2a\x00\xcd\x40\xc8\x3c\x9c\xf9\x08\xd5\x06\xd7\xc9\x17\x78\x62\x13\x0f\x87\x9a\xbc\x56\x6c\xf8\xc2\xd0\x3a\x0c\xe0\xa0\xff\x1e\x00\x67\xe8\xbf\xcb\xdd\xd2\xe8\x2a\x1f\xd0\x77\x4c\x9d\xca\xdb\xa9\x3b\xfc\x24\x3c\xfa\xa5\x6c\x44\x49\x75\x5e\x44\x18\xdd\x3e\x7c\x41\x73\x43\xc8\x38\x7a\x21\x05\xbc\xa6\xd5\x84\x6a\x77\x8e\x90\x36\x77\x74\x48\xb2\x07\xf6\x6e\xe7\xe5\xa6\xd1\x69\xe3\x46\x7f\xd2\x80\x7f\x54\x24\xbc\xef\x84\xb0\x8c\x37\xd5\xc6\x1b\x4f\x8c\x29\xbb\xad\x8a\x14\xd2\x9c\xb4\x04\x53\x0c\x3b\x79\xc2\xef\x8d\x49\xd3\x31\xb9\x2c\xb4\x68\x63\xa2\xa3\xc9\x99\x4d\x25\x2b\x05\x03\x2c\xfd\xd4\x50\x4f\xc0\x65\x28\xa4\xba\x4c\x8e\x64\x72\x3d\xa6\x57\x81\x32\x4d\x0a\x7a\xd2\x80\xf0\x18\x75\x4c\xaa\xff\x84\x1f\x3d\xf1\x1a\x8a\xdd\x3f\x83\xb2\x98\xc1\x35\x99\xb1\x78\xba\x3e\xe6\xe2\x0d\xd8\x31\x17\xc7\xfc\x9e\x83\x8e\xf9\x80\xae\x37\xc0\x19\x6b\x03\x5c\x1d\x6b\x83\x31\x1d\xeb\xbd\x3c\x3b\x10\x5f\x8e\xc5\x93\xdd\xb1\x18\xc0\x8c\x75\x0a\xe9\x89\x10\x8e\x07\x48\x63\xf1\x18\x7a\x2c\x54\x6a\x0d\xcd\xdb\xc0\x70\x56\x67\x76\x47\x40\x3a\x56\x0f\xda\x41\x20\xdb\xb1\x82\xdf\xc7\xc6\x42\xa0\x3f\x56\x00\x8c\xf1\xe1\x35\xfc\x63\xc5\x57\xd1\xe6\xbd\x45\x39\xd6\x60\x9c\x35\xee\x7f\x96\xe5\xa6\xa4\x6f\x21\x89\x9a\xc6\x0d\xac\x3e\x6e\x0a\xe1\xa6\x59\xb9\xb1\x73\x6e\xca\xf2\x26\x24\x1e\x37\xf0\xc1\x78\xea\x06\x29\x3e\xb5\x4f\xaf\x69\x3c\x01\xed\x7c\xb8\x24\xef\x0a\x4f\xe1\x0d\xa2\x29\x67\xe2\xbd\x81\x29\xb4\x13\x53\xca\x27\x4d\x69\x20\x1d\xc5\xfc\x14\x34\x65\x20\x63\x4c\xe4\xcc\xe9\x9e\xa6\xfc\x5a\x9a\xbc\xbd\x38\x55\x6a\x9a\xd0\x5e\x04\x7b\x53\x1b\x02\x89\xa9\xad\xd9\x40\x82\xe7\x40\x85\x81\xa7\xdf\x99\xe6\x45\xf6\x97\xe0\x11\xb2\x9a\x17\xda\x5d\x8a\x15\x9f\xd4\xfc\x79\x29\x1e\x31\xad\x79\x81\xcd\xe5\xbc\xd1\x35\xaf\x50\x94\xf2\x6b\xfb\xbc\x10\xab\xcf\x6b\xd5\x0d\x94\xc6\x65\xbe\x77\x5c\x26\x8c\xcb\xb4\x93\x39\x05\xef\x44\x32\xd3\xd0\x9b\xb5\x27\x4d\xeb\x09\xc8\x62\x4f\xf3\x3d\x7c\x9d\x06\x63\x3f\xe9\xd4\xa7\x6f\x80\x83\x69\xfa\x2e\x0f\xe8\x5e\xd0\xd8\x51\x7e\x2a\xc1\xdc\x74\x2b\xe8\x87\xd7\xfe\xa0\xbe\x13\xd5\xeb\x7b\x09\x91\x6a\x3c\xbd\x9d\x8b\x09\x4d\x1c\x95\x7a\xd2\x64\x4d\xef\xf8\x59\x06\xed\xec\x15\xde\x6e\x7a\x34\xd9\xc1\x26\x26\x83\xff\xe9\x63\xa4\xe9\x53\xd0\x70\x85\x71\x64\x84\x38\x93\xa1\xc3\x44\x00\x3a\xfd\x49\x93\x80\x75\x32\x5a\x9c\x21\x08\xbd\x91\x9e\x6f\x62\x0d\xb4\x0d\x68\xf5\x84\xd7\x9d\xbc\x39\x34\x81\x47\x4b\xe2\xbd\xd0\x17\x5c\x4d\xca\x16\xf8\x2e\x4d\x1e\x8d\x4d\x5e\x3d\x99\xbc\x0a\x39\xc3\x4e\x8a\x33\xac\x82\x80\x8d\xf7\x0b\x6d\xdf\x9b\x14\x33\x16\xab\x2d\x3e\x16\x14\xac\x8a\x78\x70\x06\xb0\xd1\x0c\x98\xc4\x89\x15\x5e\x60\xba\xde\x80\xe9\xdf\x26\x9d\xab\x09\x08\x42\xe1\xb9\xe2\x83\xd5\x07\xd0\x9b\x2b\xb8\x2c\xb7\xc2\x14\xcf\x5b\xdb\x7c\xd2\xbc\x61\x16\xe7\x8d\x89\xdd\x94\xca\xed\x69\x3e\xd0\xd6\xa7\x33\xcc\x5c\x67\x79\xd2\xaa\x5b\x68\x29\x92\xd6\x7b\xd5\x60\xb5\xf7\x36\xf0\x6a\x99\x6f\xef\xc5\x94\x57\x6d\x56\xdb\x3d\xad\xc6\x2b\xea\xab\xf1\x13\xe9\x6a\xef\x27\xa6\xd5\x8c\x98\x7a\x35\x5e\xcd\x5e\xcd\x26\xc8\x57\x11\x8c\xac\xf6\x69\x58\x85\xd5\x78\xc6\xba\xda\xb4\x92\x56\x5b\xbc\xa7\xb8\xda\x57\xf1\xda\x79\x9a\xb9\xfa\xc9\x05\x5a\x9d\x9f\x83\x56\xf7\x96\x16\x43\xe9\xd5\x61\x45\x56\x6c\xd2\x12\x0d\xc5\x0b\xbc\x80\xe0\x79\xe5\x7c\x0d\x3d\x56\x41\xc2\x0b\x12\xff\x98\xcf\xf7\x3f\x03\x5f\xc9\xd8\x6e\x5f\xc9\x6b\xd5\xf4\x15\xe8\xdc\x57\xe0\xc7\xbe\xef\x3d\xf8\xaf\x40\x74\x5f\x69\xf8\xd9\xb8\xd2\x57\xba\x47\xfa\xca\x7b\x15\xeb\x0b\x85\xff\xf2\x83\xfa\x57\x2f\x83\x68\xbe\x10\x36\x5e\xdb\x8e\x8a\xbc\x14\x89\xdc\x06\xd6\x1a\x1b\x88\x1d\x0f\x12\x02\xa5\x2f\x82\xdb\xaf\x8e\xa1\x25\x7d\x75\x6a\xa0\x2f\xa3\xcc\xbf\xb6\xf1\x0b\xe2\xd7\xf2\xdb\x9b\x65\xda\x75\x04\x88\x9e\x88\xda\xbf\x56\x0a\xa6\xfb\xb5\x36\xdf\xd4\x8b\x81\x41\x10\x77\x7f\x2d\xd8\x6e\x08\x88\x81\xd5\x78\xf3\x27\xe9\x17\x33\xe5\x29\xf7\x97\x17\x25\x79\xf9\xfb\xeb\x25\x4b\x73\xa4\xab\x22\x6f\x82\x3c\x60\x7f\xff\x23\xde\xd2\x2d\x36\xd3\x0d\x7b\x07\x7b\x0b\xd2\x16\x32\x1a\x48\x1c\xd0\x15\x5a\xdd\x5b\x02\xc1\x74\xba\xb1\x6d\x6e\x19\x1d\x64\xa2\x10\xf8\xe8\x06\x3e\x86\x33\xb9\xdf\xef\x8a\xb7\x0a\x96\x96\x96\xfa\x46\x6c\x55\x90\xd0\x68\xdc\xba\xa5\x5b\xdf\x70\xf8\x56\xfd\x60\xa7\xdd\x6a\x01\x5a\xf8\xcd\xeb\x86\x91\xbc\x75\xa6\x9b\x5f\xaf\x6e\xd8\xc8\xfb\xd2\x97\x82\x13\x2c\xe5\x4d\x13\x79\x03\x4a\xde\x97\x31\x02\xbf\x61\xef\x6e\xdb\xd1\xbf\x1d\x78\x2c\x3b\x48\x49\xd8\x25\xb7\x35\xc0\xd6\x1b\x08\x94\xae\xe2\xb6\xf6\x01\x69\x6c\xca\x4b\x31\x37\xc2\xac\xdb\x06\xc2\xd8\x1b\xd6\xe7\x86\xae\xdc\xff\xee\x28\xdc\x5e\x8e\x74\x23\xae\x49\xb7\x73\xc7\xdc\xee\x3b\x48\x49\xf4\x37\x3c\xdc\xbc\x3d\x0a\x1f\xe3\x01\xc5\x60\x60\x6f\xee\xd0\xfc\x01\xe5\x25\xde\x9b\x86\xec\xe6\xcd\x8d\x9b\x0e\xfc\x81\x49\x7b\x20\xaf\x47\xe9\xf7\x1e\x5f\xf8\xa1\x88\x40\xea\x4f\xb7\x90\xf4\xa7\xe1\x89\x47\x6b\x7f\xee\xe9\xff\x00\x00\x00\xff\xff\x96\xd2\xdb\xc1\x3c\x33\x00\x00") + +func keysWordlistEnglishTxtBytes() ([]byte, error) { + return bindataRead( + _keysWordlistEnglishTxt, + "keys/wordlist/english.txt", + ) +} + +func keysWordlistEnglishTxt() (*asset, error) { + bytes, err := keysWordlistEnglishTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "keys/wordlist/english.txt", size: 13116, mode: os.FileMode(420), modTime: time.Unix(1497960590, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _keysWordlistJapaneseTxt = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x5c\x5c\xff\x72\xe2\xb8\xd2\xfd\x9f\xa7\x5e\xbc\x5c\x2f\x01\x3c\x0e\x71\x1c\xc7\x61\x58\x87\x8a\x2f\x43\x60\x80\x0c\x59\xb8\x93\x8f\x2c\x3c\x8c\x5f\xe4\x2b\xf5\xe9\x3e\xea\x99\xaa\x54\xea\x1c\x59\xd6\xcf\x56\x77\xab\x25\xd3\xf5\x93\xae\x3f\xe8\xfa\x45\xd7\xcf\xbb\x7e\xd5\x25\x45\xcf\x92\xca\xae\xdf\x92\x3c\x03\x8d\xba\xfe\xdf\x5d\x72\x03\x32\xee\xfa\x8b\x2e\xf9\x93\xef\x64\x5d\x32\x06\x9a\x76\xfd\x49\xd7\x6f\x8c\x58\x72\x11\x92\x93\x09\x79\xd9\xf5\x07\x44\x07\xa0\x4a\xfe\xaf\x40\x1e\xbb\x24\xef\xfa\x29\xc8\x53\xa8\xd1\x5e\x7d\xea\xfa\x19\xd0\xbc\xeb\x9f\x80\x9a\xae\x3f\x64\x86\x26\xfc\x25\x7d\xc7\x93\x51\xd7\xbf\x74\xfd\x21\xb9\x3e\x69\xd9\x8a\x56\xfa\xa4\xd5\xbd\xc8\x70\xfc\xa7\xeb\xe7\x7c\x78\xe9\x92\x91\x11\x57\xf4\xb2\xeb\xaf\x89\xf6\x92\x4d\x9f\x1c\x88\x4e\x1c\xb5\x13\xd3\x8e\x7e\x2c\x2e\x6c\xc5\xa5\xeb\xbf\x1a\x4a\x06\xd2\xa4\x9a\x5c\xeb\xbf\x76\x49\xd2\xf5\x77\x42\x42\x4b\x46\x5d\x1f\xe5\x84\x17\x58\x7f\x92\x76\xc9\x1f\x40\x37\x32\x8b\xb7\x5d\xff\x42\x5e\x11\xd5\x5d\xff\x91\xc4\x8f\x5a\x72\x23\x65\x44\x92\x5b\x5b\x42\x8d\x93\xae\xbf\xb2\xe1\x0a\x4f\x66\xcc\x99\x87\xa1\x30\x52\x58\xcf\x12\x99\x7f\x47\x0a\xa2\xaf\x26\x44\x81\x2c\x7d\x9e\xb5\x27\x3a\x00\x03\x88\x24\xda\x32\x08\x52\x29\x6f\x0f\x58\x3c\x50\x0e\x94\x89\xd8\x0e\x48\xd6\x2c\x24\xe3\x28\x0e\x28\xbd\x03\x59\x08\x8f\x44\x27\x96\x3d\xed\xfa\x6f\x98\x69\x21\x96\x5c\x60\x08\x74\x0d\x11\xb5\x3d\x5b\x44\x17\x11\xea\x81\x71\x7b\xaf\x82\x04\x0f\x44\xca\xff\xc3\x42\x1e\xbb\xe4\x2f\x4f\x72\x36\xeb\xa9\xeb\x5f\x0d\x25\x13\xa0\x19\x0b\x9e\x05\xe1\xef\xbf\x93\x8c\xfd\x13\xad\xe8\x2b\x2b\x9f\x77\xfd\xb4\x4b\x32\x56\x34\x97\x01\x8b\xcd\x7c\xf6\x48\x3b\xd5\x48\xc5\x37\x24\x57\x43\x41\x16\x12\x90\x85\x8c\x75\x4a\xf2\x48\xf4\x4a\xf4\x46\x74\x32\x94\x8c\xfc\x10\xb4\x10\xe6\x41\x5c\x83\xd6\xec\x17\xdf\xe3\x17\x74\x83\xa4\xf1\xd9\x16\x44\x4b\xff\xc2\xbf\x7c\x61\xd9\xf5\x1f\x0c\xd9\x7b\xaf\x7c\xba\x82\x70\x0e\x28\x7f\x40\xda\xac\x6d\x97\xfc\x41\x21\xda\xb1\xb2\x1d\xa7\x6a\xcf\xf9\x7f\x73\x69\x56\xcd\x3b\x27\xe4\xc0\xb4\x23\x87\xf9\x27\xd3\xce\x6c\xce\xd5\xd2\x82\xbc\xa6\x50\x8f\x20\x8d\x89\x42\x92\x58\x8b\x12\x91\x7e\xad\x36\x10\xac\x92\x64\x28\xfa\xb3\x20\x41\x7d\xa2\x19\x88\x6a\x96\x3d\x12\x6d\xb1\x30\x12\x85\x32\xe1\x1a\x0b\xda\x8b\xeb\x27\x89\x55\x66\xa2\x87\x8b\xae\xff\x8f\x0d\x43\x50\x08\x03\xa2\x94\x28\xb6\x27\x37\xb9\x08\x02\x9f\xb2\xa8\xa2\xeb\xdf\xd9\xca\xef\x33\xa9\x64\xb9\x85\x08\x48\x6c\x5b\x21\x3d\x0b\x24\x95\xf5\x90\x19\x92\x02\x53\x91\xce\x07\x20\xed\x46\x2a\x4b\xe5\x44\xf4\xc1\xac\x59\x97\xe4\x40\xb9\xe9\xcf\x35\xf9\x04\xe3\x9e\x8a\x5a\x68\xa4\x7d\x39\xdf\x9c\x8a\x0c\x4f\x49\x56\xee\x49\x18\xb1\x96\x44\x93\xef\xa9\xe5\x41\xb4\xde\x02\xc3\x93\x4a\x8f\xbf\x00\x55\x22\x88\xa9\x91\x30\xd8\x13\xac\xc5\x54\xa6\x6f\x40\xf4\x85\xe8\x96\xb3\x2c\xdc\xf4\x7b\x2a\xab\x49\x1b\xb3\xa0\x16\x27\x9f\x70\x00\x16\x1c\xc9\x05\x17\x6a\x2a\x0b\x6a\x0c\xa9\x4b\xa5\xc7\x39\x55\x48\xaa\x2b\xd2\x8d\x7c\x4b\xf4\xca\x6e\xad\xd9\xca\x35\x74\x05\xd0\x13\x47\x60\xcd\x97\xb6\x44\x3b\xd6\x7f\xea\xfa\x77\x44\xf7\x30\xed\xa9\xcc\xc5\xc4\x72\xc7\xbe\xca\xd2\x01\x12\x1b\x69\x64\x68\x95\x85\x31\x9a\x88\xd4\xd4\xe4\xba\x04\x40\xd6\xd6\x37\x51\x78\x56\x77\x20\x99\x49\x43\x32\xa6\x57\x93\xca\x4a\xa9\x1c\x49\x52\x1b\x46\xd7\xbe\x0c\x9a\x26\x95\xb1\xcf\x88\x4a\xa0\x82\xf6\x05\x64\x61\x43\x07\x3b\xe9\x88\xea\xae\xa1\xc8\xe9\x10\x4f\x40\x26\x44\x19\x97\x0a\xf8\x3d\x91\x6a\x55\x90\x93\x7b\xdb\x96\x13\x48\x0e\x34\xc2\xa4\x0f\x65\xbc\x22\xd2\xa7\x99\x4c\xbc\x16\x17\xdd\x82\xa1\x88\xeb\x9f\xcc\x56\x77\xfd\x25\x50\x2b\xae\x85\x56\xb9\xeb\xfa\xb7\x40\x67\x9d\x4c\x19\x15\xe1\x96\x87\x69\x61\x4e\x1f\x89\x76\x40\x37\x56\x79\x40\x27\x20\xb5\x50\x50\x4b\x1c\x9d\x40\xc6\xcc\x5d\x40\x18\x87\xaa\x75\xac\x8a\xc2\xfc\xc0\x94\xfc\x2b\x56\x0d\xc8\xdc\x7a\xa4\xf3\xf3\x97\xcf\xb9\x42\xce\x91\x8c\xeb\x98\x4b\x7e\x64\x5e\x42\x4d\xa2\x82\x32\x32\x0b\x98\x83\xa4\x6c\xee\xc8\x14\xc1\x85\xe4\x91\x68\xc6\x7a\x52\x8e\x3e\xc8\xd1\x17\xf5\xe1\x9e\xd8\xcc\x8e\xb8\x48\x47\x74\x94\x46\x34\xe3\x40\xaf\x9c\x73\xe1\x09\xf3\x84\x42\xe6\x20\x63\x0c\x34\xc9\x13\xd0\x04\x2e\xa8\xa4\x05\x15\xa9\x19\xbe\x50\x8d\x8d\xe8\x7a\x8d\x44\x5c\x62\x0f\x73\xef\x0d\x09\x57\xaf\x73\x4d\xce\xd7\x6c\x45\x8d\xfc\xb0\x16\xbe\x92\x82\x19\x4a\xdf\xe3\x92\xeb\x5a\x88\xe9\x8b\x11\x66\x04\xeb\x1a\x24\xbe\xf3\x08\x49\x01\x2a\x39\x3d\x22\xde\xf6\xc2\x5c\xc4\x2f\x27\x89\x8d\x6d\x68\x7b\x40\x34\xcf\x33\x9c\x7d\x90\x85\x97\x81\x17\x18\xe5\x91\xac\x14\x1d\xbf\x6f\x10\x27\x90\x95\xd4\xad\x2b\x00\x7c\xed\x25\xea\x95\xaf\xbd\x8a\xc2\x19\x73\x84\xde\x7c\xfb\x2f\xb0\xf5\x42\x92\xbe\xd4\xb1\xb2\xe1\x4b\xb0\x0d\xfc\x46\x12\x93\x29\x6e\x81\x84\x0d\x21\xc8\xc0\x44\x32\x19\x88\xe6\x7b\xef\x99\xc0\x7c\x5a\xf5\xb2\xec\xb1\xb7\x1c\x49\xc3\x34\xb9\xa0\x3a\x01\x99\xb2\x06\x2c\xc6\x3f\x49\x66\xd6\x78\x29\xc7\x93\x68\xa8\x46\xa6\x1f\xb5\x98\x31\x76\x70\x40\xaa\x1f\x27\xd0\x8f\x44\xea\xde\x4f\xbc\x87\x3f\xf6\xbb\xe2\xb1\x2e\x5a\x69\x0b\x48\xed\x1d\xab\xb1\x77\xb8\x41\xfe\x86\xf1\x23\x6f\x7d\xb1\x4b\x9f\x73\xe5\x9f\xe8\x02\x9e\xa8\x73\x28\x8d\x1c\x7b\xff\x70\xec\xf5\xf4\xc4\xfb\x74\x63\x2a\xed\x31\xc5\x77\xcc\xa5\x3c\xfe\x2d\x79\xc2\x96\x4f\xb0\x39\x1c\xd3\xb5\x18\xcb\x62\xbc\x27\x5a\x31\xeb\x03\x5e\x9f\xa0\x7b\x48\x6b\x58\x7b\x03\xf3\x39\xf1\x8a\x71\x22\x02\x9d\x71\x7a\xc0\x0b\x4f\x4a\x8e\xfe\x8b\xf7\xef\xc6\x22\xd6\x0f\x62\x1f\xb5\x7d\x3b\xbe\xb6\x67\x93\x4e\x58\x45\x63\x3f\x40\x67\xb6\xfe\xc2\xb4\x8b\x48\x22\x46\x3d\x2c\xfb\x09\x37\x92\x63\x11\x58\xf4\x41\x06\x16\xd2\x3b\x76\x03\x9b\x8c\x89\x32\x2b\x31\xb4\x2b\x37\x24\x1b\xa5\x09\x4c\x0c\xd2\x0a\x27\x81\xce\xb0\x8f\xbd\x54\x8f\xcd\xa4\xc4\x27\x0d\xdb\x54\xd8\x68\x06\xa4\x1b\x8b\x0c\x01\x1a\xa2\x16\x28\x78\xe1\x3d\xd1\xb2\x03\xbc\x9e\x49\x2f\x06\x86\x2c\x6d\xc8\x52\x54\xdf\x03\xe5\x44\x0b\x43\xf6\xc6\x98\xa5\x8c\x99\xef\x97\x2e\x64\xf2\xb7\x04\xca\xa5\xa1\x23\x23\x61\xfc\xee\x40\xa6\xba\x7e\xad\xb4\x82\xf5\x17\xbe\x59\x05\x2b\x29\x99\xb5\xf4\x69\x17\x43\xa1\xec\x2f\xe8\xf3\xa3\x97\xe7\x2f\xdc\x6a\xe3\x49\xe3\x17\x38\x92\x36\x7e\xa3\xf8\xc5\x36\xe4\xad\xef\x52\xcd\xe6\xc5\x26\xeb\xc6\x3a\xa3\xf9\xcd\x38\x75\x99\xac\x87\xdc\x90\x0d\x5e\xe3\xbb\x16\x97\x44\x26\x95\x0d\xd9\xa4\x17\xec\x89\xf9\xa4\x65\x45\x6d\xd7\xdf\x02\x2d\xd9\x8c\x57\x16\xf2\xca\x2a\xd7\x7c\xba\x86\x82\x03\xd2\x66\x7c\x17\x6f\xb9\x02\xd9\xb2\x75\x3b\x16\xb4\x93\x31\x6b\x40\xf6\x2c\xf5\x9d\x46\x25\xe3\xde\x35\xa3\x86\xca\xe8\x39\x66\xb2\xb2\xb4\xac\x33\xd3\x2e\xec\xfa\xd5\xc6\x2b\xf9\x43\xe3\x7a\xb1\x60\xb3\xc0\x08\xce\x3c\x8b\x25\xaa\xc8\x17\x3d\x1f\xb6\xc9\xe8\x50\x66\x62\x70\x30\xdf\xa2\x59\x64\x56\xf5\xc9\xd0\x1a\x23\x03\xee\xa3\x0d\x19\x97\x74\x46\x7b\x9d\x49\x06\xb4\xd9\x36\xbb\x40\xda\xe6\x8c\x15\x65\xcc\x97\xb3\xdd\x5f\x10\xf1\xc2\x02\xcc\xcc\xc7\xd4\x98\x12\x78\xf0\x6a\x8c\x38\xfd\x72\xcb\xb5\x9c\x23\xcc\x03\x94\x72\x9f\x0c\x92\x11\xdd\xfa\x64\x5d\x40\xb7\xe6\x0f\x0e\xf8\x64\xee\x9f\x34\xd0\x4c\xb9\x77\x0e\x41\x3e\x81\x62\x5d\x71\xbb\x90\x63\x1b\x8e\x42\x0a\xa6\x95\xac\xa5\x64\xb3\x4a\x46\xc9\x84\xc8\x90\xe4\xe6\xfa\x5f\x49\x62\xc1\xb5\x88\x5b\x66\x24\x8c\xbd\x8e\x87\xec\x1d\x44\x5f\xe4\xb4\xf4\xb7\xb6\x80\x97\x7c\xe7\xd9\xd7\xd3\x04\x29\x35\x67\x30\x17\x47\xaa\x60\xbd\x0b\xdf\xd0\x96\x32\x7e\x2b\x2b\xae\xc6\x8a\x93\x27\x61\x8a\x6f\x7b\x66\xea\x52\x9a\xe7\x9c\x6b\x2c\x97\xbd\xa9\xa6\x6d\xf1\x1f\x64\xc7\x9e\x1d\x89\xae\x7e\x73\x0d\xde\x30\x44\x1a\x45\x27\x87\x10\x63\x80\x7a\xa6\x30\x6b\xa2\x0f\x66\x1b\x43\xf1\xe5\xae\xab\x66\x87\x72\xd8\x47\x4c\xcd\xad\xca\x9f\x8e\x5d\x8c\x97\xe4\xe4\x8d\xcf\x19\xd4\xf6\x54\xc4\x70\x0d\x34\xa0\x9e\x9f\x7a\xbd\x09\x12\x91\x7a\x45\x77\x2e\x9e\xd9\xf2\xa1\xd6\x70\x67\xe1\xb2\x54\xb2\xf0\xe5\xb0\xb2\x32\x12\x45\xf0\x62\x6b\x23\xc9\x88\x6b\xfe\x0e\x26\x87\x48\x05\x13\xe4\xd9\x93\x85\x27\x2b\xb6\x30\xa8\x34\x43\xa6\x34\xee\x28\xd6\x77\x76\x16\x12\xb7\x1e\x77\xc1\xe9\x90\x2e\x4c\x29\x40\x92\x66\x7d\xa8\xd8\x81\x2a\x68\x56\xd9\xf0\x4c\xbd\x98\xdf\x31\xb2\x86\x68\xd1\x1b\x90\x9c\x9e\x04\xd9\xfb\x1f\xf9\x0d\x3b\xdd\xd2\x9e\x4f\x79\x46\x31\x55\x43\x61\xd5\xbd\x30\x46\x84\x27\xaa\x58\xa6\x16\x29\x8d\xd9\x96\xbe\x80\x0b\xc7\xa2\xf5\xfa\x07\x7c\xe2\x72\x9a\x82\xbb\xa3\xdc\x4b\x34\x2b\xac\xf0\xba\xe7\x43\x5b\x53\x31\x2f\x77\x44\x35\xd1\x15\xe8\x3b\x87\x6d\xcb\x4e\x6d\xd9\xf4\x3d\x25\xe4\xc0\xb4\x13\x7d\x8d\x3b\x31\x27\x5a\xbb\x1e\x01\x4c\x65\x11\x8d\xad\xf6\x60\x47\x2a\x43\x9a\xc1\x04\x66\x4a\x1d\x3f\x95\x45\x32\x35\x21\x73\xeb\x64\xca\x63\x8a\xa9\x86\x08\xb4\x91\x81\x8c\x88\x20\x75\x01\x65\x4c\xbb\xb3\x16\x3b\x9f\x6e\x6a\x61\xca\x9c\x24\xc6\x10\xc0\x6b\x93\x0c\xe7\xf0\x4d\x75\xe7\xe2\x5e\x5b\xfa\x56\xad\x7c\xb6\xb5\x7f\xb2\xb1\x79\x0a\xe4\xe4\x1b\x7f\x21\xba\xba\x86\x06\xa3\xca\xb7\x2d\xfa\x02\x12\x7a\x5b\x88\xec\xe5\x78\x5b\xac\x59\xff\x3b\xd1\x3b\x24\xf9\x9e\x1e\x65\xe1\xc3\x14\x85\x86\x59\x1d\x51\xf5\x73\x6f\x51\x55\x1d\x87\x7b\x0b\x8f\xc6\x32\x74\xf8\x0a\x0b\x75\xc4\x27\x8f\x44\x1a\xe3\xbc\xf7\x76\xae\x30\x3b\x97\x93\x34\xfe\x89\xee\x4a\x0b\x0b\x54\xc6\x4a\x96\x3e\xdb\xab\x7f\xb2\xf6\x4f\xf6\xbe\xd2\xb3\x6f\xff\xc5\xf5\x34\x48\x1c\x5b\x90\x8c\x30\x0d\xd1\x9d\x2d\xb8\xf5\xba\xa7\x6c\xdf\x8b\x9f\xda\x5a\x9a\x95\xa5\xbb\xad\xc2\x9b\xd9\x82\xf6\x88\x64\xed\x9f\xec\x59\xf9\x2d\x27\x2e\x8e\xee\x94\x6d\x28\x44\x09\x93\xc8\x62\x28\x10\xfb\x00\xaa\xd8\xf0\x9a\x95\xc5\x81\x56\xb5\x12\x0f\xed\x20\xbf\xcf\x30\x1e\x85\x1f\xf9\xc6\x77\xbd\x61\xa9\xd1\xf1\x2d\x10\x43\x06\x6a\x79\x6e\x06\xf2\xc6\xe2\x5b\xc4\xf1\x0a\x3f\x5d\x4b\x3e\x5d\xc9\x96\xe8\x86\xa4\x22\x7a\x33\x64\x42\xbd\x96\x61\x5e\x83\x6c\xf1\xbf\x67\x23\x72\xe1\xa8\xed\xa0\xb6\x04\x25\x43\xcc\xcd\x9e\xf5\x1d\xa0\x6a\x41\x8e\xec\xc8\x91\x19\x3e\x69\x95\xef\xa5\xd4\x78\xfc\x2b\x07\x19\x6e\xea\x2f\x74\x3b\xf0\xa4\x65\xe3\x2e\x36\x6e\x41\xb3\x7d\x81\xa9\x2d\x18\xef\x2c\xe8\x0b\x17\x54\x73\x82\xb4\x09\x66\xd6\x80\xd0\xab\xe0\x55\xa5\x44\xef\x40\x43\x1b\x4f\xf3\x91\x0b\x31\xb5\x5a\xf5\x24\x7a\x6b\x56\x70\x26\x33\x36\x05\xc9\xa5\xf2\x25\xc9\x84\x6f\x16\xdc\x78\x16\x3e\xca\x5a\x50\x77\x16\xbf\x29\xc5\xc2\x94\x62\xcc\x46\x89\x82\xea\x73\xa5\xad\x3d\x79\xef\xfa\x1b\x92\x7f\xfd\x93\x0b\x1b\x5a\x20\x64\x09\x34\x71\x95\xd8\x96\xfd\x41\xc3\xe6\xd2\xb6\xd2\xdc\x9e\x01\x89\xda\x41\x64\xbb\xf3\xa4\x60\x1e\x75\xda\x4a\x1f\x50\x7f\x30\x07\x28\x56\x12\x03\x53\xa5\x77\x64\x1f\x7e\x3b\x68\x2b\xa1\x84\x80\x34\xda\x04\x32\x81\x79\x45\x72\xcc\x70\x85\x40\x94\x3c\xfc\x2b\x65\x2f\x12\x8b\xcb\x59\x42\x4e\x3b\x5b\xc2\xb5\x04\xd2\xbd\x76\xc9\x75\x58\xfa\x4b\x17\x0f\x5c\xfa\x25\x83\x12\xa5\xf9\x23\xda\xd7\x96\x9a\xff\x81\x2b\x1b\xc9\x13\x96\xfd\x62\x1b\x8b\x9c\xd9\x2a\x16\xf5\xe8\xdf\x9e\xb3\xe9\x2d\xbd\xa6\xd2\x1c\x98\x41\x97\x24\xe0\x4b\x4e\xd4\xca\x27\xaf\xf8\xf6\x8a\x31\xeb\x92\x0a\xa2\xa4\xeb\x52\xd2\x65\xc7\xd6\x45\x9b\x19\xf7\xba\xa5\xc4\xcd\x75\x3c\xce\xcc\x7a\x46\x2c\x0f\x07\xfc\x3a\x21\x57\xff\xd2\x55\xdc\xd1\x89\x90\xb0\x8a\xa7\x3d\x1f\x60\x2e\x65\x69\x0e\xfd\xd9\x4d\xc9\x35\x5a\x72\x3d\x96\x8c\x28\x22\xc2\xf1\xdc\x43\xcc\x4d\x46\x07\x03\x92\xe4\x8c\x1c\x97\x8c\x33\x97\x7e\x0d\x96\x74\x5e\x80\xe2\xb6\xb9\xf4\x5e\x4b\x69\x5e\x0b\x66\xd3\x36\x0b\x7c\x52\xfb\x6c\x33\xeb\xa7\xf8\x2f\x44\x0b\xa2\x0b\xd1\xd5\x90\x39\x1a\x15\x37\xba\x15\x0f\xd2\x2a\xbb\x07\xf4\x82\x65\x5f\xf9\x2d\x93\x84\xe2\xa5\xc1\x15\x3b\x55\xc1\xb2\xf7\x34\x36\x6f\xc5\x8d\x30\xd0\x15\x17\x70\xc5\x1d\xcc\x23\x2d\xac\xb8\xe9\xe2\xc5\x54\xec\xd6\x23\x6f\x3d\x54\x22\x6d\x29\x0b\x6a\x10\x58\x02\x5a\x12\x5d\x81\xa2\x35\xab\xec\x2a\x83\x56\x11\x8f\x47\x2b\x9a\x0c\x41\xa6\xa8\x2b\x0a\x6f\x45\x3d\x00\xd4\xa2\x41\x6a\xe4\x1e\x29\x22\x38\xfd\xfd\x02\xb1\x12\x62\xea\xbf\xa2\x5a\xac\xc4\xb4\x5d\x0c\x59\x9a\x1e\xac\x01\x9d\x80\xf6\xac\xfd\xcd\xb7\x55\xaf\x2f\x08\x32\xdf\xb9\xa2\x09\xac\x44\x7b\xc4\x3e\x1f\x39\xba\x27\x66\xf8\xc9\x97\xce\xcc\x77\xe6\xd3\x0b\xd3\xd4\xcc\x55\xf4\x4e\x2b\x2c\x15\x24\x3f\xc2\xaf\x87\x0c\x56\x74\x5a\x2b\x2e\xa2\xca\x0d\x65\x10\xe9\x81\x27\xa9\x27\x23\x1b\xc9\x40\x26\xd4\x13\xd5\x6f\x3b\x6e\x3d\xa1\x74\xcd\x0e\x7c\xea\x4b\x8a\xe8\x81\xcd\xf9\x93\x57\xe7\x40\x66\x9e\xcc\x7d\x51\x8d\x7f\xc7\x8b\x8e\xee\x04\x33\xdf\xce\x8b\x3d\x89\x42\x25\x27\x4c\x28\xe3\x91\xea\xe2\xd1\x42\x5e\xb1\x17\xff\xf1\x2e\x21\x9e\xc7\x16\xfe\xc7\xef\x0f\xc1\xaf\x86\xc2\x7c\xbf\xd9\x3b\x1a\x68\xd6\xd7\xfe\xb2\x3b\x12\x03\xf2\x9c\xc6\x0d\xfc\xc5\x0f\xd6\x5f\x4e\x6c\x83\x0b\x91\x98\x58\x85\x3a\x66\x9c\xc1\x18\xd8\xa8\xa8\xa7\x2a\xaf\x97\x1e\x2d\x68\xf6\x27\x9f\xcc\x10\x68\x20\x5f\xb0\x11\x05\x07\xab\xa6\x6e\x01\xaa\x88\x82\xd1\x7c\xc2\x9d\xb2\x9e\x9e\xdb\x98\x06\x01\x19\x13\xa9\x15\x79\xf2\x07\xe3\x3c\xe8\x51\x3f\xaa\xb6\xfb\x24\x39\xc9\x23\xba\x5a\xeb\x26\xc5\x5e\x8b\x67\x71\x35\x22\xa2\x40\x7a\x27\xa6\xf6\x3e\x7d\xcd\x55\x50\x8b\xb2\xd2\xb4\x02\xfd\x78\xe2\x21\x49\x2d\xa4\x62\x86\x1a\xe1\x87\xda\x5f\xf4\xa8\xbd\x2e\x7a\xb2\x53\x95\x48\x56\xc8\xa3\x1a\xa8\x66\x64\xaa\xe6\xb5\x0b\x04\xe9\xb4\xbe\x3d\xcc\x50\x2d\xb2\x71\xc3\xca\x9f\xbc\x5e\x78\x92\x6d\xe8\x77\x28\xaa\x5a\x86\x4e\xbb\x7d\x64\xda\x07\xb4\x69\xcd\xf9\x7f\xe2\xba\xab\xc5\x8b\xd6\xfa\x2e\xd6\x39\x0b\x05\xd7\x3c\x81\xac\x65\xfd\xa2\xd5\xb8\xbf\x24\xce\x4c\x1d\x2c\xa4\x6c\x67\x6a\x59\x2e\x72\x99\xc5\x5e\xc8\x5c\x9f\xcd\x5c\xd6\xfe\x16\x62\xad\xae\xa4\xbc\x30\xf3\xfe\xfb\xcc\x3c\xc3\x96\x44\x9d\xc1\x28\x90\x33\x7f\x1c\x37\xe3\xc1\xca\xcc\xbc\xb8\x31\x5f\xc8\xb8\x6f\x9f\x21\x16\x4e\x94\x12\xe1\x84\x34\x65\xb6\x29\x51\xc1\x72\x6b\x56\xac\xda\x05\x68\x0a\xf4\x42\xfb\x37\x33\x0d\xa3\xc6\xff\xab\xf0\xf8\x24\x96\xfd\x42\x17\x70\xa6\x07\x72\xb2\xcc\x21\xb0\x33\x31\x66\x7f\xf3\xcd\x96\x61\x37\x90\x6f\xbe\x98\x1f\xfe\xc9\x3b\xd1\xc9\x25\x9b\x5a\x07\x19\xb1\x5e\xbd\x6f\x37\x13\xd1\xd3\x57\xf7\x50\x4e\x33\x89\xf2\x66\x40\x9f\xd8\xc4\xcd\x28\x28\x33\xda\x95\x19\x97\xc0\xcc\xdf\x96\x9b\x49\x35\xc7\x1e\x66\x1c\xb1\x0e\x24\x17\x56\x82\x06\x81\x22\x19\x13\x65\x50\xb2\x20\xf1\x3d\x15\x04\x94\x78\xcf\xe4\xd2\x17\x12\x34\x2c\x49\xed\x9f\xcc\x3c\xf9\x9b\xa8\xf1\x35\x44\x73\x31\xf3\xb1\xa1\x99\x8f\x0d\x81\x68\xb4\x0d\x64\x6b\x63\x1d\xc8\x0f\xbc\x83\x56\x9e\x88\xfe\x75\x6f\xab\x1c\x22\x4a\xe4\x8e\x2b\x90\x94\xb8\xd2\x6c\x9b\x09\x92\xfa\x32\x54\xfe\xbf\xc2\xed\x23\x1a\x51\xf8\x66\x7e\x2f\x06\x12\x9a\x3c\xe7\x6c\xcc\x4d\xff\xde\x61\x06\xc1\xb7\x3d\xbd\xbc\xaa\xc7\xa0\xf1\x8c\x62\xce\xc3\x11\xa0\x7b\x22\x35\x7c\x20\xcf\x9e\xac\x3d\x79\x37\x24\xdd\x26\x19\x01\xc5\x2b\x46\x73\xc6\xba\xe6\xbc\xc9\x31\xe7\x8d\xa1\x39\x57\xe6\xdc\x42\x23\x9a\xf5\x81\x59\x2b\x98\xa0\x39\xa7\x7d\x4e\x23\x31\x97\xbf\xdb\x1e\x63\x2a\xec\x7c\xcb\x52\x5b\xdf\x80\x17\x6a\x14\x3c\xf9\xe2\x07\xe4\x05\x71\x5c\x92\xc2\x3f\x99\xf9\x32\x56\x40\x2b\xde\xfa\x03\xf9\x2f\x26\x6f\x2e\xab\x71\xc8\xb6\xac\x71\x70\x32\x17\xe7\xef\x13\xe8\x93\xd3\xf6\xc9\xa9\xbc\xb0\xf2\x8b\xbd\x1b\x3c\xba\xdc\x50\x58\x86\x43\x90\x3e\x33\x24\xf8\x0f\x22\x97\x56\xfb\x5f\x7b\x76\xa1\x46\xef\x81\xce\x79\xdc\x31\xf7\xf1\x85\xb9\x3f\x65\x07\x79\xf0\xa4\xb2\xf6\xc8\x2a\x63\x43\x7e\x59\x5b\x7f\x23\xaa\x40\x74\xb2\x61\x72\x31\xd4\x86\x1b\x18\x1c\x46\x0d\x98\x3c\xa0\xb2\x6e\x7c\x48\x01\x44\x4d\xc1\x33\xae\x9d\xa0\xfa\x86\x37\x4f\x80\x6e\x91\xe7\x97\x53\xea\x86\x91\x06\x20\xed\xd3\x73\xe7\x2e\x8c\x63\x35\x3f\xdb\x4d\x94\x58\xa0\x9e\x4d\x83\xcc\x7d\x0b\x1a\xdf\x85\x38\x00\x3c\x5f\x8b\x75\xbc\x32\x50\x88\x87\x6b\xff\xe6\xd6\x57\xb0\xf3\x65\xe8\x86\x01\x65\x1c\x7e\xab\xe0\xe8\xc9\x4f\xdf\xd1\x33\xd1\x45\x03\x81\xb2\x5c\x90\x74\x95\x79\xb8\x35\x2e\xca\x0a\xa8\xef\xca\x48\xfc\x98\x9a\x32\x02\xb9\x21\x1a\x31\x0c\x01\x3e\x26\xca\x59\x54\x0a\x01\x8d\x91\xcc\x46\xa6\xb1\x36\x14\xd3\x2c\xfa\xd5\x50\x1a\x81\xb6\x40\x19\x64\xaa\xb1\x73\x51\x2d\xbf\x60\x03\x0a\xdf\xe8\x92\x25\x54\x3c\x68\x7a\xd6\x6d\x81\x98\xb0\xc6\x7b\x88\x8d\x39\x84\x39\xf9\x1c\x9f\xda\xf4\xf4\x43\x18\xfb\xae\xa5\xa1\x49\x69\xa4\xc0\x8a\xf5\xe8\x86\xb6\xc1\x15\x7d\x8c\xf8\xb3\x79\x0f\x03\x92\xe8\x3d\x80\x17\x44\x15\x4f\xfd\x9e\xed\xf2\xaf\x16\xbd\x64\xab\x56\x7e\x18\xd7\x52\x4f\x03\xb2\xe1\x88\x7c\xe7\x20\xe0\x16\x82\xb6\x6a\x4f\x29\x3b\x31\xeb\x07\xcb\xfa\x64\xf7\x2e\xd0\xfc\x0d\x55\xce\xb3\x28\x1a\xe4\x13\x57\xc3\xca\x0f\xa4\xee\xf9\x0f\x5e\x1a\xee\x51\x1a\x5c\x9c\xb7\x2e\x24\x6c\xb5\x1d\xd0\x35\x7a\xef\x57\x76\xb5\x30\x46\x96\x1a\xc5\x3c\xa1\x7c\x24\x63\xa8\xd8\xc6\x89\x49\x02\x0b\xa6\xc9\xd1\x2b\x6d\x64\x1e\xff\x60\xce\x67\xf3\x51\xb4\x61\x05\x5b\x55\x70\x5f\xdb\xd0\x47\x69\x18\x62\x6d\x54\x19\xba\x0c\xf7\x44\xa5\x4f\xa6\x0a\x79\x67\x75\x33\x5f\xc9\xdc\x44\xc6\x9d\x17\x3f\x33\xdc\xd3\x78\x67\xa4\xf1\xce\x08\xf2\xac\x99\xbc\x31\x41\x86\x5b\xe2\x3a\x44\xb5\x91\xc8\x67\x03\x2e\xdb\xa7\x7f\x72\x71\xef\x98\xdb\xf8\x6c\x8e\x44\x4b\x92\x11\x85\x66\x2f\xa8\xac\x17\xdc\xf3\x2d\x28\x07\x0b\x3b\xbf\xd6\x0c\x43\x66\x18\x33\x6d\x0c\xad\xb1\xf0\xa7\x57\x0b\xee\xd5\x17\x76\xce\xfd\x64\xc4\x92\x75\x71\x2f\x7c\xf9\x15\xab\xad\xbc\xb0\x2c\x38\xe4\x0b\x6a\xe9\x05\x07\x7b\xc1\x88\xeb\x42\xbf\xb1\x49\x34\x39\x1e\xfa\x2e\xb8\x81\x5b\x30\x70\xb4\xe0\x72\x12\x24\xbe\xcc\x82\xa3\xbd\xf0\x4a\x79\x81\xa0\x0d\xdd\x82\x05\xf7\x62\x0b\x19\xf7\x06\x48\x6f\xee\x00\xbd\x62\xa8\x17\xb6\xae\x5e\x7b\xfc\x22\xd0\x8e\x5b\x3e\x7a\x8c\x78\x5b\x57\x92\xd4\xab\xde\x85\xc9\x5e\x45\x82\x08\x35\x87\xd1\xbe\x55\x03\xba\xf6\x34\xca\x66\x77\x13\x17\xbf\x0e\x63\x58\x69\xda\x8e\xdc\xe6\xdf\x89\xed\x42\x9d\x58\xa9\xbb\xe5\x66\xbf\x35\x83\xb8\x00\x49\x99\x9c\xfa\x9b\x00\xad\x1e\x06\x4a\xcb\x5a\xdc\xd5\xef\xf9\xef\x06\x05\xd9\xc2\x6d\x79\x2d\xa4\xe5\x65\xe5\x16\x27\xdf\x86\x2c\xed\x9e\xaf\x47\x4b\xd3\x06\xf7\xcb\xda\xa9\xe1\x43\x41\x62\xf3\x5a\x09\x60\xf7\x99\x75\xcd\xb8\x7f\xcb\x73\xf7\x56\x56\xd9\x7f\x59\xdf\x8e\x19\x4e\xd0\x62\xf8\xa6\x31\x7e\xda\xd0\x52\x6b\xb6\x32\xc1\x59\xcf\x36\x68\x8d\x65\xb0\xef\x8c\x80\x90\xd5\x8e\x91\x5a\x19\xfd\x4f\xa2\xab\x35\x5f\x4f\x8a\x76\x24\xa1\x84\x25\xa3\x32\x40\x4b\xa2\x2b\x50\xfc\xb2\x6f\xc9\x89\x5a\x72\xe1\x2e\xd5\x43\x92\x9a\x97\x76\x51\x37\x27\xd1\x2b\x29\x4b\x1e\x9d\x2c\xfd\xc1\xcc\xd2\x7b\x40\x4b\x4a\xef\xd2\x3c\x9a\x98\x1c\x97\xc8\xd2\xbb\x2a\x20\x9f\x7c\xa2\xb1\xe8\x25\xef\xa3\x83\x64\x54\x86\x4b\x91\x86\xa0\x61\xbf\xe9\x29\x61\x5f\xcb\xf9\xe5\xa0\x06\xfc\x0e\xa8\xe6\x48\xcd\xf9\x74\xc1\x4d\xc7\xd2\x7b\x6d\x4b\x7f\xcc\xb2\x34\xe9\xc9\x50\x5d\xd8\x88\x33\xf9\xd3\xbd\x20\x6a\xe4\x9b\x68\x89\x31\x3c\x9d\x25\x55\x06\xd0\x2d\xeb\xda\xc9\x58\xdc\xf4\xec\x33\x57\x4d\x3e\xe1\xf2\x11\xc8\x11\xa1\xa1\x25\x8e\x47\x58\xce\x99\x63\x76\x61\x2d\x17\x19\x9c\x27\xce\xcd\x15\x01\x7a\x23\xc1\xfe\x62\x14\xcc\xe4\x2e\x45\xcb\xbf\x03\xe5\x88\x6f\x00\x35\x28\xe4\x9b\x37\x94\x4b\x7f\x00\xb2\xf4\x9b\x84\x25\x2d\xe4\x92\xbe\xe4\xd2\xdb\x4a\x90\x7b\x1b\x4a\xb7\x8b\x07\xa9\x88\xf4\xe8\xe0\x1b\x6d\xe1\xd2\x6c\x61\x2c\x9e\xd3\xef\x2e\x6d\x80\xfc\xcf\x46\xd3\xec\x1c\x4f\x20\x96\x66\xe0\xd8\x13\x0d\x04\x69\x17\xbe\xd9\x66\x5a\x95\xe8\x37\x1a\xbb\x57\x1a\x3b\x1c\x86\x4d\x90\x16\x6f\x61\xac\x7e\xbb\x85\x81\x87\xb7\x7c\x52\x19\x92\x83\xe7\x9e\x9e\x9e\x59\x89\xfa\x9d\xf1\x8a\xb7\x84\x57\x74\x87\x57\x74\x87\x57\x6c\xe7\x8a\xdf\x1a\xac\xec\x1a\xf1\x88\x44\xc5\x63\x85\xeb\x8e\x44\xf1\x4c\x18\x7c\xc9\x76\xe7\x38\xe9\x05\xd2\x23\xb9\x15\x55\xc0\x8a\xfa\x74\x05\x67\x1a\xa8\x64\x8b\x11\x91\x8e\xc3\x30\x67\x2d\x0d\xd3\x16\xbe\xf2\x5f\xae\xa9\x83\xe7\xcc\xd9\x32\x5c\x08\xb2\xf1\x39\x5f\x7d\x5b\x56\xb2\x74\x86\xe4\x6b\xb6\x77\xfd\x6b\xb2\x8d\xcd\x8e\x17\x9b\xe3\x55\xab\x57\x59\x68\xba\x37\x5f\xd1\x36\xaf\xa8\xb0\xa3\x31\x58\xe9\xc5\x59\x11\xc8\x15\xd5\xf4\xab\x0f\x59\xaf\x64\x55\xb1\x72\x15\xad\x16\xd9\x0a\x86\x6b\xd7\xfe\x02\xe0\xda\x7f\x0c\xb1\xf6\x47\xde\x20\x35\x91\xba\x10\x6b\xbf\xe5\x5c\x53\x50\xd6\x54\x60\x6b\xdc\xf9\x04\xd2\x30\xcf\x9a\x97\x71\x40\x4a\x2c\xf4\xb5\xac\x72\x68\x4e\x2d\xfb\x85\x6b\x6b\x0d\x55\x26\xeb\xf1\x0a\x8e\xea\x2a\x90\x0d\x8f\xfb\x84\x98\x29\x02\xd1\xae\xe9\x95\x98\x35\x75\xd8\x5a\x8f\x99\x45\x48\xd7\xd4\x5c\x40\x5a\xcb\xd5\xb2\x86\xb1\xbf\xb1\x12\x6c\x22\xd6\xf2\xe9\xcb\x1f\x40\x37\xd6\xd4\x80\xde\x89\x4e\x40\x13\xbe\x81\x2b\x3e\xef\x24\x7a\x7d\x7e\x23\xeb\x3a\x05\x1a\xf0\xe7\x15\x36\x3c\xa7\xdc\x70\x99\x6e\xb8\xfc\x36\x92\x6f\x09\xa4\x1b\xd0\x8d\x7d\xa6\x79\x25\xd1\x2b\x4c\x1b\xce\xc1\x86\x47\xc6\xdc\x01\x20\x55\x9d\xd7\x8d\xc5\x53\x77\x20\x0b\xef\x23\x09\x77\xa2\xb6\xe1\x4d\x00\xa0\x8c\x68\xca\x56\xc6\xd0\xd4\xc6\x7f\x00\xb2\x71\x1f\x80\xe4\xe4\xb5\xcf\x39\xf3\x05\x2e\x59\xe0\x9a\x79\xce\x2c\x4a\x43\x47\x1b\x6e\xf2\x36\x32\x3f\x18\x5d\xf3\x50\x2d\x77\xf2\xcb\xc7\x46\x1b\x9d\x17\xcb\x5c\x58\x45\xb6\xeb\xda\xd0\xa6\x6c\x7c\x30\x78\x63\x51\xa7\xf8\xe4\xc9\x5a\x96\xc4\x7b\x7f\x1b\xef\xa1\x6e\x68\x4c\x36\x7e\x63\xb5\xd1\x1d\x94\x0e\x84\xd8\x0f\xa2\x8b\x6b\x99\x08\xdc\xc6\xef\x90\x36\x3e\x22\xfb\x1d\x47\xe9\xd0\xed\xdf\xa9\x9f\xd5\xd2\xf3\x56\xc4\x77\x46\xa2\xbe\x8b\xd6\x53\xaf\xef\x3b\x0f\x98\xbe\x63\x45\x60\x8e\xbf\xe3\x47\x28\x80\x6e\xac\x44\x8d\xab\x69\xbc\x60\xcb\xe3\xb8\x2d\x97\xd5\x96\x71\x97\x2d\x2f\xff\x6e\xa5\xe6\x59\xcf\xae\x55\xeb\xb0\x6c\x79\x53\x05\xf7\xb6\xbe\x1a\x92\xd6\x6c\xe9\x35\x6d\xed\xc0\xac\x06\x99\x33\x4c\xb0\x65\xf0\x77\xcb\x0b\xb5\x5b\x93\xb0\x98\xac\xdf\x31\x6d\x19\xc4\x80\x77\x86\xa4\x13\x37\xc3\x5b\x2a\x8a\x2d\x5d\xaa\xad\x88\xdb\x48\xbc\xa3\x33\xc6\x63\xcb\xaf\x55\xb7\xfa\x91\xb8\x28\xa5\xad\xe8\x8e\x6b\x4f\x7f\x4b\x40\xdb\x12\x10\xbb\x9b\xe8\xcf\xa0\x6c\xa9\x3b\xb6\xf2\xfa\x03\x10\x9c\x9b\x11\xc9\xc8\x0a\x4e\xe2\x85\xef\xad\x85\xc8\x23\xb9\x25\x8a\xe5\xc4\xf7\xfc\x6c\xc9\xc5\x14\xa2\x7f\x88\xf4\x76\xe9\xd6\x6f\xc8\xb7\xce\x1f\x49\xc9\x55\xcb\xef\xb8\x39\xde\x49\x33\xff\x0b\xdb\xb6\xe3\x4d\xa6\x9d\x7d\x9e\x72\x05\x29\x64\xc4\x47\x24\xb5\x21\x99\xc6\x1d\xcf\x8e\x77\x8c\xe1\x0a\x12\x41\xd8\x59\x10\x28\x05\x59\xf0\xa2\xce\x8e\xa7\x5d\x3b\x5a\xd5\x1d\x6e\x38\x00\x7d\xb0\xd4\x4f\xa2\xf8\x3b\x2b\x3b\x5e\xa5\xdb\xd9\xaf\x01\x7c\x27\xd9\xc2\x28\xed\xfc\x3d\xf5\x9d\x7d\xca\x90\x81\x68\x88\x68\x47\x4d\xf1\x46\x57\x6d\xcf\x43\x8f\x37\xbd\x05\x23\x59\xdf\xb8\xeb\x79\xe3\xfd\x97\xbd\x8f\x0b\x83\xdc\x13\x55\x3e\xb9\x66\xd9\xd1\x22\xef\xbd\x45\x06\x59\xb0\xf8\x37\xf7\x82\xc5\x53\xf6\x74\x12\xf6\x74\xef\xf6\xb4\x2f\xf1\xd2\xc8\x9e\xd7\xc4\xf6\x74\xe2\x40\x62\x53\xf5\xc0\x69\x8f\xcb\x51\x86\xec\x69\x85\x8e\xbc\xd1\xa9\x90\x34\x2b\x52\x67\xfc\x87\x9e\xaa\xd8\x4b\x73\xa2\x86\x28\x06\x29\xf6\xfe\x42\xda\xde\x9f\x84\xee\xb9\x39\xda\x9b\x9b\x37\x22\xc9\xf9\xf6\x8b\x6f\x7e\xb4\x51\x7b\x6f\xa3\xf6\x5e\x83\xec\x4d\x69\xc4\x02\xa2\x47\xb9\x57\x1b\xe5\x72\xfe\xc3\x15\xb3\xf7\x3f\x4f\xb2\xe7\x1d\x7a\xa0\x77\x20\x31\xec\x22\xe5\x7b\x9c\x48\x63\xe9\xee\xa5\xc3\x13\xeb\x4f\x50\x22\x63\x2b\xc7\xf6\x10\x7b\x91\xde\x01\x11\xde\x33\xc5\xb2\xc7\x69\x4a\xd7\xff\xd3\x1a\x67\x3f\xd8\xb1\xa7\xad\x03\x1a\x7a\xc2\x91\x55\x57\x21\x27\x89\xa7\x72\x6f\xd0\x3a\x36\xe1\x89\xba\x6f\x7b\x6f\x5d\xf7\x7e\x2f\x05\xa2\x8a\xfa\x07\x6d\x21\x50\xcb\x0c\x4b\xdf\x90\x15\x3b\x14\x43\x89\x20\x3f\x88\x4e\xbe\xb1\xff\xe7\xc9\x27\x0f\x0e\xf7\xde\x6a\xee\x3b\x77\x63\x0d\x44\x35\xe9\x81\xf6\xeb\xc0\xd3\x9e\x03\x17\xca\x81\x63\x71\xe0\xf2\x38\x70\x79\x1c\xa8\x9c\x0f\xdc\xf7\x1c\x78\x4a\x77\x30\xe7\x37\x23\xd1\x82\x4a\x66\x2d\x65\xad\x9c\x58\xb0\xca\xe1\xbb\xfb\x6c\x31\xd6\xa0\x6b\xe9\x20\xeb\x66\x6c\x48\x64\xe8\x20\x8b\xe6\x0f\xd6\xf5\xcc\x12\x1b\x36\xb5\x85\x9b\x70\x30\xe9\xaf\x48\x2a\x66\x40\xad\x07\x56\xf9\x02\xc9\x3d\xf8\x2d\xd2\x3f\xf6\x03\x3d\x23\x92\x05\xab\x6b\xe9\x9b\x1c\x38\xaf\x07\x99\xd4\x7b\x88\xcd\xc1\xbc\xee\x96\xef\xac\x59\xdd\x96\x8d\xdd\x33\xed\x9d\xc3\x16\x83\x37\x07\xee\x99\x0e\xf6\x6b\x2d\x23\x12\x7d\xef\x6a\xb3\x60\x32\x00\xf4\x68\xdd\x0d\x2b\x67\x4a\x84\x5e\x5a\xdb\xdf\x2d\x8e\x89\xe1\xd4\x1f\x13\x59\x93\xa0\x41\x76\xbd\xe1\xe0\xad\xe5\x81\xdf\x73\x09\x72\x1b\x99\x03\x8d\xe8\x41\x96\x68\x44\x29\x51\x66\x28\x89\x95\x17\x4e\x06\xf5\x44\xb4\x25\x29\xac\xbf\xee\x46\xc2\xc1\xbb\xa3\xff\x70\xd5\x21\xf9\x87\x49\x98\x8b\xc7\x1f\x19\x4a\x3f\xea\xa1\xa7\xbc\x70\xf4\xdf\x74\x1c\xfd\xed\xa7\xff\xd9\xd7\x87\x19\x0b\x48\xb9\x81\x03\x39\x02\xe9\x3a\x3a\x52\xc1\x1c\x69\x70\x8e\xf4\x66\x8e\xb2\x7a\x1e\xd0\xaf\xa3\xfe\x52\x97\x05\xa2\x8e\x54\xd5\x47\xae\x9c\xa3\x2c\x9b\x2f\x40\x8f\x18\xde\x23\xae\x17\x01\xcd\x98\x6f\x06\x37\xe9\x48\x5f\xef\xa4\x47\x54\x42\x8e\x34\x36\x47\x1f\x7f\x3b\xf2\x84\xfe\xc8\x5f\xb0\x3a\x9a\xcd\x69\x49\x32\xa2\x82\x65\xbf\xf2\xbd\x15\xbb\xbe\x62\x15\x3b\x3e\xdd\xb3\x85\x07\x5f\xed\x4f\x66\xbd\x10\x5d\x0d\x99\x01\x38\xf2\x7c\xf4\x48\x91\x3d\x8a\x38\x16\x86\xb4\xea\x84\x63\x0d\x1f\x53\x9a\x7c\xd2\x53\x2e\x6d\xb2\x79\x92\xc7\xce\x9d\xaa\x9f\xec\xe0\x28\xe3\x13\x15\x28\x3c\x51\xe3\x86\x53\x06\x15\x9e\x9f\x3e\xca\xfb\xd3\x76\xb6\x03\x92\x8c\xe8\xce\xe7\x29\x7c\x51\x25\x91\xda\x93\x9f\xfe\xdc\x1b\x64\x4e\xa4\xc7\x9f\x3f\x3b\xf7\xab\x0b\x3f\xfd\x39\xf6\xcf\xce\x7e\x34\xe1\xa7\xf8\xa5\x13\x20\xdd\x68\x7c\xe8\x06\x5c\xe4\xec\x43\x37\xc5\xba\xf2\x91\xd3\xf6\x3f\x3f\xbd\x27\xfe\xf1\x9b\x59\xfc\xb0\x10\x63\xc5\x9c\xa5\xf5\xdb\xed\x05\x3f\x3a\xfb\x22\xeb\xcc\x21\x3b\xd3\x17\x84\xe1\xd2\xcd\xc9\xd9\x3e\xa0\xca\x49\x74\xf4\xcf\xfe\xa3\xa5\xb3\x7e\xa7\x64\x45\xc5\xef\x94\xce\x5c\x79\x67\xce\xc8\x99\x1d\x38\xfb\xd6\x7f\x72\x19\x9e\xb9\xe6\xce\xd4\x32\x67\x7a\x4d\x67\xce\xd4\x99\xee\xfb\x99\x87\xce\x67\x4a\xce\x99\x7a\xe8\xdc\xb9\xaf\x26\xcf\x5c\x94\x67\x5c\xff\x21\xd2\x3e\xea\x75\xec\x33\x4d\xd6\xbf\xf8\x59\x39\xdf\xa8\x5f\x3e\x37\x00\x2f\x89\x1a\xb6\x73\xc5\xfd\xce\x99\xf1\x9b\x33\x9d\x9f\x33\x9d\x76\xa0\x29\x11\x7b\xe0\xae\x43\x21\x6c\xb4\x81\x46\x8c\xdf\xfb\x00\xa9\x27\x7b\xe1\x71\xcd\x85\xb1\xc2\x0b\xbe\x56\x02\xd2\xe3\x8b\x8b\x18\xd8\x7e\x4f\xbf\x15\xb2\xf2\xbf\xf2\x0d\xb5\x89\x17\x44\x00\x81\xd6\xf0\xb4\x2f\xb2\x4b\x9f\x02\x6d\xf9\xae\x4a\xc2\x85\x91\xc1\x8b\x98\x8e\x3b\xa0\x21\x9f\x66\xfc\xac\xe0\xc2\x1f\x7e\x8c\x86\x33\xfe\xe0\xd9\x05\xba\x81\x28\xb3\x96\xbb\x4b\x36\x17\x8b\x7e\x87\x17\xae\xbc\x87\x71\xa5\xe1\xb8\x52\xfa\xae\xd4\x33\x57\x04\xa0\x0c\xc9\x54\x5d\x29\x5c\x57\x5a\xb2\xab\xfd\xe2\xc3\x00\xa4\xf6\x28\x96\x3a\x23\x7a\x61\x3b\x5a\x3a\x66\x57\x7f\x22\x77\xa5\x23\x72\xf5\x91\xd5\xab\x74\x61\x45\x84\x06\x96\xcc\x29\x5b\x75\xcb\xa9\x7a\xfb\xea\x77\xba\x57\xc6\xa3\xae\xdc\xdf\xc7\xa3\x8e\x2b\x2f\xdb\x5f\x7d\x70\xff\xca\xaf\x94\xae\x8c\x37\x5d\xdd\xe0\x4a\xfc\x40\x92\x03\xc2\x85\x23\xa0\x50\x93\x6e\x07\x06\x3d\xb7\x31\x50\x34\x24\xaa\x7a\xf6\x9d\x19\xbe\x94\x8c\x77\xf0\x03\xba\x63\x41\xa5\xed\x8d\x71\x2f\x3f\xfe\x7a\xaa\xf2\x37\xa0\x47\xfb\xcd\x46\xbd\xbe\xaf\x0d\xaa\x59\x79\x2d\x66\x47\xd1\xc9\x50\x10\xdf\x80\x66\xac\x62\xc6\x52\xb8\x8d\x0a\x84\x3f\x6e\x14\xc8\xce\x92\xc3\x30\x5e\x81\x86\x4c\xbb\xb1\x2f\xb6\x71\xdb\x4c\x55\x4b\x20\xd0\x60\x7a\x72\x9d\x78\x92\x7a\x32\xf4\x04\x4e\x95\xdd\x22\xb1\x19\x52\x0e\x39\x50\x52\x11\x41\x0b\x2b\x41\xf0\x04\x44\x5d\x3b\x25\x39\x8b\xba\x75\xbf\x60\x17\xf8\x83\xc8\x8e\xdc\x7d\x96\xd5\x10\xd0\x93\xbb\x78\x1d\xf8\x33\xcb\xbd\x58\x9a\xba\xa8\x7a\x87\x13\x97\x56\x95\xc0\x46\x2b\x81\xf7\xa1\x3f\x2c\xa9\xdf\xe3\xa0\xee\x84\x1f\xc5\xda\xa2\x0b\x49\x43\x3e\x44\x2c\x4b\x11\xce\xbc\x40\x62\xf4\x57\x7f\x12\x2a\xe3\xdb\xaf\xf6\xb6\xee\x3d\x13\xfc\xb0\x6b\x4e\x84\x13\xb0\x64\x60\x97\x1c\x92\x01\x45\x31\x8e\xf1\xc0\xb6\x41\x4a\x6a\x8f\xe8\x63\x46\x47\x3a\x19\x50\xaa\xe2\x8c\xf0\xfc\x37\x19\xd8\x6f\x05\x24\x03\xbb\x85\xa3\xe8\x87\x28\xbb\x64\x60\x3f\xdb\x9b\x0c\x4c\x19\x24\xb8\x64\x56\xb8\x66\xe8\x31\x78\x82\x0b\x64\x37\x5c\x77\xa9\xed\x0b\x14\xbd\x3b\x67\x20\x67\xea\x87\x21\xdd\x7c\x24\xa9\x59\xd4\x24\x75\xb7\xab\x12\xba\xd4\x09\x4d\x7c\x82\xef\x9d\xc7\x40\x0c\xe2\x05\xf2\x0d\x8d\x4d\xdd\x01\x55\x82\x26\x20\x83\x6a\x9c\x84\xbf\x49\xa8\x73\x37\x20\x8a\x69\x3c\x0c\x53\xfe\x48\x54\x13\xf1\x06\x4d\xbc\xb9\x19\x7f\x78\x34\x19\x9a\xe3\x90\xd8\x4f\x03\x5a\x45\xb9\xed\x2c\x02\x99\x32\xf9\xde\x37\xab\xe4\xab\x95\x6f\xc9\xdc\xa3\x1c\xe8\x85\xed\x5e\xb2\xac\x57\x9c\x9f\x31\x0f\xfc\xbd\x64\x68\x76\x3b\xa0\xd4\xca\x4a\x32\x0b\x58\x29\xd1\x59\x46\xe4\x2f\x05\xca\x2d\xec\xa2\xe4\x9e\x08\xd6\x5b\xc9\x73\x4f\x57\x6b\xc2\xcf\x69\xf4\x0b\x18\x45\xaa\xc7\x6f\x28\x90\x37\xec\xc1\x8d\x85\xe2\xe4\xaa\x2c\x2a\x1b\x51\xb2\x46\xee\xf7\x90\x94\xcc\x98\x3b\xb7\x1f\x88\x51\xa2\xc9\x53\xa6\xc1\x37\x0b\x68\xc6\xe2\xe6\x4c\x9b\xb3\xd4\x25\xdf\xd8\x1a\xb2\x81\x1a\xd9\xc1\xc9\xc4\x72\x9b\xee\x1d\xf1\xc7\x76\x48\xc6\x7c\xfb\x2f\xfd\x39\x16\xb1\x35\xe0\x6c\x4c\x32\x62\x51\x13\xeb\xaf\x29\x10\x1c\xca\x84\x61\x1e\xbb\xdb\x1f\xc9\xd8\xeb\x5f\x90\x47\x22\x55\x76\x63\xfb\x60\xa5\x10\x82\x0b\x44\xfa\x3b\x5d\xc9\xa4\x8b\x5f\x66\x28\xf9\x42\xa4\x83\x03\x82\x1f\x71\x8b\xd9\xb0\x81\x55\xf2\x49\x92\x41\x35\x4e\xf4\x47\x49\xb4\x00\xbd\x9e\x10\xc9\xd4\x93\xc2\xaa\x8f\xbb\x01\x25\x51\xdc\x27\xde\xee\x4f\x34\x42\x25\x24\xe3\x62\xcd\xec\xfa\xbb\x22\x7c\x53\xab\x64\xce\xdc\xb9\xf8\x6c\x2a\xe7\x2d\xd0\xa3\xcc\xd8\x4d\x4f\x25\xde\x54\x4e\x46\x61\xcd\x28\x0d\x99\x6d\x28\x13\xfe\x36\x52\x82\x5f\x37\xfa\x42\xf4\x83\xe8\xc4\xac\xd8\xcf\xe0\xc7\x7f\x45\x6f\xe0\x27\x87\xfa\x44\x88\xb2\x2b\xd1\xc5\x9f\x9b\xa3\x9d\xc8\x0f\xb3\xc8\x4f\x6a\x83\xd4\xee\x57\x88\x55\xeb\xa6\xbd\xf8\x31\xfa\xff\x07\x00\x00\xff\xff\xaa\x0a\xcc\xb8\xdf\x5e\x00\x00") + +func keysWordlistJapaneseTxtBytes() ([]byte, error) { + return bindataRead( + _keysWordlistJapaneseTxt, + "keys/wordlist/japanese.txt", + ) +} + +func keysWordlistJapaneseTxt() (*asset, error) { + bytes, err := keysWordlistJapaneseTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "keys/wordlist/japanese.txt", size: 24287, mode: os.FileMode(420), modTime: time.Unix(1497960590, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _keysWordlistSpanishTxt = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x34\x5b\xbb\x76\xfc\x2e\xaf\xed\x79\x4b\x8c\x65\x8f\xe6\x00\xe2\x27\xc0\x2b\x99\xb7\x49\x99\x62\x8a\xff\x4a\x97\xd6\x2f\x76\xd6\xde\xe4\x2b\x46\x98\x3b\xe8\x2e\x60\xee\xaf\x2d\x26\x0b\x71\xdb\xad\x48\x0d\x71\x93\x67\x0c\x71\x53\xf1\x81\x52\x3b\xe3\xce\xb4\x12\xae\x42\x8f\x2f\x26\xea\x21\x6e\x53\x32\x32\xb3\x5b\x88\x29\x6e\xd1\x91\xec\x52\x34\x86\x98\x92\xb0\x38\xe9\xfd\x53\x43\x4c\xa2\x43\x90\xe4\x13\x95\x52\x31\x5a\x92\x36\xa2\x87\xfb\x2b\x29\x66\x4a\x39\x3a\xc7\xa8\xf7\x77\x88\xc9\x4e\x41\xc6\x38\xcc\xd0\x8b\x09\x81\xeb\x0b\xc9\x64\xe3\xb9\x2b\x13\x71\x8e\x31\x3b\x4a\x77\x65\xd3\xbd\xe8\x40\xed\x6e\x9c\x28\xee\xe6\xd8\xcc\x3e\x63\x8d\x48\x32\x1a\xdd\xdf\x2e\x16\xe2\x21\x89\x6d\x0e\xfd\x5b\xf2\xa1\x75\xe5\xbd\x70\x91\xa7\xe6\x10\x4f\x65\xa3\xd3\xea\xfd\x8e\x48\x3b\x86\x38\x6d\x95\xba\x9c\x2b\x55\x14\x4e\x34\x98\xbb\xa1\xef\xd4\xcc\x1c\x30\xfc\xb0\xd3\x00\xdd\x2d\x44\x75\x09\x51\x7b\x46\xbf\xa7\xec\x2e\x2f\xa4\x58\xe5\x73\x76\xa0\x2c\xc7\xe4\xf7\x57\xc5\x47\xd9\x9c\x05\x5e\x62\x88\x79\x8b\xe1\xfe\xca\xdb\x2c\x21\xe6\x14\xf3\x8e\xaa\x5d\x50\x23\x27\xdb\xc9\x13\x83\x66\xf1\xc1\x42\xc2\x43\x33\xb0\x4a\x2a\xe4\xd3\x76\xee\x34\x2b\x29\x9d\x75\x91\x25\xeb\x85\xf5\x67\xce\x52\xc8\x14\xb9\xdc\x6f\xd2\x37\x8f\x05\xe5\x85\xd2\x45\x15\x62\x31\x8f\xe9\x28\x9a\x05\x6b\xcf\x2f\x34\x2b\x71\xcb\x82\xa4\x0e\x26\xcd\x80\x84\x12\x1d\xfb\x2f\xb1\x13\xad\x65\xfb\x4b\x14\xc3\x14\x6e\xbd\x28\x5b\x68\x1f\x71\x0f\xb1\x18\xc6\x6a\x11\xe8\x2a\x2d\x63\x6d\x35\x3d\x08\x35\x56\xa6\x18\xb7\xee\x98\xb3\xee\xf7\x77\x0d\xb1\x92\x0b\xef\xaf\x7a\x4e\xf0\x68\xd5\x9c\x41\x87\xaa\x05\xb9\xfb\xdd\x43\xac\x8b\x68\x75\x08\x98\xa1\x0e\x3d\x27\xea\x86\x3d\x91\xcc\x98\x01\x49\x97\x3a\x6b\xc2\xac\xf7\x7f\x91\xcc\x76\xff\x27\x4f\x66\x2d\xc4\x16\x49\xf2\x16\x3d\x62\xfd\x4d\x06\xf7\xd1\xd0\xbe\x65\x4d\xac\x34\xa0\xb7\x99\x03\x0d\xcd\x3e\x91\x71\xa9\x3b\x28\xd1\xdc\x88\xd8\x36\xa5\x83\x42\x6d\x62\x9b\x4e\x82\x38\x66\x0c\x14\x8a\xfb\xcb\x37\x1d\x6e\xfc\xb0\x1c\xa2\x6f\x93\xac\xe7\xe9\x41\x22\x38\x24\xd9\x39\xa4\xef\x9a\x81\x10\xdf\x27\xdb\x0b\x10\xe1\x14\x31\x57\xe9\x21\x7a\xf9\x63\x5f\xaf\xf7\x37\xf2\x06\x52\x7b\x23\x20\x47\xb8\xcb\x09\xbc\xb9\xdb\x0b\x70\x82\x5f\xb8\x7c\x1f\xca\x75\x76\xfe\x30\x66\x5f\x0c\xd0\x93\x54\x88\x6a\x97\x73\x52\x8c\xbb\x30\xd7\x41\xbd\xfe\xc7\x5a\x5d\x33\x61\xa7\x58\x76\x10\xaf\x5b\xd9\xb8\xaf\xde\x04\x5b\xef\x63\xad\xbe\x8f\x95\x9b\xec\x37\x0b\x3b\x4c\x8e\x32\xe2\x93\xf0\xdf\x14\x24\x1e\xe2\x58\xc3\x0f\xc1\x40\x43\x81\x8b\x41\x8e\xbf\xbf\x86\x81\xe4\xc3\x23\x50\x33\xb8\x9f\x71\xff\xd6\x10\xe7\x1e\x5f\x80\xa0\xd4\x3c\x25\xc4\x89\x69\x67\x59\x43\xcd\x2e\xe4\xda\x39\xb0\xfe\x0b\xdc\x70\xc5\x9a\x04\x09\x16\x76\xe1\x4b\x72\xa6\x26\xb9\x64\xc1\x3e\x7c\xbe\x42\xbc\x96\x02\xb9\x14\xf8\xf8\xc4\xbc\x9f\x73\x8f\x80\xd8\xf0\x2b\x1e\x4b\xa0\x29\x23\x2f\xc3\x2c\xaf\xfb\x97\x9c\xf2\x9a\x07\x44\xf7\x35\x73\xd8\xe2\x16\x01\xcc\xc3\x16\xd3\x43\xc2\x16\x1f\x20\xda\x16\x35\x23\x03\xe1\xde\x62\x8e\xf5\x85\xb2\x9c\x30\xe5\x46\x35\xb0\xc5\xb2\xdd\xbf\x61\x8b\x35\x19\xe0\x8e\x06\x60\xd6\x2d\x3a\xc7\x74\x96\x7b\xd5\x17\x12\xb7\xb0\xdd\x5f\x3d\x61\xfb\x5b\xec\x63\x0d\xd4\x21\xce\x5b\x1c\x31\xb3\x78\x88\xaf\xc9\x41\xb8\x2d\x8e\x39\x38\xe8\x2f\xd6\x89\x7d\x6c\xb2\xdd\xdf\x80\x8a\xd9\x04\xd2\xb6\x49\x67\x45\xe7\xe7\xd0\x18\x36\x85\xd8\x6e\x2a\x35\x6c\x5a\x4f\x0b\x5b\x5e\x6b\xcc\x06\x52\x6e\x79\xf6\x18\x36\xc3\x6f\xd3\xca\xc4\xc2\x66\x09\x5f\x69\x15\xec\x04\x72\x22\x59\x25\x99\x00\xac\xb3\x59\x66\xff\x82\x4d\x5a\xdd\xe3\x8e\x04\xe2\x48\x1b\xb6\x59\xed\xf7\x97\x86\xcd\x1c\x48\x32\x07\x97\x6e\xd6\x39\x35\xa8\xb0\xd9\xb8\xdf\x35\x6c\xf7\xcf\x25\x9c\xe7\x15\x73\xd8\x3c\x5e\x16\x96\xdd\xdb\x5c\xd2\x23\x22\xb9\x24\x6c\x4e\x9d\xb2\xb9\x72\x0b\xae\x98\xdb\xb9\x58\xca\xd3\xe6\x06\x76\xd9\x9c\x43\x3b\x34\xff\xe6\xb3\xb3\x2d\x78\x7a\x9b\x49\x08\x41\xcd\x09\xb5\xb7\x4d\xf9\x0c\xdb\x3c\x16\xc5\xe6\x41\x42\xdc\xbf\x40\xd9\xd4\xe1\x68\x96\xd9\xd1\x37\x8e\x36\x3d\x13\x62\xeb\xb3\x83\x7f\xb6\x39\x22\x16\x30\x5f\xe8\x0b\x93\x8c\x25\xa6\xb8\x41\x5d\xa7\x48\xa4\x26\x18\xf1\x90\x62\x8a\xa8\xd9\xef\xaf\x4b\x1c\x1f\xc2\x3a\x7e\x1f\xf7\x77\x48\xf1\x7e\xef\x28\xd1\x02\x66\x4d\xf1\x89\xcc\x73\x8d\x9b\xf1\x83\x22\x47\x0a\xd5\x08\xfb\x43\xa8\xc0\x7a\x8a\x39\x0b\x60\x41\x9f\x6c\x6c\x76\xa1\x9e\x05\x65\x63\x8f\x22\x6b\x71\x45\x2b\x93\x66\x21\xdd\x5f\x35\x71\x09\x75\x57\x4c\x52\x25\xa3\x47\x3d\xa1\x15\x53\xac\x9a\x98\x1d\xc8\x40\x37\x02\xae\x25\xd9\x86\x9c\xf5\x90\x62\x8b\x2f\x40\x1d\x6b\xe1\x0d\x04\x48\x91\x1e\x40\x8a\x6d\x82\x84\x29\x12\x07\xbe\xb1\xf3\xfd\xe5\x49\x30\x9d\x43\x65\xa4\xe8\x27\xa1\x42\x66\x52\xf4\x8a\xee\xde\xfe\xea\xb8\x10\xe7\x77\x27\x48\x28\xe8\xc2\xf2\xde\x58\x34\xb8\xe5\x61\x9e\xd0\x15\xa4\x4b\x50\x37\x98\x62\xb2\xd3\xcb\x42\x92\xcd\x20\x5b\x49\xa0\xb4\x93\xec\x18\x40\x32\x70\x7e\x7f\x67\x81\xa9\x4f\x92\xe1\xfd\x20\x3f\xd9\x72\xe9\xa6\x24\x55\x41\x4f\xa9\x83\x7d\x1c\x48\xa1\xfb\x93\xc4\x49\x69\x59\xe5\x60\xf0\x24\x4e\x63\x9d\xee\xef\xde\x64\x0f\x49\xd8\xe9\x11\x49\xc5\x47\xcc\x92\x98\x2d\xed\xfe\x45\x4a\x5b\x9a\x1e\xb1\x11\x3a\x33\xca\x26\x0a\x77\x64\x59\x9b\xf4\xa0\xc0\xa6\x87\x61\xe4\xc7\xa4\xaa\x4d\x8f\xd9\x30\xa1\xa6\x4c\xac\xaa\x9c\x06\x98\x09\x59\x00\x1f\x32\xe9\x01\xdc\xeb\xb9\x50\xa9\x60\x09\x8a\x50\x52\x20\x5a\x2b\x86\xd2\xe6\xb0\x4c\x49\x9d\x15\x3e\xc9\x07\xda\xd9\x82\x0d\x26\x19\x2d\xd3\x39\x48\x39\x56\x00\x8c\x97\x63\x17\xc0\x0b\x50\xa9\xc3\x53\xe6\x24\xf9\x7e\x2f\xfe\x31\xe2\xd6\xfe\x5c\xd3\x64\xe9\x41\x0e\x5c\x2a\x26\x19\x66\xbc\x7f\x76\xb8\x20\x09\x86\x3b\xd9\xc1\xf6\x70\x47\x93\x3d\x04\x23\xda\x13\x9a\x22\xc1\x55\x48\xd0\x40\xc9\x32\xd9\xca\xb2\x9c\xca\x32\x78\x05\xc9\xf2\x1a\x32\xe7\x95\x2b\xac\x9a\x85\x85\x05\x5a\x15\x29\xc7\x2d\x4a\xca\xff\x94\x35\x65\x69\x40\x92\xd5\x1d\x2d\xaa\x70\x9e\x7a\xb2\xc8\x28\x21\x56\xfb\x5f\x29\xf9\xda\x40\x2f\x6b\x0a\xe8\x71\x89\xbf\x39\xf4\x37\x52\xa8\xdd\x64\xbe\xff\x15\x1b\xe7\x77\xe7\x38\x7d\xc1\x02\xd1\x31\x98\x76\xba\x9b\x62\x4c\x07\x2a\x5d\x22\x61\x5a\x99\xfb\x8d\x15\xba\x14\x36\x7d\x03\x2a\xe2\x87\xe4\xda\xd8\x5d\xbb\xf6\x90\x1c\x76\x37\xf9\xfd\xb3\x90\xee\xe0\x18\x56\x4f\x76\x9f\xaf\x90\x66\x24\xd3\xcf\x48\xbe\x98\x91\x9c\x39\x37\x02\x44\x18\x09\xb2\x0a\x3c\xcc\xa5\x2a\xe6\x62\x7f\xb8\xfa\x2c\xe4\x6a\xa7\x5c\x80\x0a\xef\x2f\x4d\x08\x0e\xb2\xb9\x11\xb2\x39\xdd\xe6\x34\xe1\x3a\xa2\x09\x36\x3f\x2b\xd7\x32\x8d\xb0\x2d\x2d\xf0\xdb\x28\x65\xf4\x5e\xd2\x74\xa5\xec\x4d\x5f\x90\x93\x0c\xed\x61\x87\x12\xdb\x69\x76\x31\xe5\x1e\x21\x78\x3b\xbc\x8e\x1c\x76\xd9\xc4\xc3\x7e\x7f\x6f\xc8\xdc\xdf\x29\xee\x31\xec\x92\xd4\xc3\x2e\x68\x26\x87\xd4\x8e\xa2\x43\x2b\x0b\x61\xc5\x77\xc9\x07\xd8\x69\x47\x70\xc4\x56\x19\x46\x6b\x97\x62\x8e\xb6\x70\xab\x76\xa9\x23\x62\x82\xe5\x45\xee\x02\x53\x84\x62\x77\xec\x61\x97\xbe\xbc\x8b\x5d\xe0\x76\xed\xd2\xe1\xe8\x23\xad\x93\x23\xf6\xa1\xab\xf6\xba\xdf\x48\x07\x55\xf4\x2e\x43\x2a\x56\x2c\xf0\x4f\x76\x10\x73\xd7\xb8\x65\x43\xb2\x83\xc2\xbb\xfe\xb9\xef\xbb\xc2\xd3\xd9\x35\x22\xb6\xd9\x75\x9b\x4f\x24\x0c\x99\xf6\x25\x66\xbb\x02\xa7\xbb\xca\x2b\xec\x7a\xdc\xef\x04\x1c\xe8\x89\x69\x35\xaf\xb1\xf2\xc4\xa6\xb5\x42\x3f\xed\xea\x82\x20\x6d\x57\xd7\x93\xc5\xd0\xa4\xbb\x76\x81\xda\xdd\xb5\x1f\x1e\x31\xd2\x85\x8e\x17\x57\x6f\x08\x27\x76\x4b\x00\xb0\x2a\xbb\x15\xba\x11\xbb\x55\xfc\xb0\x14\xa3\xe7\xbc\x9b\xc3\x5f\xdc\x0d\xc4\xdb\xad\xe3\x07\xd2\x79\x3c\x41\xea\xdd\xed\x8c\x61\xa7\x25\xd8\xb9\x73\x46\xb2\xfb\x5c\x53\xcf\x8c\x19\xee\x5f\x7c\x42\xcd\xed\xe4\x88\x7d\x52\xb7\xee\xb0\x44\xf7\xf7\x86\xc0\x43\x36\x20\x03\x3e\x81\x07\xa8\x51\x01\x47\x9b\x07\x81\x6e\x92\xfd\x2f\x90\x94\x5d\x11\x53\x1a\x3e\x06\x6b\x27\x6c\xb5\x1c\xdc\xbe\x1c\x9a\xe2\x2b\xc8\x53\xf0\x2b\x2d\x5b\x90\x2c\x07\x71\x2e\xd0\x26\x8e\x64\x29\x7e\xc9\x72\xa1\x67\xd6\xd6\x25\xdc\xdf\x59\xd9\x48\x3f\xd8\xc8\xa0\x79\x24\x33\x1e\x96\xb2\x81\xee\xb2\xe2\x5f\x29\xf6\xb7\x94\xd2\xa0\x73\xa4\x34\xee\x14\xd3\x09\x13\x97\x1e\x83\x54\x6e\xaa\x26\x06\x68\x52\xd3\x63\x1e\x82\x14\x7c\x21\x88\xa8\x58\x0c\xe2\x49\x3d\x80\x67\xa9\x87\x78\x41\x7a\xd2\xc1\x94\xaa\x67\x41\xdb\x1c\x13\x7a\x9a\x17\x24\x2e\x6c\xdb\xe3\x27\x13\xb9\xff\xc3\x2e\xea\x58\x23\x0d\x67\xee\x82\xe2\x96\x4a\xfe\xbc\xbf\x1b\x1c\x29\xf9\x37\xb5\x59\x10\xd7\x97\x05\xe9\xf0\x39\x90\xc0\x53\x91\x0e\xbd\xeb\x48\x5d\x37\xe5\x07\x77\xdc\x05\x51\x61\x90\x7e\x88\x33\x99\xe2\xec\xdd\x20\x8b\xd2\x1b\xb4\xa6\xf4\xc6\x3d\xf5\x66\x9d\xc9\xc4\xaa\xfb\xbf\x79\xbf\x03\xb4\x0a\x86\x03\x9e\x10\x8b\xa0\xf5\x98\x47\x0c\x32\x60\x14\x65\x88\x57\xac\x70\x40\xad\xc9\xa8\x98\xec\x62\x5c\x28\x57\xcc\x13\x7d\xaf\x45\xad\x8b\x67\x05\xf2\xc1\x63\x0b\xf9\x40\x6c\x1b\xe4\x83\xe7\x22\xf2\x91\xe0\x08\xc8\xc7\x6a\xf9\x41\x09\x90\x0f\x45\x70\x2b\x1f\x2b\x3c\xba\xbf\x3f\x94\x95\x8d\x76\x53\x3e\xfe\xc2\x49\xf9\x68\x06\xa1\x95\x8f\xe1\x52\x2c\x1c\xf7\xd7\xe6\x58\x0c\x3e\xa0\xc1\x8e\x98\x1e\xd8\xec\x71\x7f\x41\x06\x0f\xcc\xef\xe1\x88\xc0\xdb\x01\x3f\xee\x88\x70\x33\x0e\x3a\x87\x47\xcc\x9d\x10\x6b\x3d\xa0\xdb\x8e\x58\x34\x2b\x53\x63\x95\x47\xf0\xce\x11\xbd\xc4\xc4\x72\x37\x8c\xea\x1d\xdf\x5d\xc2\x11\x87\x9e\xf8\x9e\x9c\xe0\xe2\x64\x1f\xe1\x80\x0f\xe3\x16\x0e\x3a\xcd\x87\x64\x7d\x85\x43\x90\x77\x8c\x22\x08\xc5\x8e\xfb\xdb\xa1\x38\x0f\x71\x76\x93\x4e\x17\xfc\x50\x9e\x1c\x1c\x4a\x35\x7b\x28\x96\xa6\x50\xec\x87\xfe\x59\xed\x43\x39\xa8\xee\x18\x50\xe9\x2d\x1d\x2a\x19\x80\xcd\x68\x1b\x0e\x45\x28\x1a\x0e\x7d\x72\x80\x27\x9a\x02\x3f\x9a\x61\xc4\x0f\xec\x12\x3d\x32\xec\xce\xa1\x18\xb4\x02\x8d\x5a\x41\x0d\x68\xe8\x81\x72\x07\x4e\x72\x4c\x06\x88\xb8\xe7\xc8\x6b\x47\x50\x41\x47\x36\x96\x40\xb1\x1d\x19\x4a\xf1\xc8\xf7\x2f\x2a\x6c\xc3\x2e\xc1\xc6\x87\x9d\xb0\xc3\x87\x51\xf9\x1c\x06\x22\x1f\x96\xb3\x60\x78\xab\x3b\x20\x27\xe1\x89\xd0\x61\x3e\x88\x48\x73\x04\x56\x07\x38\xf4\x30\x34\xf5\x98\x22\x08\xe2\xeb\x2c\xea\xf0\x58\x41\x4c\x27\x0d\x3c\xce\x1d\x89\xdc\x6f\x47\x52\xd1\x10\x52\x7d\x38\x24\xea\x70\x6e\xc6\xb9\xfe\x09\xcf\xec\x98\xd4\xda\x94\x0f\x94\x81\x82\x13\x2e\xfd\x31\xeb\x1f\x8e\x27\x02\x91\x63\xfa\x5a\xf7\x24\xd9\x66\xc7\xd4\xf7\xef\xd8\xc0\x04\x73\x40\x1d\x9e\x31\xc1\x3f\x3b\xe3\x11\x7b\x38\x23\x1c\xb4\x13\x21\xfa\x19\x59\x9a\x57\xec\x78\x92\xdf\xce\x88\xf0\xec\x8c\xd0\xd6\xe7\x3a\xc7\x39\x23\x3c\x9b\x33\xc2\xce\x9d\xd1\xe3\x53\x90\xbc\x50\xd4\x97\x07\x75\x46\x0a\xe5\x19\x07\x5a\x5c\x9a\xe1\xd9\x9f\x52\xa0\xb5\x4f\x81\xaa\x3f\xa5\x86\xf3\xfe\xa6\x72\x3a\xa5\x2a\xe1\x90\x70\x8a\xc7\x95\xf3\xff\xe5\x21\x86\xa7\x74\x0c\xa5\x27\xf5\xec\xa9\xa5\xc6\x8e\x56\x0a\x5d\x74\x2a\x06\xc9\x60\x76\x0f\x67\x46\x10\x7a\x66\xc3\xee\x4f\xcb\xf8\x1d\x06\x08\xe1\x38\x2d\x37\x09\x27\xe2\xbd\xd3\xe0\x08\x9c\xe6\x60\xb1\x13\xd1\x65\x38\xc1\x1b\xa7\x0d\x41\x39\x88\x79\x3a\xe4\xf2\xf4\xfb\xeb\x80\x4f\x7d\x3a\x14\xee\xe9\x08\x24\x4e\x8f\xf0\x2e\x4e\x87\xe7\x7a\x3a\x6d\xe9\xb9\x42\xcc\xd3\xb5\xb1\x0c\xd5\x20\xe3\xe9\xd6\x0d\xa3\xdd\xbf\x68\x34\xa1\x51\x4e\x9f\x85\xb0\x59\x38\xe7\xda\xd6\x8c\x2b\xe3\x3b\xd6\x3e\x85\x6b\x9a\xa4\xc5\x64\x70\x73\x4e\xb5\x0a\xd8\xf9\x3d\xe2\x6a\xd1\xb9\xac\x49\x9c\x3f\x22\x5c\x9a\xc7\xfd\x05\x97\xe6\x11\xb7\xcc\x32\xb8\x82\x0f\xa8\x99\x40\x4d\xf3\x88\x79\x95\x17\x84\x9f\x8f\xe8\x20\xda\x23\xbe\xf0\x63\x9c\xf6\x90\x8d\xa7\x3a\x0f\xba\x67\x0f\xfa\x2e\x0f\xc9\xb0\x21\x0f\x81\x3c\x3c\xa4\xac\x1a\xf8\x7d\x0f\xf1\x82\x25\x3c\xee\x6f\x37\x41\xf6\x42\x29\x43\x89\x87\xc2\xe5\x09\x8f\xfb\x4d\x5f\xe9\xa1\xa7\x4a\x95\xf0\x80\x74\x3f\xb4\xa0\x97\x22\xfe\xd2\x18\x1e\x96\x80\xe5\x87\xc1\x17\x7f\x18\x10\x80\xc2\x27\x00\x7d\xc2\x87\xc1\x7b\x78\x58\x35\xd4\x57\xd6\x2e\x50\xa0\xd0\x1e\x3c\x2d\x7e\x18\xac\x40\x78\xd8\xa7\x85\xc7\x84\x99\x7f\x4c\x9e\x62\x3f\x26\x4f\x56\x1f\x44\xff\x63\xca\x05\x08\x2f\xfe\x01\x65\xf0\x98\x7f\x5b\xf8\x2d\xb0\x7e\x8f\x59\x34\xef\x82\x14\x99\xba\xb3\x89\x47\x44\xbc\xf8\x18\x16\x14\xbe\x7d\xd0\x5d\x62\x0e\xba\x2b\x78\x0a\xae\x76\xb6\xa0\x67\x96\xae\x11\xe9\xfd\x1b\xf4\x9c\x68\x91\xe5\x64\x32\x3b\x85\x55\x4b\x84\x0c\xac\x68\x5d\x0b\x4d\x8f\x96\xb6\xa0\xc0\x4f\xd1\xb2\xec\x86\x96\x36\xa1\xf3\xa1\xec\x10\x2a\xdf\xef\xba\x6b\x92\x00\xb7\x6c\x20\xa1\x22\xd5\x7a\xd0\x7a\x6b\x5d\xe2\xa4\x95\x3e\x8c\xd6\x42\x7f\x54\x6b\x99\x15\xb5\x15\x32\xa9\xb5\xd3\x99\xd1\xda\x07\x59\x4f\x61\xdc\x11\xc1\xdd\xef\x3a\xb4\xa0\x66\x00\x2b\x5a\xef\x5f\x60\x53\xeb\xa5\xb4\xa3\xea\x31\x28\x38\x5b\x7d\x9d\x49\x6a\xcf\x04\x08\xda\x9f\x71\x8b\xf9\x7e\x23\xc5\x16\x9f\xb1\xac\xc4\xe3\x86\x4a\xdf\x61\x2b\x9e\x64\xda\x27\x4f\xef\x9e\xf1\x55\x58\x26\x87\x84\xa7\xb8\x42\xb1\x3c\xb5\x42\xdd\x3f\xcd\x2b\x78\xf5\x69\x6e\x1b\x92\x4b\x6a\x78\xda\x67\x0c\xcf\x29\x88\xf8\x9f\x53\x2e\xe9\x48\x5e\xe1\x39\x4f\x7a\x72\xcf\x79\x1a\xc0\xe4\x08\x93\x28\x78\x4e\x44\xab\xcf\x59\x4f\xcc\x38\xeb\x2a\x02\xbe\x9f\xf7\x6f\x53\x84\x4c\x4f\x7a\x8c\x4f\x9e\xd0\x3e\xe7\x25\x55\x73\x78\xce\x17\xf8\xf0\xff\xe0\x51\xfc\x9f\x41\x33\xe6\xb8\xa9\x05\xe8\x19\x42\x47\xc9\x8e\xcf\x1d\x51\x53\xc8\xf1\x64\x60\x94\xef\xaf\xd3\x11\xc1\xe6\x78\xc2\x30\xe4\x08\xae\xce\x11\x71\x63\xbe\xbf\x0a\x64\x0d\x69\x8b\x1c\x81\x2d\x2a\x44\x33\xc7\x7a\x32\xa2\x5b\x87\x84\xf9\xfe\x6a\xfa\x0a\x99\xde\x5d\x8e\x88\x68\xf2\xfd\xd5\xc7\x1a\x7a\x30\x37\xe4\x03\xdf\xea\x21\xc7\xe9\x92\x43\x8e\xf0\x38\x73\x7c\x59\xc8\x60\xcc\x2c\x7f\x06\x18\x36\x50\x00\xe1\x5b\x64\xc1\x5a\xe4\xfc\xab\x39\x57\xc8\x95\xe5\x09\x11\xc8\x52\xcf\x19\x91\x60\x33\x70\xfe\x00\xd9\xd0\x1a\xa3\x27\x70\xf7\x2a\x18\x9c\x62\x60\x23\x72\x61\x84\x4f\x81\x0d\xca\xba\x41\xd6\x76\x7c\xb8\x85\xac\x09\x93\xde\xef\x1d\xd3\x2a\x82\x92\x80\x58\x1f\x8b\x84\xe0\x66\x3d\x85\xcd\xb0\xb3\xfb\x5d\xe0\x26\x67\x25\xf3\x64\x2d\x0d\xe8\xd6\x9a\x50\x06\xe3\x9b\xef\x77\x15\x74\xaa\x50\xd5\x48\x59\x0f\x3f\x8f\xdd\xff\x4d\x45\x2b\xe8\xc8\xcc\xb3\x6f\xb8\xdd\xce\x84\x23\xc1\x7b\xc8\x20\x16\x60\x21\xe4\x4e\x79\x06\x91\x33\xaf\x84\x72\x96\xba\x12\xa2\x33\x9b\xaf\xe4\xc2\x06\xf2\xbc\x34\x06\xda\x99\xfc\xe7\xa8\x67\x4b\xcc\xc0\x7d\xc9\xf7\xcf\x09\xf7\x2e\xdb\x89\x99\xa0\xba\x40\x46\x84\xd7\xd9\xe0\x01\x50\x56\x32\xa3\x99\x3c\x11\x6b\xe6\xc9\x39\xe1\x8d\x64\x72\xcc\xac\xd2\x43\x9e\x0d\x9f\x3c\x57\xcf\x13\x2b\x9c\xaf\x50\x62\x82\xa5\x29\x11\x1a\xb9\xc4\x1d\x1b\x2b\x71\x77\x01\x84\x6d\x2f\x51\xd8\xa3\xc4\x43\x51\x75\x2e\x88\x82\xfb\x8d\xfe\x19\xc1\x4e\x59\xf7\x4b\x85\xa7\xc5\x25\x66\x54\x97\xfb\x0b\x70\xe3\xf7\x1c\xa1\xf0\xac\xb7\x44\xe0\xbc\xc4\xca\xd0\xb7\xd0\xf4\x97\x58\x95\xbe\x77\x81\x47\xc3\x52\x36\xe9\x84\x1c\xf7\xfe\x0f\x8c\x5d\xe0\x81\x97\xfb\xeb\xdf\x54\xe6\xd0\xd4\x39\xa8\x0b\xf3\x87\x66\x24\xd0\x84\x25\xf2\xca\xa3\xdc\x5f\x5e\x8c\xa5\x94\xaa\x12\x7d\x48\x47\xf2\x42\xbf\xce\xf1\x3a\xcf\x03\x4b\xec\x7a\xa1\x70\x70\xe0\x41\x3f\xb5\xc4\xa1\xd8\x26\x2f\x1d\xcb\xfd\xf5\x01\x6d\x56\xe2\xa7\xa1\xc9\xcb\x3c\xc5\x50\xe8\x0e\x16\xd9\xd7\xee\x65\x57\x4c\xfb\xbd\x4f\xe6\x9e\xba\x4a\x9f\xe8\x21\xe0\x03\x24\x5c\x0a\x02\x7c\x4c\x81\x40\x09\xb0\xc3\xf5\x29\xf4\x53\x8a\xd4\xfb\x37\x14\xf1\x04\x95\x50\xe0\xbd\x9c\x53\x30\x2c\x3d\x80\x82\x2d\x48\x5f\xa3\x00\x41\x08\x4b\x50\x3b\x8c\xcd\x49\x31\x79\x25\xcc\xac\xb0\x3f\x05\x3a\xbd\xa8\xf0\xae\x85\xd6\xad\x00\x55\x9a\xe3\xc9\x82\x4c\x83\x51\x34\xaf\x95\x71\x93\xc4\xf1\x0a\xd6\xa1\x55\xff\xca\xc0\x39\x45\xad\x49\x28\xf4\x96\x8a\x02\x87\xda\x17\xb6\xb4\x73\xd8\xce\xb6\x90\xd8\xc2\xe5\x5a\x7a\xc0\x2d\xfa\x5f\x1c\x5a\x6c\x47\x66\x87\x41\x2f\x06\xce\x33\xd2\xdd\x60\x22\x8b\x65\xe1\x37\x04\xb1\xd8\x0a\x7d\x8b\x15\x0c\x8f\x20\x3f\x31\x15\x8e\x00\xf6\x2f\xb6\x1a\xc0\xa1\x29\x46\x0f\xab\x18\x6f\xc2\x8a\xd1\x0f\x06\x96\x99\x71\x7e\x77\xd6\x43\xd3\x14\xeb\x1c\xac\x33\x04\x2d\xc6\xeb\xcc\x42\xa1\x2c\xf7\xcf\x85\x9d\x18\xb8\x64\x52\x38\xe6\x8e\x46\x53\x10\x99\x14\x1e\x48\x96\x49\x8b\x59\x26\x44\x04\xd9\x13\x72\x33\x9f\xe8\x4f\xe2\xaf\x83\xd1\x32\x33\x21\x19\x7f\xde\xff\x09\x26\x9d\x8e\x05\x50\xc2\xee\xdf\x9e\x26\x30\x31\xbb\x10\x9e\xab\x50\xd9\xae\x67\x0b\xf5\xfe\x42\xe4\x57\xe3\x42\x1f\xec\x18\x72\x70\x0b\x6b\x5c\x61\x40\x8d\x60\xd0\x1a\x79\xe8\x5b\x63\x8f\x39\xd4\x38\x16\xc4\xb6\x6a\x1c\x9c\xb2\xde\x5f\xb3\x0b\xda\x5f\xac\xbc\x30\xc4\xc5\x63\xfb\x2a\xb0\x44\xf5\xfe\xe6\xa9\x4e\xa5\xe2\xaa\x72\x1a\x4b\x05\x7c\x52\xa9\xb7\x2b\xfc\x31\x64\x06\xc0\x1c\xac\xb8\xd8\xf8\x82\xfe\xa8\xbc\xe6\xa9\x90\xbe\xaa\xb2\x65\x94\xb0\xad\xde\xff\xc9\x8b\x09\xa6\x79\x8f\xd5\xe2\x92\x1c\xaa\x6d\x59\x5e\x31\x54\x83\x55\xa9\xf7\x0f\x99\xaf\x52\x3c\x2a\x83\xa3\xca\x73\xaf\x0a\x8f\xba\xda\xd0\xc4\x8a\x0b\xce\x47\xb5\x0b\xc4\xa8\xc6\x45\xcd\x4d\x42\x9d\x29\x86\x7a\xff\xa6\x2c\x28\xd9\xe9\x45\xf3\x20\xac\xd2\x07\xac\xb0\xf4\x80\xaf\x50\x27\xd1\xfb\x5b\xc0\xe5\x75\x0e\x4c\x68\xb1\x6b\x0f\xc6\x9b\x2b\xdb\xb4\x37\x24\x4f\xec\xc0\xe0\xa3\xda\x0a\x6b\x6d\xeb\xe2\xd8\xb5\x6d\xeb\x10\xcd\x36\x2c\x00\x01\x9f\x31\x4e\xb3\x74\x7f\x43\x91\x61\x4b\x50\x62\x06\xac\x10\x99\x96\x5c\x82\xa5\x11\x2f\x7c\x8f\xb9\x31\xcb\xd3\x4a\x4b\x3c\x44\x87\xe6\x07\xd3\x1a\x6d\x9b\x41\xa3\xd8\xae\xa0\x9b\xf1\x64\xc2\xd6\x39\xa2\x1d\x74\x41\x6d\x9d\x2f\xd9\xb1\xce\x68\x69\x27\x8c\xc7\xb4\x86\x68\xd0\x9e\x16\x2c\xc7\x60\x59\x20\x1c\x96\x0f\xa0\xcd\x32\xd8\x82\x57\x10\x3c\x98\xe6\x89\x9a\xe5\x0b\x44\xb1\xb2\x65\x3d\x2d\x18\x8c\xaf\xc1\x79\xb0\x86\x00\xd8\xda\x62\xc0\xfb\xa7\x01\x8f\xd6\xf8\x44\xc2\x96\x5f\xb9\xde\x58\xdc\x3f\x8d\x27\x23\xc6\x0b\x6d\x0b\xe6\x7f\x4c\xcb\x93\x39\x47\x92\xc3\xfd\xe3\x1b\xa2\x44\xaa\x4f\xc8\x2a\xaa\xe5\x19\x51\x71\x12\x67\x7e\xc2\x19\x34\x3f\x27\x68\x67\xbe\x8e\x18\xcd\xf5\x64\x5b\xea\x54\xc3\x36\xfd\xdf\x3a\x07\x36\xde\x51\x5b\x8f\x3c\xc5\xb4\x9e\x20\x5a\xd6\xe5\x85\xd1\x40\x0d\x8a\xa8\x0d\xaa\x09\x03\xcf\xda\xb5\x66\xbc\xc0\x02\xf7\xcf\x07\x37\xfe\x71\xbf\x4f\xe8\x0c\xfb\x5c\x13\xbe\xe0\x93\x37\x9e\xe0\x34\x9a\xc5\x16\x05\x73\x37\xc4\xe0\x35\x86\x06\x53\xd8\xe2\xfd\xee\x28\x7a\x46\x47\x2e\xf3\x8a\xad\xc5\x9c\x98\x83\x0e\x68\xf7\x57\xc6\x04\x8d\x97\x62\x2d\x66\x5b\x09\x88\xdd\x62\xc5\x2f\x66\xb4\xaa\xca\x4e\x95\x2e\x46\x8b\xf7\x7f\x3c\x9a\x6c\xb1\xdd\x5f\x80\x92\x01\xb9\xfd\x16\xff\xd1\x2d\x6d\x7c\x20\xd0\xa2\x33\x08\x6f\xd1\x65\x07\x54\x96\x19\xc6\xf4\x16\x39\x35\x70\xc5\xbc\xc7\x83\x79\xf6\xee\xec\x0d\xd5\xd3\xe2\xf2\xc3\x1a\xd8\xb7\x21\xe6\x0e\x2d\x2e\xa0\x28\xa0\x74\x34\x5e\x61\x35\x9e\x84\x34\x70\x70\x8b\x9f\x6c\x2f\x91\x57\xc7\x4d\x68\xb2\x1a\x58\x31\x22\x79\x20\xb3\x63\x77\x82\xa8\xa7\x51\xaf\x34\xd1\x2a\xa1\x49\xe6\x77\xde\x79\x7c\xd8\x24\x0b\xba\x64\x05\x07\x37\xc9\x59\x9e\x4c\x09\x20\xd4\x0d\xe6\xb3\x81\xf7\xd1\x6d\xdd\xfd\x35\x59\xd0\x50\xd4\x60\x34\x9a\xfc\x5b\x47\xb9\x6d\x2d\xc1\x61\x9f\x9b\xd0\x26\xb4\x75\x45\xd6\x84\xbe\x02\x22\xa3\xc4\x76\x99\x65\x45\xb9\x13\xe7\xf4\xde\x8d\xb3\x75\x02\xcc\x7e\x7f\x77\x58\xc1\x06\x8e\x83\x1f\xdb\xee\xef\x11\xb9\xba\xe1\xf7\x0f\xb4\x4d\x93\x17\x7e\x93\xb5\x3c\xae\x6b\x9a\x1e\x5c\xa0\x0a\x7e\x3b\x56\xa4\xf4\x2d\x9b\x72\x25\xfa\x84\xd7\xd8\x94\xa8\xd0\x6c\x60\x35\x2d\x4a\x9d\xb1\xb6\xa3\x15\x4e\x76\xd3\xca\xe6\x6b\x68\x08\x75\xd3\x86\x4f\x27\x8d\x94\x38\xd1\xce\x5b\xac\xc6\x7d\xd0\x5b\x6d\xba\xc8\xa2\x2f\xec\x20\xc7\x05\x2b\xc0\xe0\xe7\x27\x21\x86\xce\x02\x63\xdd\x32\x04\xa0\xd1\xc1\x6c\x79\x62\x6d\x99\xa6\xa3\xf1\xe2\xac\xc1\x35\x6d\x46\x5c\x52\x31\x35\x13\xb4\x31\xe9\x90\xbc\x66\x64\x77\xcb\x52\x01\x35\xad\x42\x48\x71\xb3\x0c\x76\xb1\x02\x2d\xd4\x8c\xa7\x37\x8d\xb3\x58\xc1\x46\xa8\x45\x9a\xf9\xd2\x17\x6d\xd9\xe8\x06\x91\x46\x65\x17\xd6\x76\x85\xfd\x6d\x06\x2d\xd8\x6c\xac\xd3\xde\x46\x81\x6e\x30\xd6\x8d\x17\x00\xcd\x25\xd9\x0b\xc9\x39\x89\x47\x97\xa2\x2c\x86\xda\x6c\x0e\xd5\xde\x5c\x2e\x96\x91\xa4\x7e\xbf\x6b\x82\x41\x6d\xae\x7f\x52\xe0\x0a\xf5\xde\xdc\xd0\x83\xaf\x74\x9a\x5b\x5a\x5d\x6d\x9f\xd4\x09\x6e\xa4\xa1\xdb\xc1\x87\x2e\xcd\xed\x74\x92\xd3\x0d\xcb\x74\x2b\x64\x1f\xa7\x8f\xd2\xdc\x1a\x67\x84\xb6\xe1\xa4\x53\x36\x70\xd1\xef\x96\xc9\x86\x33\x3d\x60\x5a\xda\x84\xa6\x6c\x70\x35\x90\xa1\x8e\xff\x53\xa7\x6d\xe6\x13\x99\x0c\x49\x9a\x99\x31\x4d\x9b\xb9\xb1\x06\x2b\x23\xbd\xf8\x4c\xa6\x81\x09\x33\x13\x64\x80\xe1\x09\x2e\x0b\x6d\xfa\xfd\x1d\xfe\x4d\x81\x17\xf1\x6f\x42\x0b\xfe\x9b\x52\x56\xc6\x85\x49\xb7\xf0\x6f\xd2\x6a\xc3\x31\x2f\xd0\xe8\x70\xba\x93\x20\x81\x9e\xf7\xfb\x8b\x77\x20\x1e\x37\x8d\x80\xf8\x5c\x94\xf3\xb8\x6b\x8a\x39\x38\x23\x04\xa2\xc3\x23\x28\xec\xeb\xbc\xcf\x11\x97\x06\xe7\xe1\x83\x23\x28\xdd\x99\x1b\x80\x9d\x35\x9d\x8d\x59\xf0\x09\xf0\x42\x96\x97\x9a\x2e\xff\x7b\x52\xe8\xf2\xf7\xda\xc0\x65\xbd\x6e\x71\xe1\x2b\x0e\x17\xbe\x62\x80\x29\x1c\x31\xf0\xc5\xc6\x0b\x95\xeb\x02\xd7\x25\xb9\x30\x3b\x08\x79\xbd\x07\x8d\xe9\xb2\xf3\x28\xd6\x65\x67\x0c\xe5\x72\x50\xfb\xb8\xac\xc3\x59\x97\xf5\x6a\xc7\xe5\x98\xa7\xa2\xfc\x84\xe4\x3b\x6f\x68\x5c\xce\x8c\x26\x27\x19\xcb\xe5\x71\x7f\xa3\x25\x84\x77\x1d\xc8\xd2\xb8\xb9\x64\xee\x49\xb2\x5c\x4c\x14\x6e\x88\x43\xcd\xb1\x61\xb6\x67\x70\xd2\xc1\x65\x45\x11\x3c\xdf\x77\xa9\x08\x77\x5d\x78\x68\xe4\xd4\x0b\x2e\x8d\x67\x03\x2e\x4d\x06\x4b\x9b\x71\xe6\x36\x34\x07\x97\x8e\x5f\x8a\x44\x47\x87\x42\x70\xe9\x4d\xd8\xa1\x2f\x38\x8b\x60\x89\x43\x1d\xd9\xc1\xa3\x2e\x47\xe4\xcd\xea\x59\x39\xe8\x75\x7f\x63\xa4\x8b\x8a\xc4\xe5\x33\x40\x77\x7a\xa0\xce\x74\xde\xef\xc3\x30\xef\x11\x09\x29\xa7\x47\x0c\x7e\xbf\x4f\x92\x54\x4f\x2c\x5b\x2b\x9f\x26\xb9\x2e\x6d\xcd\xd3\x68\xd7\x7f\x13\x72\xc3\x47\x33\xae\x03\xbb\x84\xea\xe1\x45\x8f\xf3\x9a\x0f\x92\x06\x00\xff\xc7\x6d\x5f\x10\x94\xb3\xf5\xba\xcd\x0d\xd4\xb4\xe7\xea\x01\x42\x19\x7d\x38\xb7\xd2\x58\x53\xf1\xc3\x3a\xe9\xc4\xb8\x35\x82\xd5\x04\xb3\xd2\xf7\x77\x63\x70\xeb\x7c\x0a\xe8\x73\xbb\xdf\x80\x58\x36\xbc\x45\x87\x88\x04\x9f\x24\x31\x4f\x01\x9c\x81\xa7\x2f\xbf\xde\xe1\x38\xf8\x44\x84\xeb\xb3\xb0\x53\xe3\x2b\x48\x9e\xb2\xfb\x1c\x68\xdb\x21\x27\xbb\x85\xce\x73\xd4\xce\x23\x9f\xce\xdb\x8d\x1e\x61\x1e\x7a\x3c\xe3\x0b\xd0\x57\xab\x1c\x01\xd6\x27\x16\xdb\x23\x44\xbd\xc7\x25\xea\x3d\xe6\xbf\xa4\xb3\xdd\x60\x83\xb9\x03\x5e\x1c\xad\x6c\xa8\xf8\x3b\xc1\xef\xb1\xd2\x1d\xea\xb1\x0a\x6b\x2b\x22\x94\x1e\x2b\x05\x87\xc7\xbc\x9d\x87\x15\x3d\x36\x00\xf8\x07\x3d\xfa\xce\x85\x47\x1f\x60\xe3\x1e\xfb\x60\x27\x3e\xa7\xe9\xbc\xe4\xe9\xf1\xc3\xf8\x3c\xa9\xff\xef\x38\xa8\x4b\x32\x00\xb0\x12\xd2\x11\x43\x97\x3d\x74\x39\x27\x96\x2f\xda\x43\xe7\x25\x7e\x97\x7c\xa1\xae\x20\x9e\xef\x52\x48\xcc\x4e\x26\xea\x52\xa1\x43\x79\x3f\x98\x99\x30\xb7\xfc\x9b\x2e\x4d\xd1\xe4\x1f\xcf\xaf\x3b\x70\x29\xae\x02\xb8\x30\xb3\x0e\x89\xbb\x74\x0a\x48\xff\x3b\x52\xea\xc2\xcc\xf8\x2b\xbc\x88\x52\xf9\x20\xc0\x4a\x15\xf6\xb8\xaf\xeb\xa2\xae\x70\xa7\xba\x9e\x58\x26\x2f\xae\xfb\xfd\xce\x11\x08\xd5\x0c\xf5\xdf\x35\x0b\x5f\x82\xf6\xb5\xea\xfb\x5d\x36\x63\xe3\xc2\x42\x87\x77\xd2\xb5\x0f\x18\xc4\xce\xe3\xa1\xae\x7c\xa6\xdc\x69\x3a\x3b\xbd\xff\x4e\xab\xd9\x2d\xe3\x17\x5b\x44\xb2\x93\xf8\x96\x79\x73\xdc\xef\x1f\xfa\x8a\xdd\x78\x29\xd7\x2d\xcf\x3f\x24\x1b\x0f\xc9\xbb\x55\x48\x42\xb7\xba\x5a\x55\x38\xc2\xdd\x2a\xa5\xa9\x1b\x47\x6c\x99\x3d\xd7\x6b\x81\xce\xab\x89\x6e\xbe\xee\x79\x3b\x0a\x91\xef\x8b\xc0\xf7\xcf\x20\x27\x4c\x04\x83\x7d\x6e\x40\xe3\xa4\x9d\xeb\x34\x44\x7d\xca\x89\x69\xe9\x89\xf6\xe5\x59\xf5\x15\xfa\xf6\x79\x38\x9b\x33\x3c\xea\x33\x2f\x26\xe1\x3d\x52\x9f\x70\xbf\x98\x92\x85\xe7\x32\xf0\x7d\x36\xaa\xb5\x3e\xf1\xed\x89\x5f\x7f\x63\xfa\xc9\x86\x9d\x63\x41\x93\x8d\xc8\x27\xea\x23\x6e\xd0\x18\x48\x73\x04\xbc\x7f\xc3\x58\x15\xd0\xe3\x7c\x0f\x3a\x22\xb6\x3c\xe8\x74\x8f\xb8\x4e\x1b\xd7\xeb\xc5\xb1\x84\x66\xc4\x42\x3b\x31\x62\x81\x84\x0f\x5a\xa1\x11\xeb\x1a\xb8\xa1\x5d\x03\x03\x8c\x08\x4e\x1b\xb1\xad\x4e\xff\xa6\xae\x41\x7c\x47\x9d\x0b\xbf\xa1\xe8\x46\xf4\x27\xd8\x6b\x44\xb7\x01\xe8\x18\xcf\x59\x32\x66\x7c\xa2\xf9\x64\xd9\x0b\x45\xb4\x5f\x43\xf8\xca\x65\xd0\x2d\x1e\x92\x30\xf2\xfd\x9d\xf8\x46\x66\xc8\x13\x6c\x30\xe4\x29\x0e\xa8\xcc\xa0\x85\xe4\xfb\xfb\x40\x24\x42\xce\x1a\x02\x65\x33\xd6\x63\x81\x21\x35\xbe\x00\x77\x76\xaa\x0b\x6a\x07\xec\xa8\x36\x5e\xbe\x21\x9c\xe0\xb6\x04\x18\x1f\xf7\xb7\xf3\xd9\xdd\x10\xaf\xd0\x58\x03\x2e\x2f\x7a\x76\xf6\xec\xc6\x35\xf6\x81\x20\x70\x08\x63\x91\x41\x81\x19\xf2\x0a\x43\xa1\xc4\x86\x6e\x93\x27\x6a\x43\xa5\x34\xe4\x29\xc4\x43\x79\xcd\x34\x14\xfc\x33\x14\xfa\x66\xe8\x93\x03\xf0\x02\x64\x28\xcf\x86\x07\x9c\x0a\xec\x0f\x7e\xd0\xe0\xa3\xaf\x01\xcb\x30\xee\x77\x83\x75\x19\xca\x21\xd9\xed\x6f\x16\xb2\xd6\xb8\xdf\x43\x56\xff\x01\xf5\x3b\x14\xb8\xb5\x45\x67\xdb\x18\xe9\x0f\x83\x62\x1d\x96\xb8\x43\xc3\x2c\x76\xa2\x3a\xf3\xb3\xb0\x92\x55\xe4\x11\x6b\x2c\x68\x12\x06\x5f\xb5\x8d\xfb\xc7\xe3\x47\x18\xc6\x30\x7f\x98\x17\x2a\x0f\x98\x48\x61\x9e\xa0\x09\x07\x73\xac\x85\xcf\x4c\x86\xf9\x98\x9c\xa6\xe3\x87\x3d\xf0\x6d\xd5\x80\xb3\x87\x9c\xc7\x8d\x7c\xea\xeb\x3e\x7e\xbd\x48\x1e\xff\xbb\x0b\x1c\x8e\x48\x72\xf0\xf6\x73\x78\x2c\xfc\x86\xbf\xb5\x4c\xf2\xf0\x08\xcf\x6e\x38\x5f\xdb\x0e\xbf\xbf\x37\xcb\x61\xc0\xbf\x45\xa9\x2c\x0c\xba\x54\x00\x6e\x08\x4e\xc0\x70\xdd\x26\x20\x87\x46\xb4\x30\x9c\xcf\xf8\x86\xeb\xac\x07\x0a\xed\x10\x26\x85\x95\xb4\x98\x83\xc6\x72\xf0\xe1\xea\x70\x38\xd5\xc3\x27\xcb\xf9\x4c\x75\xf8\x04\xf3\xcf\x6d\x5d\xeb\x8e\xb9\x59\x18\x93\x6f\x14\xc6\x84\xf9\x19\x34\x86\xe3\xfe\xad\x92\x99\x90\xb9\xa7\xf3\xf9\xe9\x98\xce\xd3\xc1\x31\xe1\x71\x0c\x3e\xaf\x9e\x1b\x23\xa5\xfb\x37\x33\x66\x9c\xd0\x72\x39\xcc\x65\xa5\xe8\x8a\xcc\xaa\x17\xe2\xb1\x30\x2b\x7e\x50\x8b\x0c\xb1\xa6\xd3\x09\x9d\xbe\x49\x98\xbe\xae\x7c\x27\x62\x2b\xfe\x0d\x64\xf6\xc9\xe7\x4a\xeb\xce\x69\x0e\xe3\xab\x8f\x79\xc5\x70\x21\x0c\xba\x62\x02\xcb\x5d\x91\x6f\xc2\x2e\x3e\xe4\xbf\x40\x85\x2b\x2a\x0b\xd6\xd1\xed\x15\xb3\x84\xeb\x2f\x7e\xbf\xf8\x6e\xea\xe2\xa3\x56\x94\x5d\x93\x2d\x4a\x83\x1f\x75\x45\x47\xc6\x95\x03\x91\x6d\x2f\x84\xc6\x97\x90\x15\xaf\x75\x59\x72\xc9\xe3\x7e\xf3\xc0\xef\x02\xd9\x24\x5c\xf2\x94\x57\xe0\x21\xd6\x25\x34\xfa\x97\x64\x43\x09\x56\x21\x7c\x11\x7b\x51\xb8\x2e\xa9\xc2\x81\x2a\xd7\x2a\x40\xcd\x45\xee\xbc\xa4\xce\x1e\x2e\xb6\xe4\xad\xf2\x25\xbe\x11\xee\x98\xc0\x85\xbd\xfd\x49\xc8\x25\xf9\x40\x63\x20\xe4\x52\x30\xdd\xa5\x1b\xb4\xf5\xc5\xa3\xa4\xeb\x7e\x27\x5e\x0c\x5d\x8a\x8e\xf7\x1b\x06\xe7\xd2\x1d\xd8\xbc\x14\x7e\x31\xef\xef\xa4\x87\x8b\x5e\xde\xa5\x19\x3f\xec\x40\x6b\x84\xd0\xf3\xc5\xd6\xa5\xf7\x7f\x90\x93\x4b\x2d\xdf\xef\x1a\x2e\x05\x61\x2f\x75\x20\x59\x7d\xcc\x3d\x5c\xda\x89\xca\x77\x67\xb0\xbe\x5c\xcd\x4b\x47\xe4\x09\xe0\xa5\x93\xdd\xaf\xf8\x02\x24\x6e\x14\x76\xfe\xd2\xcb\xc2\x65\x99\xf7\xa7\x97\x65\xba\xb3\x97\x65\x62\xc0\x1c\xcd\xe9\xd3\x5d\x08\xa7\x2f\x20\x93\xd6\xeb\x9a\x7c\x98\xf9\xc9\x0b\xec\x4f\xf8\xc7\x9f\x94\xa0\x4f\xe8\xd5\x4f\xde\x48\x7e\x42\x71\x7d\x42\x6b\x7c\x42\x6b\x7c\xda\x39\x3d\xbc\xe2\x01\x02\xbf\x78\xd4\xfa\x8a\x0d\x22\xf9\xe2\x1b\x85\x97\x55\x00\xe8\xfe\xd7\x2c\x00\xb0\xb5\xff\x1f\x00\x00\xff\xff\x11\x91\x1a\xde\x5b\x35\x00\x00") + +func keysWordlistSpanishTxtBytes() ([]byte, error) { + return bindataRead( + _keysWordlistSpanishTxt, + "keys/wordlist/spanish.txt", + ) +} + +func keysWordlistSpanishTxt() (*asset, error) { + bytes, err := keysWordlistSpanishTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "keys/wordlist/spanish.txt", size: 13659, mode: os.FileMode(420), modTime: time.Unix(1497960590, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "keys/wordlist/chinese_simplified.txt": keysWordlistChinese_simplifiedTxt, + "keys/wordlist/english.txt": keysWordlistEnglishTxt, + "keys/wordlist/japanese.txt": keysWordlistJapaneseTxt, + "keys/wordlist/spanish.txt": keysWordlistSpanishTxt, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} +var _bintree = &bintree{nil, map[string]*bintree{ + "keys": &bintree{nil, map[string]*bintree{ + "wordlist": &bintree{nil, map[string]*bintree{ + "chinese_simplified.txt": &bintree{keysWordlistChinese_simplifiedTxt, map[string]*bintree{}}, + "english.txt": &bintree{keysWordlistEnglishTxt, map[string]*bintree{}}, + "japanese.txt": &bintree{keysWordlistJapaneseTxt, map[string]*bintree{}}, + "spanish.txt": &bintree{keysWordlistSpanishTxt, map[string]*bintree{}}, + }}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} + From 15609e12195e4c0e12a7787f543a7a06d32f637d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 18:15:49 +0200 Subject: [PATCH 097/273] Updated Manager interface to return seed on create, fix server tests --- keys/cryptostore/holder.go | 12 +++++++++--- keys/server/keys.go | 5 +++-- keys/server/keys_test.go | 18 ++++++++++-------- keys/server/types/keys.go | 7 +++++++ keys/transactions.go | 5 ++++- 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 42d4662de..0b139a14e 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -32,14 +32,20 @@ func (s Manager) assertKeyManager() keys.Manager { // // algo must be a supported go-crypto algorithm: // -func (s Manager) Create(name, passphrase, algo string) (keys.Info, error) { +func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error) { gen, err := getGenerator(algo) if err != nil { - return keys.Info{}, err + return keys.Info{}, "", err } key := gen.Generate() err = s.es.Put(name, passphrase, key) - return info(name, key), err + // TODO + return info(name, key), "", err +} + +func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) { + // TODO + return keys.Info{}, nil } // List loads the keys from the storage and enforces alphabetical order diff --git a/keys/server/keys.go b/keys/server/keys.go index 90d6da2b0..80852802e 100644 --- a/keys/server/keys.go +++ b/keys/server/keys.go @@ -31,13 +31,14 @@ func (k Keys) GenerateKey(w http.ResponseWriter, r *http.Request) { return } - key, err := k.manager.Create(req.Name, req.Passphrase, req.Algo) + key, seed, err := k.manager.Create(req.Name, req.Passphrase, req.Algo) if err != nil { writeError(w, err) return } - writeSuccess(w, &key) + res := types.CreateKeyResponse{key, seed} + writeSuccess(w, &res) } func (k Keys) GetKey(w http.ResponseWriter, r *http.Request) { diff --git a/keys/server/keys_test.go b/keys/server/keys_test.go index 4908559b0..a0bca8bd3 100644 --- a/keys/server/keys_test.go +++ b/keys/server/keys_test.go @@ -40,13 +40,15 @@ func TestKeyServer(t *testing.T) { key, code, err := createKey(r, n1, p1, algo) require.Nil(err, "%+v", err) require.Equal(http.StatusOK, code) - require.Equal(key.Name, n1) + require.Equal(n1, key.Key.Name) + require.NotEmpty(n1, key.Seed) // the other one works key2, code, err := createKey(r, n2, p2, algo) require.Nil(err, "%+v", err) require.Equal(http.StatusOK, code) - require.Equal(key2.Name, n2) + require.Equal(key2.Key.Name, n2) + require.NotEmpty(n2, key.Seed) // let's abstract this out a bit.... keys, code, err = listKeys(r) @@ -62,9 +64,9 @@ func TestKeyServer(t *testing.T) { k, code, err := getKey(r, n1) require.Nil(err, "%+v", err) require.Equal(http.StatusOK, code) - assert.Equal(k.Name, n1) + assert.Equal(n1, k.Name) assert.NotNil(k.Address) - assert.Equal(k.Address, key.Address) + assert.Equal(key.Key.Address, k.Address) // delete with proper key _, code, err = deleteKey(r, n1, p1) @@ -134,7 +136,7 @@ func getKey(h http.Handler, name string) (*keys.Info, int, error) { return &data, rr.Code, err } -func createKey(h http.Handler, name, passphrase, algo string) (*keys.Info, int, error) { +func createKey(h http.Handler, name, passphrase, algo string) (*types.CreateKeyResponse, int, error) { rr := httptest.NewRecorder() post := types.CreateKeyRequest{ Name: name, @@ -157,9 +159,9 @@ func createKey(h http.Handler, name, passphrase, algo string) (*keys.Info, int, return nil, rr.Code, nil } - data := keys.Info{} - err = json.Unmarshal(rr.Body.Bytes(), &data) - return &data, rr.Code, err + data := new(types.CreateKeyResponse) + err = json.Unmarshal(rr.Body.Bytes(), data) + return data, rr.Code, err } func deleteKey(h http.Handler, name, passphrase string) (*types.ErrorResponse, int, error) { diff --git a/keys/server/types/keys.go b/keys/server/types/keys.go index ffdc542f1..56ed60ceb 100644 --- a/keys/server/types/keys.go +++ b/keys/server/types/keys.go @@ -1,5 +1,7 @@ package types +import "github.com/tendermint/go-crypto/keys" + // CreateKeyRequest is sent to create a new key type CreateKeyRequest struct { Name string `json:"name" validate:"required,min=4,printascii"` @@ -26,3 +28,8 @@ type ErrorResponse struct { Error string `json:"error"` // error message if Success is false Code int `json:"code"` // error code if Success is false } + +type CreateKeyResponse struct { + Key keys.Info `json:"key"` + Seed string `json:"seed_phrase"` +} diff --git a/keys/transactions.go b/keys/transactions.go index 13d37feb5..10da7a6fa 100644 --- a/keys/transactions.go +++ b/keys/transactions.go @@ -63,7 +63,10 @@ type Signer interface { // Manager allows simple CRUD on a keystore, as an aid to signing type Manager interface { Signer - Create(name, passphrase, algo string) (Info, error) + // Create also returns a seed phrase for cold-storage + Create(name, passphrase, algo string) (Info, string, error) + // Recover takes a seedphrase and loads in the private key + Recover(name, passphrase, seedphrase string) (Info, error) List() (Infos, error) Get(name string) (Info, error) Update(name, oldpass, newpass string) error From 7108dedc21ac17a7ca8f84c1a9b8ae76dffda24b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 18:17:50 +0200 Subject: [PATCH 098/273] Fix broken key manager tests --- keys/cryptostore/holder_test.go | 6 +++--- keys/tx/multi_test.go | 4 ++-- keys/tx/one_test.go | 4 ++-- keys/tx/reader_test.go | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 4f0383198..9ad98bb9c 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -32,10 +32,10 @@ func TestKeyManagement(t *testing.T) { // create some keys _, err = cstore.Get(n1) assert.NotNil(err) - i, err := cstore.Create(n1, p1, algo) + i, _, err := cstore.Create(n1, p1, algo) require.Equal(n1, i.Name) require.Nil(err) - _, err = cstore.Create(n2, p2, algo) + _, _, err = cstore.Create(n2, p2, algo) require.Nil(err) // we can get these keys @@ -161,7 +161,7 @@ func TestAdvancedKeyManagement(t *testing.T) { p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$" // make sure key works with initial password - _, err := cstore.Create(n1, p1, algo) + _, _, err := cstore.Create(n1, p1, algo) require.Nil(err, "%+v", err) assertPassword(assert, cstore, n1, p1, p2) diff --git a/keys/tx/multi_test.go b/keys/tx/multi_test.go index 97463a5f7..e9477c8cd 100644 --- a/keys/tx/multi_test.go +++ b/keys/tx/multi_test.go @@ -22,9 +22,9 @@ func TestMultiSig(t *testing.T) { n, p := "foo", "bar" n2, p2 := "other", "thing" - acct, err := cstore.Create(n, p, algo) + acct, _, err := cstore.Create(n, p, algo) require.Nil(err, "%+v", err) - acct2, err := cstore.Create(n2, p2, algo) + acct2, _, err := cstore.Create(n2, p2, algo) require.Nil(err, "%+v", err) type signer struct { diff --git a/keys/tx/one_test.go b/keys/tx/one_test.go index 05af347b4..0480f5a33 100644 --- a/keys/tx/one_test.go +++ b/keys/tx/one_test.go @@ -22,9 +22,9 @@ func TestOneSig(t *testing.T) { n, p := "foo", "bar" n2, p2 := "other", "thing" - acct, err := cstore.Create(n, p, algo) + acct, _, err := cstore.Create(n, p, algo) require.Nil(err, "%+v", err) - acct2, err := cstore.Create(n2, p2, algo) + acct2, _, err := cstore.Create(n2, p2, algo) require.Nil(err, "%+v", err) cases := []struct { diff --git a/keys/tx/reader_test.go b/keys/tx/reader_test.go index c50481f14..7c622bff9 100644 --- a/keys/tx/reader_test.go +++ b/keys/tx/reader_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" - data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-crypto/keys/cryptostore" "github.com/tendermint/go-crypto/keys/storage/memstorage" + data "github.com/tendermint/go-wire/data" ) func TestReader(t *testing.T) { @@ -23,9 +23,9 @@ func TestReader(t *testing.T) { u := sigs{"alice", "1234"} u2 := sigs{"bob", "foobar"} - _, err := cstore.Create(u.name, u.pass, algo) + _, _, err := cstore.Create(u.name, u.pass, algo) require.Nil(err, "%+v", err) - _, err = cstore.Create(u2.name, u2.pass, algo) + _, _, err = cstore.Create(u2.name, u2.pass, algo) require.Nil(err, "%+v", err) cases := []struct { From 53e19e3dfaac5a9242204175e7a2d66c81574e8b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 18:35:16 +0200 Subject: [PATCH 099/273] Add codec to keys.Manager, recovery test passes --- keys/cryptostore/holder.go | 37 ++++++++++++++++++++++++++------ keys/cryptostore/holder_test.go | 38 +++++++++++++++++++++++++++++++++ keys/server/keys_test.go | 1 + keys/tx/multi_test.go | 1 + keys/tx/one_test.go | 1 + keys/tx/reader_test.go | 2 ++ keys/wordcodec.go | 10 +++++++++ 7 files changed, 83 insertions(+), 7 deletions(-) diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 0b139a14e..6709687d6 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -1,19 +1,26 @@ package cryptostore -import keys "github.com/tendermint/go-crypto/keys" +import ( + "strings" + + crypto "github.com/tendermint/go-crypto" + keys "github.com/tendermint/go-crypto/keys" +) // Manager combines encyption and storage implementation to provide // a full-featured key manager type Manager struct { - es encryptedStorage + es encryptedStorage + codec keys.Codec } -func New(coder Encoder, store keys.Storage) Manager { +func New(coder Encoder, store keys.Storage, codec keys.Codec) Manager { return Manager{ es: encryptedStorage{ coder: coder, store: store, }, + codec: codec, } } @@ -39,13 +46,29 @@ func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error } key := gen.Generate() err = s.es.Put(name, passphrase, key) - // TODO - return info(name, key), "", err + if err != nil { + return keys.Info{}, "", err + } + seed, err := s.codec.BytesToWords(key.Bytes()) + phrase := strings.Join(seed, " ") + return info(name, key), phrase, err } func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) { - // TODO - return keys.Info{}, nil + words := strings.Split(strings.TrimSpace(seedphrase), " ") + data, err := s.codec.WordsToBytes(words) + if err != nil { + return keys.Info{}, err + } + + key, err := crypto.PrivKeyFromBytes(data) + if err != nil { + return keys.Info{}, err + } + + // d00d, it worked! create the bugger.... + err = s.es.Put(name, passphrase, key) + return info(name, key), err } // List loads the keys from the storage and enforces alphabetical order diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 9ad98bb9c..c17eef24b 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto/keys" "github.com/tendermint/go-crypto/keys/cryptostore" "github.com/tendermint/go-crypto/keys/storage/memstorage" ) @@ -18,6 +19,7 @@ func TestKeyManagement(t *testing.T) { cstore := cryptostore.New( cryptostore.SecretBox, memstorage.New(), + keys.MustLoadCodec("english"), ) algo := crypto.NameEd25519 @@ -154,6 +156,7 @@ func TestAdvancedKeyManagement(t *testing.T) { cstore := cryptostore.New( cryptostore.SecretBox, memstorage.New(), + keys.MustLoadCodec("english"), ) algo := crypto.NameSecp256k1 @@ -199,6 +202,41 @@ func TestAdvancedKeyManagement(t *testing.T) { assertPassword(assert, cstore, n2, p3, pt) } +// TestSeedPhrase verifies restoring from a seed phrase +func TestSeedPhrase(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + // make the storage with reasonable defaults + cstore := cryptostore.New( + cryptostore.SecretBox, + memstorage.New(), + keys.MustLoadCodec("english"), + ) + + algo := crypto.NameEd25519 + n1, n2 := "lost-key", "found-again" + p1, p2 := "1234", "foobar" + + // make sure key works with initial password + info, seed, err := cstore.Create(n1, p1, algo) + require.Nil(err, "%+v", err) + assert.Equal(n1, info.Name) + assert.NotEmpty(seed) + + // now, let us delete this key + err = cstore.Delete(n1, p1) + require.Nil(err, "%+v", err) + _, err = cstore.Get(n1) + require.NotNil(err) + + // let us re-create it from the seed-phrase + newInfo, err := cstore.Recover(n2, p2, seed) + require.Nil(err, "%+v", err) + assert.Equal(n2, newInfo.Name) + assert.Equal(info.Address, newInfo.Address) + assert.Equal(info.PubKey, newInfo.PubKey) +} + // func ExampleStore() { // // Select the encryption and storage for your cryptostore // cstore := cryptostore.New( diff --git a/keys/server/keys_test.go b/keys/server/keys_test.go index a0bca8bd3..2aa17753c 100644 --- a/keys/server/keys_test.go +++ b/keys/server/keys_test.go @@ -91,6 +91,7 @@ func setupServer() http.Handler { cstore := cryptostore.New( cryptostore.SecretBox, memstorage.New(), + keys.MustLoadCodec("english"), ) // build your http server diff --git a/keys/tx/multi_test.go b/keys/tx/multi_test.go index e9477c8cd..22fb0ed75 100644 --- a/keys/tx/multi_test.go +++ b/keys/tx/multi_test.go @@ -18,6 +18,7 @@ func TestMultiSig(t *testing.T) { cstore := cryptostore.New( cryptostore.SecretBox, memstorage.New(), + keys.MustLoadCodec("english"), ) n, p := "foo", "bar" n2, p2 := "other", "thing" diff --git a/keys/tx/one_test.go b/keys/tx/one_test.go index 0480f5a33..e0a3f1056 100644 --- a/keys/tx/one_test.go +++ b/keys/tx/one_test.go @@ -18,6 +18,7 @@ func TestOneSig(t *testing.T) { cstore := cryptostore.New( cryptostore.SecretBox, memstorage.New(), + keys.MustLoadCodec("english"), ) n, p := "foo", "bar" n2, p2 := "other", "thing" diff --git a/keys/tx/reader_test.go b/keys/tx/reader_test.go index 7c622bff9..f0561301f 100644 --- a/keys/tx/reader_test.go +++ b/keys/tx/reader_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto/keys" "github.com/tendermint/go-crypto/keys/cryptostore" "github.com/tendermint/go-crypto/keys/storage/memstorage" data "github.com/tendermint/go-wire/data" @@ -18,6 +19,7 @@ func TestReader(t *testing.T) { cstore := cryptostore.New( cryptostore.SecretBox, memstorage.New(), + keys.MustLoadCodec("english"), ) type sigs struct{ name, pass string } u := sigs{"alice", "1234"} diff --git a/keys/wordcodec.go b/keys/wordcodec.go index f66d1e983..ee1374644 100644 --- a/keys/wordcodec.go +++ b/keys/wordcodec.go @@ -40,6 +40,7 @@ func NewCodec(words []string) (codec *WordCodec, err error) { return res, nil } +// LoadCodec loads a pre-compiled language file func LoadCodec(bank string) (codec *WordCodec, err error) { words, err := loadBank(bank) if err != nil { @@ -48,6 +49,15 @@ func LoadCodec(bank string) (codec *WordCodec, err error) { return NewCodec(words) } +// MustLoadCodec panics if word bank is missing, only for tests +func MustLoadCodec(bank string) *WordCodec { + codec, err := LoadCodec(bank) + if err != nil { + panic(err) + } + return codec +} + // loadBank opens a wordlist file and returns all words inside func loadBank(bank string) ([]string, error) { filename := "keys/wordlist/" + bank + ".txt" From 7d08ea4c09a020e5721943eb7454d431ba08c4b2 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 18:50:53 +0200 Subject: [PATCH 100/273] Fixed all tests and binaries to compile --- cmd/new.go | 2 +- cmd/root.go | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/new.go b/cmd/new.go index 033410e6a..0dd481e01 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -48,7 +48,7 @@ func newPassword(cmd *cobra.Command, args []string) error { return err } - info, err := GetKeyManager().Create(name, pass, algo) + info, _, err := GetKeyManager().Create(name, pass, algo) if err == nil { printInfo(info) } diff --git a/cmd/root.go b/cmd/root.go index 33153d850..cd1913273 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -48,10 +48,15 @@ func GetKeyManager() keys.Manager { // store the keys directory rootDir := viper.GetString(cli.HomeFlag) keyDir := filepath.Join(rootDir, KeySubdir) + + // TODO: smarter loading??? with language and fallback? + codec := keys.MustLoadCodec("english") + // and construct the key manager manager = cryptostore.New( cryptostore.SecretBox, filestorage.New(keyDir), + codec, ) } return manager From e9537b2da6554795d52eac68c5085f73ab6721cf Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 19:50:39 +0200 Subject: [PATCH 101/273] Freshen up existing cmd files --- cmd/get.go | 26 ++++++++++++-------------- cmd/keys/main.go | 3 +++ cmd/list.go | 16 +++++++--------- cmd/new.go | 13 ++++++++----- cmd/root.go | 33 +++++++++------------------------ cmd/serve.go | 22 +++++++++++++--------- cmd/update.go | 9 ++------- cmd/utils.go | 29 ++++++++++++++++++++++++++--- 8 files changed, 80 insertions(+), 71 deletions(-) diff --git a/cmd/get.go b/cmd/get.go index 6e8c620d0..9d30f49b8 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -25,20 +25,18 @@ var getCmd = &cobra.Command{ Use: "get ", Short: "Get details of one key", Long: `Return public details of one local key.`, - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) != 1 || len(args[0]) == 0 { - return errors.New("You must provide a name for the key") - } - name := args[0] - - info, err := GetKeyManager().Get(name) - if err == nil { - printInfo(info) - } - return err - }, + RunE: runGetCmd, } -func init() { - RootCmd.AddCommand(getCmd) +func runGetCmd(cmd *cobra.Command, args []string) error { + if len(args) != 1 || len(args[0]) == 0 { + return errors.New("You must provide a name for the key") + } + name := args[0] + + info, err := GetKeyManager().Get(name) + if err == nil { + printInfo(info) + } + return err } diff --git a/cmd/keys/main.go b/cmd/keys/main.go index 82b355346..8780f7bbc 100644 --- a/cmd/keys/main.go +++ b/cmd/keys/main.go @@ -22,6 +22,9 @@ import ( ) func main() { + // for demos, we enable the key server, probably don't want this + // in most binaries we embed the key management into + cmd.RegisterServer() root := cli.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) root.Execute() } diff --git a/cmd/list.go b/cmd/list.go index b0419a1e4..51eeeda12 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -22,15 +22,13 @@ var listCmd = &cobra.Command{ Short: "List all keys", Long: `Return a list of all public keys stored by this key manager along with their associated name and address.`, - RunE: func(cmd *cobra.Command, args []string) error { - infos, err := GetKeyManager().List() - if err == nil { - printInfos(infos) - } - return err - }, + RunE: runListCmd, } -func init() { - RootCmd.AddCommand(listCmd) +func runListCmd(cmd *cobra.Command, args []string) error { + infos, err := GetKeyManager().List() + if err == nil { + printInfos(infos) + } + return err } diff --git a/cmd/new.go b/cmd/new.go index 0dd481e01..b48f9727a 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -21,6 +21,10 @@ import ( "github.com/spf13/viper" ) +const ( + flagType = "type" +) + // newCmd represents the new command var newCmd = &cobra.Command{ Use: "new ", @@ -28,20 +32,19 @@ var newCmd = &cobra.Command{ Long: `Add a public/private key pair to the key store. The password muts be entered in the terminal and not passed as a command line argument for security.`, - RunE: newPassword, + RunE: runNewCmd, } func init() { - RootCmd.AddCommand(newCmd) - newCmd.Flags().StringP("type", "t", "ed25519", "Type of key (ed25519|secp256k1)") + newCmd.Flags().StringP(flagType, "t", "ed25519", "Type of key (ed25519|secp256k1)") } -func newPassword(cmd *cobra.Command, args []string) error { +func runNewCmd(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { return errors.New("You must provide a name for the key") } name := args[0] - algo := viper.GetString("type") + algo := viper.GetString(flagType) pass, err := getCheckPassword("Enter a passphrase:", "Repeat the passphrase:") if err != nil { diff --git a/cmd/root.go b/cmd/root.go index cd1913273..ad5a633fb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -15,14 +15,8 @@ package cmd import ( - "path/filepath" - "github.com/spf13/cobra" - "github.com/spf13/viper" keys "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/cryptostore" - "github.com/tendermint/go-crypto/keys/storage/filestorage" - "github.com/tendermint/tmlibs/cli" ) const KeySubdir = "keys" @@ -42,22 +36,13 @@ used by light-clients, full nodes, or any other application that needs to sign with a private key.`, } -// GetKeyManager initializes a key manager based on the configuration -func GetKeyManager() keys.Manager { - if manager == nil { - // store the keys directory - rootDir := viper.GetString(cli.HomeFlag) - keyDir := filepath.Join(rootDir, KeySubdir) - - // TODO: smarter loading??? with language and fallback? - codec := keys.MustLoadCodec("english") - - // and construct the key manager - manager = cryptostore.New( - cryptostore.SecretBox, - filestorage.New(keyDir), - codec, - ) - } - return manager +func init() { + RootCmd.AddCommand(getCmd) + RootCmd.AddCommand(listCmd) + RootCmd.AddCommand(newCmd) + RootCmd.AddCommand(updateCmd) +} + +func RegisterServer() { + RootCmd.AddCommand(serveCmd) } diff --git a/cmd/serve.go b/cmd/serve.go index 5ea96db3f..8cf7d12d4 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -28,6 +28,11 @@ import ( "github.com/tendermint/go-crypto/keys/server" ) +const ( + flagPort = "port" + flagSocket = "socket" +) + // serveCmd represents the serve command var serveCmd = &cobra.Command{ Use: "serve", @@ -36,27 +41,26 @@ var serveCmd = &cobra.Command{ private keys much more in depth than the cli can perform. In particular, this will allow you to sign transactions with the private keys in the store.`, - RunE: serveHTTP, + RunE: runServeCmd, } func init() { - RootCmd.AddCommand(serveCmd) - serveCmd.Flags().IntP("port", "p", 8118, "TCP Port for listen for http server") - serveCmd.Flags().StringP("socket", "s", "", "UNIX socket for more secure http server") - serveCmd.Flags().StringP("type", "t", "ed25519", "Default key type (ed25519|secp256k1)") + serveCmd.Flags().IntP(flagPort, "p", 8118, "TCP Port for listen for http server") + serveCmd.Flags().StringP(flagSocket, "s", "", "UNIX socket for more secure http server") + serveCmd.Flags().StringP(flagType, "t", "ed25519", "Default key type (ed25519|secp256k1)") } -func serveHTTP(cmd *cobra.Command, args []string) error { +func runServeCmd(cmd *cobra.Command, args []string) error { var l net.Listener var err error - socket := viper.GetString("socket") + socket := viper.GetString(flagSocket) if socket != "" { l, err = createSocket(socket) if err != nil { return errors.Wrap(err, "Cannot create socket") } } else { - port := viper.GetInt("port") + port := viper.GetInt(flagPort) l, err = net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { return errors.Errorf("Cannot listen on port %d", port) @@ -64,7 +68,7 @@ func serveHTTP(cmd *cobra.Command, args []string) error { } router := mux.NewRouter() - ks := server.New(GetKeyManager(), viper.GetString("type")) + ks := server.New(GetKeyManager(), viper.GetString(flagType)) ks.Register(router) // only set cors for tcp listener diff --git a/cmd/update.go b/cmd/update.go index c046af126..ec2bd2083 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -26,15 +26,10 @@ import ( var updateCmd = &cobra.Command{ Use: "update ", Short: "Change the password for a private key", - Long: `Change the password for a private key.`, - RunE: updatePassword, + RunE: runUpdateCmd, } -func init() { - RootCmd.AddCommand(updateCmd) -} - -func updatePassword(cmd *cobra.Command, args []string) error { +func runUpdateCmd(cmd *cobra.Command, args []string) error { if len(args) != 1 || len(args[0]) == 0 { return errors.New("You must provide a name for the key") } diff --git a/cmd/utils.go b/cmd/utils.go index d082bbbc9..e54343b7a 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "os" + "path/filepath" "strings" "github.com/bgentry/speakeasy" @@ -15,9 +16,31 @@ import ( "github.com/tendermint/tmlibs/cli" keys "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/go-crypto/keys/cryptostore" + "github.com/tendermint/go-crypto/keys/storage/filestorage" ) -const PassLength = 10 +const MinPassLength = 10 + +// GetKeyManager initializes a key manager based on the configuration +func GetKeyManager() keys.Manager { + if manager == nil { + // store the keys directory + rootDir := viper.GetString(cli.HomeFlag) + keyDir := filepath.Join(rootDir, KeySubdir) + + // TODO: smarter loading??? with language and fallback? + codec := keys.MustLoadCodec("english") + + // and construct the key manager + manager = cryptostore.New( + cryptostore.SecretBox, + filestorage.New(keyDir), + codec, + ) + } + return manager +} // if we read from non-tty, we just need to init the buffer reader once, // in case we try to read multiple passwords (eg. update) @@ -47,8 +70,8 @@ func getPassword(prompt string) (pass string, err error) { if err != nil { return "", err } - if len(pass) < PassLength { - return "", errors.Errorf("Password must be at least %d characters", PassLength) + if len(pass) < MinPassLength { + return "", errors.Errorf("Password must be at least %d characters", MinPassLength) } return pass, nil } From 1ab9ab9494343c15979801129fa21654a8cd061b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 20:34:13 +0200 Subject: [PATCH 102/273] Add delete and recover commands, and test them --- cmd/delete.go | 49 ++++++++++++++++++++++++++++++++++++++++++++++ cmd/new.go | 41 +++++++++++++++++++++++++++++++++++--- cmd/recover.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/root.go | 2 ++ cmd/utils.go | 6 ++++++ tests/keys.sh | 51 ++++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 cmd/delete.go create mode 100644 cmd/recover.go diff --git a/cmd/delete.go b/cmd/delete.go new file mode 100644 index 000000000..6c0185166 --- /dev/null +++ b/cmd/delete.go @@ -0,0 +1,49 @@ +// Copyright © 2017 Ethan Frey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/pkg/errors" + + "github.com/spf13/cobra" +) + +// deleteCmd represents the delete command +var deleteCmd = &cobra.Command{ + Use: "delete ", + Short: "DANGER: Delete a private key from your system", + RunE: runDeleteCmd, +} + +func runDeleteCmd(cmd *cobra.Command, args []string) error { + if len(args) != 1 || len(args[0]) == 0 { + return errors.New("You must provide a name for the key") + } + name := args[0] + + oldpass, err := getPassword("DANGER - enter password to permanently delete key:") + if err != nil { + return err + } + + err = GetKeyManager().Delete(name, oldpass) + if err != nil { + return err + } + fmt.Println("Password deleted forever (uh oh!)") + return nil +} diff --git a/cmd/new.go b/cmd/new.go index b48f9727a..2969a1042 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -15,14 +15,20 @@ package cmd import ( + "fmt" + "github.com/pkg/errors" + "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/go-wire/data" + "github.com/tendermint/tmlibs/cli" "github.com/spf13/cobra" "github.com/spf13/viper" ) const ( - flagType = "type" + flagType = "type" + flagNoBackup = "no-backup" ) // newCmd represents the new command @@ -37,6 +43,7 @@ passed as a command line argument for security.`, func init() { newCmd.Flags().StringP(flagType, "t", "ed25519", "Type of key (ed25519|secp256k1)") + newCmd.Flags().Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)") } func runNewCmd(cmd *cobra.Command, args []string) error { @@ -51,9 +58,37 @@ func runNewCmd(cmd *cobra.Command, args []string) error { return err } - info, _, err := GetKeyManager().Create(name, pass, algo) + info, seed, err := GetKeyManager().Create(name, pass, algo) if err == nil { - printInfo(info) + printCreate(info, seed) } return err } + +type NewOutput struct { + Key keys.Info `json:"key"` + Seed string `json:"seed"` +} + +func printCreate(info keys.Info, seed string) { + switch viper.Get(cli.OutputFlag) { + case "text": + printInfo(info) + // print seed unless requested not to. + if !viper.GetBool(flagNoBackup) { + fmt.Println("**Important** write this seed phrase in a safe place.") + fmt.Println("It is the only way to recover your account if you ever forget your password.\n") + fmt.Println(seed) + } + case "json": + out := NewOutput{Key: info} + if !viper.GetBool(flagNoBackup) { + out.Seed = seed + } + json, err := data.ToJSON(out) + if err != nil { + panic(err) // really shouldn't happen... + } + fmt.Println(string(json)) + } +} diff --git a/cmd/recover.go b/cmd/recover.go new file mode 100644 index 000000000..e3bd919b1 --- /dev/null +++ b/cmd/recover.go @@ -0,0 +1,53 @@ +// Copyright © 2017 Ethan Frey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "github.com/pkg/errors" + + "github.com/spf13/cobra" +) + +// recoverCmd represents the recover command +var recoverCmd = &cobra.Command{ + Use: "recover ", + Short: "Change the password for a private key", + RunE: runRecoverCmd, +} + +func runRecoverCmd(cmd *cobra.Command, args []string) error { + if len(args) != 1 || len(args[0]) == 0 { + return errors.New("You must provide a name for the key") + } + name := args[0] + + pass, err := getPassword("Enter the new passphrase:") + if err != nil { + return err + } + + // not really a password... huh? + seed, err := getSeed("Enter your recovery seed phrase") + if err != nil { + return err + } + + info, err := GetKeyManager().Recover(name, pass, seed) + if err != nil { + return err + } + printInfo(info) + return nil +} diff --git a/cmd/root.go b/cmd/root.go index ad5a633fb..cfd3d1adf 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -41,6 +41,8 @@ func init() { RootCmd.AddCommand(listCmd) RootCmd.AddCommand(newCmd) RootCmd.AddCommand(updateCmd) + RootCmd.AddCommand(deleteCmd) + RootCmd.AddCommand(recoverCmd) } func RegisterServer() { diff --git a/cmd/utils.go b/cmd/utils.go index e54343b7a..7978f78a7 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -76,6 +76,12 @@ func getPassword(prompt string) (pass string, err error) { return pass, nil } +func getSeed(prompt string) (seed string, err error) { + seed, err = stdinPassword() + seed = strings.TrimSpace(seed) + return +} + func getCheckPassword(prompt, prompt2 string) (string, error) { // simple read on no-tty if !inputIsTty() { diff --git a/tests/keys.sh b/tests/keys.sh index 82c8083ec..c848f8dd2 100755 --- a/tests/keys.sh +++ b/tests/keys.sh @@ -12,8 +12,9 @@ oneTimeSetUp() { newKey(){ assertNotNull "keyname required" "$1" KEYPASS=${2:-qwertyuiop} - KEY=$(echo $KEYPASS | ${EXE} new $1) - assertTrue "created $1" $? + KEY=$(echo $KEYPASS | ${EXE} new $1 -o json) + if ! assertTrue "created $1" $?; then return 1; fi + assertEquals "$1" $(echo $KEY | jq .key.name | tr -d \") return $? } @@ -59,6 +60,52 @@ test02updateKeys() { assertTrue "takes new key after update" "updateKey $USER $PASS2 $PASS3" } +test03recoverKeys() { + USER=sleepy + PASS1=S4H.9j.D9S7hso + + USER2=easy + PASS2=1234567890 + + # make a user and check they exist + echo "create..." + KEY=$(echo $PASS1 | ${EXE} new $USER -o json) + if ! assertTrue "created $USER" $?; then return 1; fi + if [ -n "$DEBUG" ]; then echo $KEY; echo; fi + + SEED=$(echo $KEY | jq .seed | tr -d \") + ADDR=$(echo $KEY | jq .key.address | tr -d \") + PUBKEY=$(echo $KEY | jq .key.pubkey | tr -d \") + assertTrue "${EXE} get $USER > /dev/null" + + # let's delete this key + echo "delete..." + assertFalse "echo foo | ${EXE} delete $USER > /dev/null" + assertTrue "echo $PASS1 | ${EXE} delete $USER > /dev/null" + assertFalse "${EXE} get $USER > /dev/null" + + # fails on short password + echo "recover..." + assertFalse "echo foo; echo $SEED | ${EXE} recover $USER2 -o json > /dev/null" + # fails on bad seed + assertFalse "echo $PASS2; echo \"silly white whale tower bongo\" | ${EXE} recover $USER2 -o json > /dev/null" + # now we got it + KEY2=$((echo $PASS2; echo $SEED) | ${EXE} recover $USER2 -o json) + if ! assertTrue "recovery failed: $KEY2" $?; then return 1; fi + if [ -n "$DEBUG" ]; then echo $KEY2; echo; fi + + # make sure it looks the same + NAME2=$(echo $KEY2 | jq .name | tr -d \") + ADDR2=$(echo $KEY2 | jq .address | tr -d \") + PUBKEY2=$(echo $KEY2 | jq .pubkey | tr -d \") + assertEquals "wrong username" "$USER2" "$NAME2" + assertEquals "address doesn't match" "$ADDR" "$ADDR2" + assertEquals "pubkey doesn't match" "$PUBKEY" "$PUBKEY2" + + # and we can find the info + assertTrue "${EXE} get $USER2 > /dev/null" +} + # load and run these tests with shunit2! DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory . $DIR/shunit2 From a944bdebfc5ef4fca2f4e5ad6381d319dc4067e1 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 20 Jun 2017 20:46:00 +0200 Subject: [PATCH 103/273] Make sure prompt looks good in interactive mode --- cmd/recover.go | 2 +- cmd/utils.go | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/recover.go b/cmd/recover.go index e3bd919b1..3a6953391 100644 --- a/cmd/recover.go +++ b/cmd/recover.go @@ -39,7 +39,7 @@ func runRecoverCmd(cmd *cobra.Command, args []string) error { } // not really a password... huh? - seed, err := getSeed("Enter your recovery seed phrase") + seed, err := getSeed("Enter your recovery seed phrase:") if err != nil { return err } diff --git a/cmd/utils.go b/cmd/utils.go index 7978f78a7..b1550a127 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -77,6 +77,9 @@ func getPassword(prompt string) (pass string, err error) { } func getSeed(prompt string) (seed string, err error) { + if inputIsTty() { + fmt.Println(prompt) + } seed, err = stdinPassword() seed = strings.TrimSpace(seed) return From d665c9ef103219a1990081a47ea735aada3620eb Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 21 Jun 2017 18:57:32 +0200 Subject: [PATCH 104/273] Code cleanup from review comments --- cmd/delete.go | 2 +- cmd/get.go | 2 +- cmd/new.go | 2 +- cmd/recover.go | 2 +- cmd/update.go | 2 +- keys/cryptostore/holder.go | 9 +++++++-- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cmd/delete.go b/cmd/delete.go index 6c0185166..033cf2768 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -24,7 +24,7 @@ import ( // deleteCmd represents the delete command var deleteCmd = &cobra.Command{ - Use: "delete ", + Use: "delete [name]", Short: "DANGER: Delete a private key from your system", RunE: runDeleteCmd, } diff --git a/cmd/get.go b/cmd/get.go index 9d30f49b8..dfade2b74 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -22,7 +22,7 @@ import ( // getCmd represents the get command var getCmd = &cobra.Command{ - Use: "get ", + Use: "get [name]", Short: "Get details of one key", Long: `Return public details of one local key.`, RunE: runGetCmd, diff --git a/cmd/new.go b/cmd/new.go index 2969a1042..ce4634074 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -33,7 +33,7 @@ const ( // newCmd represents the new command var newCmd = &cobra.Command{ - Use: "new ", + Use: "new [name]", Short: "Create a new public/private key pair", Long: `Add a public/private key pair to the key store. The password muts be entered in the terminal and not diff --git a/cmd/recover.go b/cmd/recover.go index 3a6953391..f5e4f0527 100644 --- a/cmd/recover.go +++ b/cmd/recover.go @@ -22,7 +22,7 @@ import ( // recoverCmd represents the recover command var recoverCmd = &cobra.Command{ - Use: "recover ", + Use: "recover [name]", Short: "Change the password for a private key", RunE: runRecoverCmd, } diff --git a/cmd/update.go b/cmd/update.go index ec2bd2083..f31af509c 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -24,7 +24,7 @@ import ( // updateCmd represents the update command var updateCmd = &cobra.Command{ - Use: "update ", + Use: "update [name]", Short: "Change the password for a private key", RunE: runUpdateCmd, } diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 6709687d6..0e4fde042 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -37,8 +37,7 @@ func (s Manager) assertKeyManager() keys.Manager { // Create adds a new key to the storage engine, returning error if // another key already stored under this name // -// algo must be a supported go-crypto algorithm: -// +// algo must be a supported go-crypto algorithm: ed25519, secp256k1 func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error) { gen, err := getGenerator(algo) if err != nil { @@ -54,6 +53,12 @@ func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error return info(name, key), phrase, err } +// Recover takes a seed phrase and tries to recover the private key. +// +// If the seed phrase is valid, it will create the private key and store +// it under name, protected by passphrase. +// +// Result similar to New(), except it doesn't return the seed again... func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) { words := strings.Split(strings.TrimSpace(seedphrase), " ") data, err := s.codec.WordsToBytes(words) From ad70b2222698a2018c4bf18bab86f3727621f492 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 21 Jun 2017 19:35:57 +0200 Subject: [PATCH 105/273] Update to 0.2.1 --- CHANGELOG.md | 10 ++++++++++ version.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 510785477..346d34fd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.2.1 (June 21, 2017) + +- Improve keys command + - No password prompts in non-interactive mode (echo 'foobar' | keys new foo) + - Added support for seed phrases + - Seed phrase now returned on `keys new` + - Add `keys restore` to restore private key from key phrase + - Checksum to verify typos in the seed phrase (rather than just a useless key) + - Add `keys delete` to remove a key if needed + ## 0.2.0 (May 18, 2017) BREAKING CHANGES: diff --git a/version.go b/version.go index e2c9c787b..c785b1bca 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.2.0" +const Version = "0.2.1" From d31cfbaeaa4d930798ec327b52917975f3203c11 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 23 Jun 2017 09:10:59 +0200 Subject: [PATCH 106/273] Fixed up help text for "keys recover" --- cmd/recover.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/recover.go b/cmd/recover.go index f5e4f0527..4896c4e05 100644 --- a/cmd/recover.go +++ b/cmd/recover.go @@ -23,8 +23,16 @@ import ( // recoverCmd represents the recover command var recoverCmd = &cobra.Command{ Use: "recover [name]", - Short: "Change the password for a private key", - RunE: runRecoverCmd, + Short: "Recover a private key from a seed phrase", + Long: `Recover a private key from a seed phrase. + +I really hope you wrote this down when you created the new key. +The seed is only displayed on creation, never again. + +You can also use this to copy a key between multiple testnets, +simply by "recovering" the key in the other nets you want to copy +to. Of course, it has no coins on the other nets, just the same address.`, + RunE: runRecoverCmd, } func runRecoverCmd(cmd *cobra.Command, args []string) error { From 65da3cf340e035254dcb3955fb069467d509301d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sat, 22 Jul 2017 05:25:59 -0400 Subject: [PATCH 107/273] Add crc16 support --- glide.lock | 24 +++++++++--------- glide.yaml | 1 + keys/ecc.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ keys/ecc_test.go | 6 +++++ 4 files changed, 83 insertions(+), 11 deletions(-) diff --git a/glide.lock b/glide.lock index 71292ce11..4cd7c5670 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 3bcee9fbccf29d21217b24b6a83ec51e1514f37b2ae5d8718cf6c5df80f4fb2c -updated: 2017-06-19T17:16:58.037568333+02:00 +hash: c0a2db1b80c6b1b8aab31c526ce43e22e49b23c893c78b8fdb8546aa2e7b7cc6 +updated: 2017-07-22T05:24:42.82932575-04:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -38,11 +38,11 @@ imports: - name: github.com/gorilla/context version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 - name: github.com/gorilla/handlers - version: 3a5767ca75ece5f7f1440b1d16975247f8d8b221 + version: a4043c62cc2329bacda331d33fc908ab11ef0ec3 - name: github.com/gorilla/mux - version: 392c28fe23e1c45ddba891b0320b3b5df220beea + version: bcd8bc72b08df0f70df986b97f95590779502d31 - name: github.com/hashicorp/hcl - version: a4b07c25de5ff55ad3b8936cea69a79a3d95a855 + version: 392dba7d905ed5d04a5794ba89f558b27e2ba1ca subpackages: - hcl/ast - hcl/parser @@ -52,6 +52,8 @@ imports: - json/parser - json/scanner - json/token +- name: github.com/howeyc/crc16 + version: 58da63c846043d0bea709c8d47039df06577d6d9 - name: github.com/inconshreveable/mousetrap version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/kr/logfmt @@ -67,7 +69,7 @@ imports: - name: github.com/pelletier/go-toml version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a - name: github.com/pkg/errors - version: ff09b135c25aae272398c51a07235b90a75aa4f0 + version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/spf13/afero version: 9be650865eab0c12963d8753212f4f9c66cdcf12 subpackages: @@ -75,11 +77,11 @@ imports: - name: github.com/spf13/cast version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra - version: db6b9a8b3f3f400c8ecb4a4d7d02245b8facad66 + version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77 - name: github.com/spf13/jwalterweatherman - version: fa7ca7e836cf3a8bb4ebf799f472c12d7e903d66 + version: 8f07c835e5cc1450c082fe3a439cf87b0cbb2d99 - name: github.com/spf13/pflag - version: 80fe0fb4eba54167e2ccae1c6c950e72abf61b73 + version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 - name: github.com/spf13/viper version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/tendermint/ed25519 @@ -93,7 +95,7 @@ imports: - data - data/base58 - name: github.com/tendermint/tmlibs - version: bd9d0d1637dadf1330e167189d5e5031aadcda6f + version: 2f6f3e6aa70bb19b70a6e73210273fa127041070 subpackages: - cli - common @@ -111,7 +113,7 @@ imports: - ripemd160 - salsa20/salsa - name: golang.org/x/sys - version: 9ccfe848b9db8435a24c424abbc07a921adf1df5 + version: e62c3de784db939836898e5c19ffd41bece347da subpackages: - unix - name: golang.org/x/text diff --git a/glide.yaml b/glide.yaml index 58e3aecca..a99d3b63f 100644 --- a/glide.yaml +++ b/glide.yaml @@ -29,6 +29,7 @@ import: - package: github.com/spf13/cobra - package: github.com/spf13/viper - package: gopkg.in/go-playground/validator.v9 +- package: github.com/howeyc/crc16 testImport: - package: github.com/mndrix/btcutil - package: github.com/stretchr/testify diff --git a/keys/ecc.go b/keys/ecc.go index 96590cd91..b94bf1fb9 100644 --- a/keys/ecc.go +++ b/keys/ecc.go @@ -5,6 +5,8 @@ import ( "errors" "hash/crc32" "hash/crc64" + + "github.com/howeyc/crc16" ) // ECC is used for anything that calculates an error-correcting code @@ -26,6 +28,67 @@ var _ ECC = NoECC{} func (_ NoECC) AddECC(input []byte) []byte { return input } func (_ NoECC) CheckECC(input []byte) ([]byte, error) { return input, nil } +// CRC16 does the ieee crc16 polynomial check +type CRC16 struct { + Poly uint16 + table *crc16.Table +} + +var _ ECC = &CRC16{} + +const crc16Size = 2 + +func NewIBMCRC16() *CRC16 { + return &CRC16{Poly: crc16.IBM} +} + +func NewSCSICRC16() *CRC16 { + return &CRC16{Poly: crc16.SCSI} +} + +func NewCCITTCRC16() *CRC16 { + return &CRC16{Poly: crc16.CCITT} +} + +func (c *CRC16) AddECC(input []byte) []byte { + table := c.getTable() + + // get crc and convert to some bytes... + crc := crc16.Checksum(input, table) + check := make([]byte, crc16Size) + binary.BigEndian.PutUint16(check, crc) + + // append it to the input + output := append(input, check...) + return output +} + +func (c *CRC16) CheckECC(input []byte) ([]byte, error) { + table := c.getTable() + + if len(input) <= crc16Size { + return nil, errors.New("input too short, no checksum present") + } + cut := len(input) - crc16Size + data, check := input[:cut], input[cut:] + crc := binary.BigEndian.Uint16(check) + calc := crc16.Checksum(data, table) + if crc != calc { + return nil, errors.New("Checksum does not match") + } + return data, nil +} + +func (c *CRC16) getTable() *crc16.Table { + if c.table == nil { + if c.Poly == 0 { + c.Poly = crc16.IBM + } + c.table = crc16.MakeTable(c.Poly) + } + return c.table +} + // CRC32 does the ieee crc32 polynomial check type CRC32 struct { Poly uint32 diff --git a/keys/ecc_test.go b/keys/ecc_test.go index 334c49423..930422b98 100644 --- a/keys/ecc_test.go +++ b/keys/ecc_test.go @@ -14,6 +14,9 @@ func TestECCPasses(t *testing.T) { checks := []ECC{ NoECC{}, + NewIBMCRC16(), + NewSCSICRC16(), + NewCCITTCRC16(), NewIEEECRC32(), NewCastagnoliCRC32(), NewKoopmanCRC32(), @@ -40,6 +43,9 @@ func TestECCFails(t *testing.T) { assert := assert.New(t) checks := []ECC{ + NewIBMCRC16(), + NewSCSICRC16(), + NewCCITTCRC16(), NewIEEECRC32(), NewCastagnoliCRC32(), NewKoopmanCRC32(), From 4ff889a236daa068db5666115637d74761a55a33 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sat, 22 Jul 2017 05:44:09 -0400 Subject: [PATCH 108/273] Use 16 random bytes for seed and key, crc16 by default --- keys/cryptostore/encoder_test.go | 9 ++++++--- keys/cryptostore/generator.go | 16 ++++++++-------- keys/cryptostore/holder.go | 21 ++++++++++++++------- keys/cryptostore/storage_test.go | 6 +++++- keys/wordcodec.go | 3 ++- keys/wordcodec_test.go | 2 +- 6 files changed, 36 insertions(+), 21 deletions(-) diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go index e5ea21111..945e19865 100644 --- a/keys/cryptostore/encoder_test.go +++ b/keys/cryptostore/encoder_test.go @@ -5,6 +5,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + cmn "github.com/tendermint/tmlibs/common" + "github.com/tendermint/go-crypto/keys/cryptostore" ) @@ -12,8 +15,8 @@ func TestNoopEncoder(t *testing.T) { assert, require := assert.New(t), require.New(t) noop := cryptostore.Noop - key := cryptostore.GenEd25519.Generate() - key2 := cryptostore.GenSecp256k1.Generate() + key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + key2 := cryptostore.GenSecp256k1.Generate(cmn.RandBytes(16)) b, err := noop.Encrypt(key, "encode") require.Nil(err) @@ -40,7 +43,7 @@ func TestSecretBox(t *testing.T) { assert, require := assert.New(t), require.New(t) enc := cryptostore.SecretBox - key := cryptostore.GenEd25519.Generate() + key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) pass := "some-special-secret" b, err := enc.Encrypt(key, pass) diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index 6bbdb6441..307a0ae86 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -14,22 +14,22 @@ var ( // Generator determines the type of private key the keystore creates type Generator interface { - Generate() crypto.PrivKey + Generate(secret []byte) crypto.PrivKey } // GenFunc is a helper to transform a function into a Generator -type GenFunc func() crypto.PrivKey +type GenFunc func(secret []byte) crypto.PrivKey -func (f GenFunc) Generate() crypto.PrivKey { - return f() +func (f GenFunc) Generate(secret []byte) crypto.PrivKey { + return f(secret) } -func genEd25519() crypto.PrivKey { - return crypto.GenPrivKeyEd25519().Wrap() +func genEd25519(secret []byte) crypto.PrivKey { + return crypto.GenPrivKeyEd25519FromSecret(secret).Wrap() } -func genSecp256() crypto.PrivKey { - return crypto.GenPrivKeySecp256k1().Wrap() +func genSecp256(secret []byte) crypto.PrivKey { + return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap() } func getGenerator(algo string) (Generator, error) { diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 0e4fde042..a3b5d2f61 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -43,12 +43,16 @@ func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error if err != nil { return keys.Info{}, "", err } - key := gen.Generate() + + // 128-bits the the all the randomness we can make use of + secret := crypto.CRandBytes(16) + key := gen.Generate(secret) err = s.es.Put(name, passphrase, key) if err != nil { return keys.Info{}, "", err } - seed, err := s.codec.BytesToWords(key.Bytes()) + + seed, err := s.codec.BytesToWords(secret) phrase := strings.Join(seed, " ") return info(name, key), phrase, err } @@ -61,15 +65,18 @@ func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error // Result similar to New(), except it doesn't return the seed again... func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) { words := strings.Split(strings.TrimSpace(seedphrase), " ") - data, err := s.codec.WordsToBytes(words) + secret, err := s.codec.WordsToBytes(words) if err != nil { return keys.Info{}, err } - key, err := crypto.PrivKeyFromBytes(data) - if err != nil { - return keys.Info{}, err - } + // TODO: flag this??? + gen := GenEd25519 + // gen, err := getGenerator(algo) + // if err != nil { + // return keys.Info{}, "", err + // } + key := gen.Generate(secret) // d00d, it worked! create the bugger.... err = s.es.Put(name, passphrase, key) diff --git a/keys/cryptostore/storage_test.go b/keys/cryptostore/storage_test.go index b109c44e8..907a19f11 100644 --- a/keys/cryptostore/storage_test.go +++ b/keys/cryptostore/storage_test.go @@ -4,13 +4,17 @@ import ( "testing" "github.com/stretchr/testify/assert" + + crypto "github.com/tendermint/go-crypto" + cmn "github.com/tendermint/tmlibs/common" + keys "github.com/tendermint/go-crypto/keys" ) func TestSortKeys(t *testing.T) { assert := assert.New(t) - gen := GenEd25519.Generate + gen := func() crypto.PrivKey { return GenEd25519.Generate(cmn.RandBytes(16)) } assert.NotEqual(gen(), gen()) // alphabetical order is n3, n1, n2 diff --git a/keys/wordcodec.go b/keys/wordcodec.go index ee1374644..214fe7e0b 100644 --- a/keys/wordcodec.go +++ b/keys/wordcodec.go @@ -34,7 +34,8 @@ func NewCodec(words []string) (codec *WordCodec, err error) { res := &WordCodec{ words: words, // TODO: configure this outside??? - check: NewIEEECRC32(), + // check: NewIEEECRC32(), + check: NewIBMCRC16(), } return res, nil diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index 1ae97d8a7..25c5439a6 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -152,7 +152,7 @@ func TestCheckTypoDetection(t *testing.T) { codec, err := LoadCodec(bank) require.Nil(err, "%s: %+v", bank, err) for i := 0; i < 1000; i++ { - numBytes := cmn.RandInt()%60 + 1 + numBytes := cmn.RandInt()%60 + 4 data := cmn.RandBytes(numBytes) words, err := codec.BytesToWords(data) From c20e83565c959438f00c029195345e23485b9e50 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sat, 22 Jul 2017 05:53:46 -0400 Subject: [PATCH 109/273] Recovery also works with secp256 keys --- keys/cryptostore/generator.go | 11 +++++++++++ keys/cryptostore/holder.go | 17 ++++++++++------ tests/keys.sh | 37 ++++++++++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index 307a0ae86..0a2bb55c2 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -42,3 +42,14 @@ func getGenerator(algo string) (Generator, error) { return nil, errors.Errorf("Cannot generate keys for algorithm: %s", algo) } } + +func getGeneratorByType(typ byte) (Generator, error) { + switch typ { + case crypto.TypeEd25519: + return GenEd25519, nil + case crypto.TypeSecp256k1: + return GenSecp256k1, nil + default: + return nil, errors.Errorf("Cannot generate keys for algorithm: %X", typ) + } +} diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index a3b5d2f61..202e55973 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -52,6 +52,10 @@ func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error return keys.Info{}, "", err } + // TODO: clean up type/kind handling with go-data + typ := key.Bytes()[0] + secret = append(secret, typ) + seed, err := s.codec.BytesToWords(secret) phrase := strings.Join(seed, " ") return info(name, key), phrase, err @@ -70,12 +74,13 @@ func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) return keys.Info{}, err } - // TODO: flag this??? - gen := GenEd25519 - // gen, err := getGenerator(algo) - // if err != nil { - // return keys.Info{}, "", err - // } + l := len(secret) + secret, typ := secret[:l-1], secret[l-1] + + gen, err := getGeneratorByType(typ) + if err != nil { + return keys.Info{}, err + } key := gen.Generate(secret) // d00d, it worked! create the bugger.... diff --git a/tests/keys.sh b/tests/keys.sh index c848f8dd2..599f3d743 100755 --- a/tests/keys.sh +++ b/tests/keys.sh @@ -68,7 +68,6 @@ test03recoverKeys() { PASS2=1234567890 # make a user and check they exist - echo "create..." KEY=$(echo $PASS1 | ${EXE} new $USER -o json) if ! assertTrue "created $USER" $?; then return 1; fi if [ -n "$DEBUG" ]; then echo $KEY; echo; fi @@ -79,13 +78,11 @@ test03recoverKeys() { assertTrue "${EXE} get $USER > /dev/null" # let's delete this key - echo "delete..." assertFalse "echo foo | ${EXE} delete $USER > /dev/null" assertTrue "echo $PASS1 | ${EXE} delete $USER > /dev/null" assertFalse "${EXE} get $USER > /dev/null" # fails on short password - echo "recover..." assertFalse "echo foo; echo $SEED | ${EXE} recover $USER2 -o json > /dev/null" # fails on bad seed assertFalse "echo $PASS2; echo \"silly white whale tower bongo\" | ${EXE} recover $USER2 -o json > /dev/null" @@ -106,6 +103,40 @@ test03recoverKeys() { assertTrue "${EXE} get $USER2 > /dev/null" } +# try recovery with secp256k1 keys +test03recoverSecp() { + USER=dings + PASS1=Sbub-U9byS7hso + + USER2=booms + PASS2=1234567890 + + KEY=$(echo $PASS1 | ${EXE} new $USER -o json -t secp256k1) + if ! assertTrue "created $USER" $?; then return 1; fi + if [ -n "$DEBUG" ]; then echo $KEY; echo; fi + + SEED=$(echo $KEY | jq .seed | tr -d \") + ADDR=$(echo $KEY | jq .key.address | tr -d \") + PUBKEY=$(echo $KEY | jq .key.pubkey | tr -d \") + assertTrue "${EXE} get $USER > /dev/null" + + # now we got it + KEY2=$((echo $PASS2; echo $SEED) | ${EXE} recover $USER2 -o json) + if ! assertTrue "recovery failed: $KEY2" $?; then return 1; fi + if [ -n "$DEBUG" ]; then echo $KEY2; echo; fi + + # make sure it looks the same + NAME2=$(echo $KEY2 | jq .name | tr -d \") + ADDR2=$(echo $KEY2 | jq .address | tr -d \") + PUBKEY2=$(echo $KEY2 | jq .pubkey | tr -d \") + assertEquals "wrong username" "$USER2" "$NAME2" + assertEquals "address doesn't match" "$ADDR" "$ADDR2" + assertEquals "pubkey doesn't match" "$PUBKEY" "$PUBKEY2" + + # and we can find the info + assertTrue "${EXE} get $USER2 > /dev/null" +} + # load and run these tests with shunit2! DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory . $DIR/shunit2 From 10222adaf1dc58a0d844caafce36fdd001c1e0be Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 26 Jul 2017 16:12:25 -0400 Subject: [PATCH 110/273] Remove deprecated code. Now in basecoin/weave --- keys/tx/docs.go | 10 ------ keys/tx/multi.go | 67 ------------------------------------ keys/tx/multi_test.go | 78 ------------------------------------------ keys/tx/one.go | 57 ------------------------------ keys/tx/one_test.go | 74 --------------------------------------- keys/tx/reader.go | 76 ---------------------------------------- keys/tx/reader_test.go | 72 -------------------------------------- 7 files changed, 434 deletions(-) delete mode 100644 keys/tx/docs.go delete mode 100644 keys/tx/multi.go delete mode 100644 keys/tx/multi_test.go delete mode 100644 keys/tx/one.go delete mode 100644 keys/tx/one_test.go delete mode 100644 keys/tx/reader.go delete mode 100644 keys/tx/reader_test.go diff --git a/keys/tx/docs.go b/keys/tx/docs.go deleted file mode 100644 index 6a5ea3ce3..000000000 --- a/keys/tx/docs.go +++ /dev/null @@ -1,10 +0,0 @@ -/* -package tx contains generic Signable implementations that can be used -by your application or tests to handle authentication needs. - -It currently supports transaction data as opaque bytes and either single -or multiple private key signatures using straightforward algorithms. -It currently does not support N-of-M key share signing of other more -complex algorithms (although it would be great to add them) -*/ -package tx diff --git a/keys/tx/multi.go b/keys/tx/multi.go deleted file mode 100644 index f069fb273..000000000 --- a/keys/tx/multi.go +++ /dev/null @@ -1,67 +0,0 @@ -package tx - -import ( - "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" - data "github.com/tendermint/go-wire/data" -) - -// MultiSig lets us wrap arbitrary data with a go-crypto signature -// -// TODO: rethink how we want to integrate this with KeyStore so it makes -// more sense (particularly the verify method) -type MultiSig struct { - Data data.Bytes - Sigs []Signed -} - -type Signed struct { - Sig crypto.Signature - Pubkey crypto.PubKey -} - -var _ SigInner = &MultiSig{} - -func NewMulti(data []byte) Sig { - return Sig{&MultiSig{Data: data}} -} - -// SignBytes returns the original data passed into `NewSig` -func (s *MultiSig) SignBytes() []byte { - return s.Data -} - -// Sign will add a signature and pubkey. -// -// Depending on the Signable, one may be able to call this multiple times for multisig -// Returns error if called with invalid data or too many times -func (s *MultiSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error { - if pubkey.Empty() || sig.Empty() { - return errors.New("Signature or Key missing") - } - - // set the value once we are happy - x := Signed{sig, pubkey} - s.Sigs = append(s.Sigs, x) - return nil -} - -// Signers will return the public key(s) that signed if the signature -// is valid, or an error if there is any issue with the signature, -// including if there are no signatures -func (s *MultiSig) Signers() ([]crypto.PubKey, error) { - if len(s.Sigs) == 0 { - return nil, errors.New("Never signed") - } - - keys := make([]crypto.PubKey, len(s.Sigs)) - for i := range s.Sigs { - ms := s.Sigs[i] - if !ms.Pubkey.VerifyBytes(s.Data, ms.Sig) { - return nil, errors.Errorf("Signature %d doesn't match (key: %X)", i, ms.Pubkey.Bytes()) - } - keys[i] = ms.Pubkey - } - - return keys, nil -} diff --git a/keys/tx/multi_test.go b/keys/tx/multi_test.go deleted file mode 100644 index 22fb0ed75..000000000 --- a/keys/tx/multi_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package tx - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/cryptostore" - "github.com/tendermint/go-crypto/keys/storage/memstorage" -) - -func TestMultiSig(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - algo := crypto.NameEd25519 - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), - keys.MustLoadCodec("english"), - ) - n, p := "foo", "bar" - n2, p2 := "other", "thing" - - acct, _, err := cstore.Create(n, p, algo) - require.Nil(err, "%+v", err) - acct2, _, err := cstore.Create(n2, p2, algo) - require.Nil(err, "%+v", err) - - type signer struct { - key keys.Info - name, pass string - } - cases := []struct { - data string - signers []signer - }{ - {"one", []signer{{acct, n, p}}}, - {"two", []signer{{acct2, n2, p2}}}, - {"both", []signer{{acct, n, p}, {acct2, n2, p2}}}, - } - - for _, tc := range cases { - tx := NewMulti([]byte(tc.data)) - // unsigned version - _, err = tx.Signers() - assert.NotNil(err) - orig, err := tx.TxBytes() - require.Nil(err, "%+v", err) - data := tx.SignBytes() - assert.Equal(tc.data, string(data)) - - // sign it - for _, s := range tc.signers { - err = cstore.Sign(s.name, s.pass, tx) - require.Nil(err, "%+v", err) - } - - // make sure it is proper now - sigs, err := tx.Signers() - require.Nil(err, "%+v", err) - if assert.Equal(len(tc.signers), len(sigs)) { - for i := range sigs { - // This must be refactored... - assert.Equal(tc.signers[i].key.PubKey, sigs[i]) - } - } - // the tx bytes should change after this - after, err := tx.TxBytes() - require.Nil(err, "%+v", err) - assert.NotEqual(orig, after, "%X != %X", orig, after) - - // sign bytes are the same - data = tx.SignBytes() - assert.Equal(tc.data, string(data)) - } -} diff --git a/keys/tx/one.go b/keys/tx/one.go deleted file mode 100644 index af468cc2c..000000000 --- a/keys/tx/one.go +++ /dev/null @@ -1,57 +0,0 @@ -package tx - -import ( - "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" - data "github.com/tendermint/go-wire/data" -) - -// OneSig lets us wrap arbitrary data with a go-crypto signature -// -// TODO: rethink how we want to integrate this with KeyStore so it makes -// more sense (particularly the verify method) -type OneSig struct { - Data data.Bytes - Signed -} - -var _ SigInner = &OneSig{} - -func New(data []byte) Sig { - return WrapSig(&OneSig{Data: data}) -} - -// SignBytes returns the original data passed into `NewSig` -func (s *OneSig) SignBytes() []byte { - return s.Data -} - -// Sign will add a signature and pubkey. -// -// Depending on the Signable, one may be able to call this multiple times for multisig -// Returns error if called with invalid data or too many times -func (s *OneSig) Sign(pubkey crypto.PubKey, sig crypto.Signature) error { - if pubkey.Empty() || sig.Empty() { - return errors.New("Signature or Key missing") - } - if !s.Sig.Empty() { - return errors.New("Transaction can only be signed once") - } - - // set the value once we are happy - s.Signed = Signed{sig, pubkey} - return nil -} - -// Signers will return the public key(s) that signed if the signature -// is valid, or an error if there is any issue with the signature, -// including if there are no signatures -func (s *OneSig) Signers() ([]crypto.PubKey, error) { - if s.Pubkey.Empty() || s.Sig.Empty() { - return nil, errors.New("Never signed") - } - if !s.Pubkey.VerifyBytes(s.Data, s.Sig) { - return nil, errors.New("Signature doesn't match") - } - return []crypto.PubKey{s.Pubkey}, nil -} diff --git a/keys/tx/one_test.go b/keys/tx/one_test.go deleted file mode 100644 index e0a3f1056..000000000 --- a/keys/tx/one_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package tx - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/cryptostore" - "github.com/tendermint/go-crypto/keys/storage/memstorage" -) - -func TestOneSig(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - algo := crypto.NameEd25519 - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), - keys.MustLoadCodec("english"), - ) - n, p := "foo", "bar" - n2, p2 := "other", "thing" - - acct, _, err := cstore.Create(n, p, algo) - require.Nil(err, "%+v", err) - acct2, _, err := cstore.Create(n2, p2, algo) - require.Nil(err, "%+v", err) - - cases := []struct { - data string - key keys.Info - name, pass string - }{ - {"first", acct, n, p}, - {"kehfkhefy8y", acct, n, p}, - {"second", acct2, n2, p2}, - } - - for _, tc := range cases { - tx := New([]byte(tc.data)) - // unsigned version - _, err = tx.Signers() - assert.NotNil(err) - orig, err := tx.TxBytes() - require.Nil(err, "%+v", err) - data := tx.SignBytes() - assert.Equal(tc.data, string(data)) - - // sign it - err = cstore.Sign(tc.name, tc.pass, tx) - require.Nil(err, "%+v", err) - // but not twice - err = cstore.Sign(tc.name, tc.pass, tx) - require.NotNil(err) - - // make sure it is proper now - sigs, err := tx.Signers() - require.Nil(err, "%+v", err) - if assert.Equal(1, len(sigs)) { - // This must be refactored... - assert.Equal(tc.key.PubKey, sigs[0]) - } - // the tx bytes should change after this - after, err := tx.TxBytes() - require.Nil(err, "%+v", err) - assert.NotEqual(orig, after, "%X != %X", orig, after) - - // sign bytes are the same - data = tx.SignBytes() - assert.Equal(tc.data, string(data)) - } -} diff --git a/keys/tx/reader.go b/keys/tx/reader.go deleted file mode 100644 index 265e88b46..000000000 --- a/keys/tx/reader.go +++ /dev/null @@ -1,76 +0,0 @@ -package tx - -import ( - crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-crypto/keys" - data "github.com/tendermint/go-wire/data" -) - -const ( - typeOneSig = byte(0x01) - typeMultiSig = byte(0x02) - nameOneSig = "sig" - nameMultiSig = "multi" -) - -var _ keys.Signable = Sig{} -var TxMapper data.Mapper - -func init() { - TxMapper = data.NewMapper(Sig{}). - RegisterImplementation(&OneSig{}, nameOneSig, typeOneSig). - RegisterImplementation(&MultiSig{}, nameMultiSig, typeMultiSig) -} - -/* -DO NOT USE this interface. - -It is public by necessity but should never be used directly -outside of this package. - -Only use Sig, never SigInner -*/ -type SigInner interface { - SignBytes() []byte - Sign(pubkey crypto.PubKey, sig crypto.Signature) error - Signers() ([]crypto.PubKey, error) -} - -// Sig is what is exported, and handles serialization -type Sig struct { - SigInner -} - -// TxBytes -func (s Sig) TxBytes() ([]byte, error) { - return data.ToWire(s) -} - -// WrapSig goes from concrete implementation to "interface" struct -func WrapSig(pk SigInner) Sig { - if wrap, ok := pk.(Sig); ok { - pk = wrap.Unwrap() - } - return Sig{pk} -} - -// Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (p Sig) Unwrap() SigInner { - pk := p.SigInner - for wrap, ok := pk.(Sig); ok; wrap, ok = pk.(Sig) { - pk = wrap.SigInner - } - return pk -} - -func (p Sig) MarshalJSON() ([]byte, error) { - return TxMapper.ToJSON(p.Unwrap()) -} - -func (p *Sig) UnmarshalJSON(data []byte) (err error) { - parsed, err := TxMapper.FromJSON(data) - if err == nil && parsed != nil { - p.SigInner = parsed.(SigInner) - } - return -} diff --git a/keys/tx/reader_test.go b/keys/tx/reader_test.go deleted file mode 100644 index f0561301f..000000000 --- a/keys/tx/reader_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package tx - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/cryptostore" - "github.com/tendermint/go-crypto/keys/storage/memstorage" - data "github.com/tendermint/go-wire/data" -) - -func TestReader(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - algo := crypto.NameEd25519 - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), - keys.MustLoadCodec("english"), - ) - type sigs struct{ name, pass string } - u := sigs{"alice", "1234"} - u2 := sigs{"bob", "foobar"} - - _, _, err := cstore.Create(u.name, u.pass, algo) - require.Nil(err, "%+v", err) - _, _, err = cstore.Create(u2.name, u2.pass, algo) - require.Nil(err, "%+v", err) - - cases := []struct { - tx Sig - sigs []sigs - }{ - {New([]byte("first")), nil}, - {New([]byte("second")), []sigs{u}}, - {New([]byte("other")), []sigs{u2}}, - {NewMulti([]byte("m-first")), nil}, - {NewMulti([]byte("m-second")), []sigs{u}}, - {NewMulti([]byte("m-other")), []sigs{u, u2}}, - } - - for _, tc := range cases { - tx := tc.tx - - // make sure json serialization and loading works w/o sigs - var pre Sig - pjs, err := data.ToJSON(tx) - require.Nil(err, "%+v", err) - err = data.FromJSON(pjs, &pre) - require.Nil(err, "%+v", err) - assert.Equal(tx, pre) - - for _, s := range tc.sigs { - err = cstore.Sign(s.name, s.pass, tx) - require.Nil(err, "%+v", err) - } - - var post Sig - sjs, err := data.ToJSON(tx) - require.Nil(err, "%+v", err) - err = data.FromJSON(sjs, &post) - require.Nil(err, "%+v\n%s", err, string(sjs)) - assert.Equal(tx, post) - - if len(tc.sigs) > 0 { - assert.NotEqual(pjs, sjs, "%s\n ------ %s", string(pjs), string(sjs)) - } - } -} From 050b9657083e3c2835dc6807291bd83b90345b61 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 27 Jul 2017 15:59:59 -0400 Subject: [PATCH 111/273] Code cleanup ala Emmanuel --- keys/cryptostore/holder.go | 7 +++++-- keys/ecc.go | 40 +++++++++++++++++++++----------------- keys/ecc_test.go | 35 +++++++++++++-------------------- 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 202e55973..18437a9b5 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -44,7 +44,7 @@ func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error return keys.Info{}, "", err } - // 128-bits the the all the randomness we can make use of + // 128-bits are the all the randomness we can make use of secret := crypto.CRandBytes(16) key := gen.Generate(secret) err = s.es.Put(name, passphrase, key) @@ -52,7 +52,8 @@ func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error return keys.Info{}, "", err } - // TODO: clean up type/kind handling with go-data + // we append the type byte to the serialized secret to help with recovery + // ie [secret] = [secret] + [type] typ := key.Bytes()[0] secret = append(secret, typ) @@ -74,6 +75,8 @@ func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) return keys.Info{}, err } + // secret is comprised of the actual secret with the type appended + // ie [secret] = [secret] + [type] l := len(secret) secret, typ := secret[:l-1], secret[l-1] diff --git a/keys/ecc.go b/keys/ecc.go index b94bf1fb9..c1ac258fe 100644 --- a/keys/ecc.go +++ b/keys/ecc.go @@ -20,6 +20,9 @@ type ECC interface { CheckECC([]byte) ([]byte, error) } +var errInputTooShort = errors.New("input too short, no checksum present") +var errChecksumDoesntMatch = errors.New("checksum does not match") + // NoECC is a no-op placeholder, kind of useless... except for tests type NoECC struct{} @@ -34,9 +37,9 @@ type CRC16 struct { table *crc16.Table } -var _ ECC = &CRC16{} +var _ ECC = (*CRC16)(nil) -const crc16Size = 2 +const crc16ByteCount = 2 func NewIBMCRC16() *CRC16 { return &CRC16{Poly: crc16.IBM} @@ -55,7 +58,7 @@ func (c *CRC16) AddECC(input []byte) []byte { // get crc and convert to some bytes... crc := crc16.Checksum(input, table) - check := make([]byte, crc16Size) + check := make([]byte, crc16ByteCount) binary.BigEndian.PutUint16(check, crc) // append it to the input @@ -66,26 +69,27 @@ func (c *CRC16) AddECC(input []byte) []byte { func (c *CRC16) CheckECC(input []byte) ([]byte, error) { table := c.getTable() - if len(input) <= crc16Size { - return nil, errors.New("input too short, no checksum present") + if len(input) <= crc16ByteCount { + return nil, errInputTooShort } - cut := len(input) - crc16Size + cut := len(input) - crc16ByteCount data, check := input[:cut], input[cut:] crc := binary.BigEndian.Uint16(check) calc := crc16.Checksum(data, table) if crc != calc { - return nil, errors.New("Checksum does not match") + return nil, errChecksumDoesntMatch } return data, nil } func (c *CRC16) getTable() *crc16.Table { - if c.table == nil { - if c.Poly == 0 { - c.Poly = crc16.IBM - } - c.table = crc16.MakeTable(c.Poly) + if c.table != nil { + return c.table + } + if c.Poly == 0 { + c.Poly = crc16.IBM } + c.table = crc16.MakeTable(c.Poly) return c.table } @@ -95,7 +99,7 @@ type CRC32 struct { table *crc32.Table } -var _ ECC = &CRC32{} +var _ ECC = (*CRC32)(nil) func NewIEEECRC32() *CRC32 { return &CRC32{Poly: crc32.IEEE} @@ -126,14 +130,14 @@ func (c *CRC32) CheckECC(input []byte) ([]byte, error) { table := c.getTable() if len(input) <= crc32.Size { - return nil, errors.New("input too short, no checksum present") + return nil, errInputTooShort } cut := len(input) - crc32.Size data, check := input[:cut], input[cut:] crc := binary.BigEndian.Uint32(check) calc := crc32.Checksum(data, table) if crc != calc { - return nil, errors.New("Checksum does not match") + return nil, errChecksumDoesntMatch } return data, nil } @@ -154,7 +158,7 @@ type CRC64 struct { table *crc64.Table } -var _ ECC = &CRC64{} +var _ ECC = (*CRC64)(nil) func NewISOCRC64() *CRC64 { return &CRC64{Poly: crc64.ISO} @@ -181,14 +185,14 @@ func (c *CRC64) CheckECC(input []byte) ([]byte, error) { table := c.getTable() if len(input) <= crc64.Size { - return nil, errors.New("input too short, no checksum present") + return nil, errInputTooShort } cut := len(input) - crc64.Size data, check := input[:cut], input[cut:] crc := binary.BigEndian.Uint64(check) calc := crc64.Checksum(data, table) if crc != calc { - return nil, errors.New("Checksum does not match") + return nil, errChecksumDoesntMatch } return data, nil } diff --git a/keys/ecc_test.go b/keys/ecc_test.go index 930422b98..d6b536aaa 100644 --- a/keys/ecc_test.go +++ b/keys/ecc_test.go @@ -8,21 +8,22 @@ import ( cmn "github.com/tendermint/tmlibs/common" ) +var codecs = []ECC{ + NewIBMCRC16(), + NewSCSICRC16(), + NewCCITTCRC16(), + NewIEEECRC32(), + NewCastagnoliCRC32(), + NewKoopmanCRC32(), + NewISOCRC64(), + NewECMACRC64(), +} + // TestECCPasses makes sure that the AddECC/CheckECC methods are symetric func TestECCPasses(t *testing.T) { assert := assert.New(t) - checks := []ECC{ - NoECC{}, - NewIBMCRC16(), - NewSCSICRC16(), - NewCCITTCRC16(), - NewIEEECRC32(), - NewCastagnoliCRC32(), - NewKoopmanCRC32(), - NewISOCRC64(), - NewECMACRC64(), - } + checks := append(codecs, NoECC{}) for _, check := range checks { for i := 0; i < 2000; i++ { @@ -42,17 +43,7 @@ func TestECCPasses(t *testing.T) { func TestECCFails(t *testing.T) { assert := assert.New(t) - checks := []ECC{ - NewIBMCRC16(), - NewSCSICRC16(), - NewCCITTCRC16(), - NewIEEECRC32(), - NewCastagnoliCRC32(), - NewKoopmanCRC32(), - NewISOCRC64(), - NewECMACRC64(), - } - + checks := codecs attempts := 2000 for _, check := range checks { From ae9c5b1ca0c77ea7203bbfa4f1cd68cd6d480e17 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Wed, 26 Jul 2017 20:43:27 -0600 Subject: [PATCH 112/273] hd: optimize ReverseBytes + add tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Optimized ReverseBytes to: a) Minimally allocate --> 60.0% reduction in the number of allocations b) Only walk halfway the length of the string thus performing byte swaps from left to right. Improves the performance as well. Complexity is O(n/2) instead of O(n) which is still O(n) but benchmarks show the new time is in deed 1/2 of the original time. * Added unit tests and some common cases to ensure correctness. * Benchmark shoot out results: ```shell name old time/op new time/op delta ReverseBytes-4 554ns ± 4% 242ns ± 3% -56.20% (p=0.000 n=10+10) name old alloc/op new alloc/op delta ReverseBytes-4 208B ± 0% 114B ± 0% -45.19% (p=0.000 n=10+10) name old allocs/op new allocs/op delta ReverseBytes-4 10.0 ± 0% 4.0 ± 0% -60.00% (p=0.000 n=10+10) ``` --- hd/address.go | 17 ++++++++++++++--- hd/hd_test.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/hd/address.go b/hd/address.go index 28f70a98f..d7553a4d7 100644 --- a/hd/address.go +++ b/hd/address.go @@ -282,9 +282,20 @@ func CalcSha512(buf []byte) []byte { } func ReverseBytes(buf []byte) []byte { - res := []byte{} - for i := len(buf) - 1; i >= 0; i-- { - res = append(res, buf[i]) + var res []byte + if len(buf) == 0 { + return res + } + + // Walk till mid-way, swapping bytes from each end: + // b[i] and b[len-i-1] + blen := len(buf) + res = make([]byte, blen) + mid := blen / 2 + for left := 0; left <= mid; left++ { + right := blen - left - 1 + res[left] = buf[right] + res[right] = buf[left] } return res } diff --git a/hd/hd_test.go b/hd/hd_test.go index e771f14b6..b2f7d2e8f 100644 --- a/hd/hd_test.go +++ b/hd/hd_test.go @@ -89,6 +89,26 @@ func TestHDToAddr(t *testing.T) { } } +func TestReverseBytes(t *testing.T) { + tests := [...]struct { + v []byte + want []byte + }{ + {[]byte(""), []byte("")}, + {nil, nil}, + {[]byte("Tendermint"), []byte("tnimredneT")}, + {[]byte("T"), []byte("T")}, + {[]byte("Te"), []byte("eT")}, + } + + for i, tt := range tests { + got := ReverseBytes(tt.v) + if !bytes.Equal(got, tt.want) { + t.Errorf("#%d:\ngot= (%x)\nwant=(%x)", i, got, tt.want) + } + } +} + func ifExit(err error, n int) { if err != nil { fmt.Println(n, err) @@ -187,3 +207,36 @@ func tylerSmith(seed []byte) ([]byte, []byte, []byte) { pub := k.PublicKey().Key return masterKey.Key, priv, pub } + +// Benchmarks + +var revBytesCases = [][]byte{ + nil, + []byte(""), + + []byte("12"), + + // 16byte case + []byte("abcdefghijklmnop"), + + // 32byte case + []byte("abcdefghijklmnopqrstuvwxyz123456"), + + // 64byte case + []byte("abcdefghijklmnopqrstuvwxyz123456abcdefghijklmnopqrstuvwxyz123456"), +} + +func BenchmarkReverseBytes(b *testing.B) { + var sink []byte + for i := 0; i < b.N; i++ { + for _, tt := range revBytesCases { + sink = ReverseBytes(tt) + } + } + b.ReportAllocs() + + // sink is necessary to ensure if the compiler tries + // to smart, that it won't optimize away the benchmarks. + if sink != nil { + } +} From ce80f234c75b85383a20b19cae393aec0f2b1a50 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Fri, 28 Jul 2017 13:01:28 -0600 Subject: [PATCH 113/273] README: add godoc instead of tedious MD regeneration Add a godoc reference to delegate indexing and references to that service, thus keeping our library and usages upto date, instead of relying on generated markdown that goes stale especially for changing API signatures, and becomes tedious where someone has to remember to always regenerate the README markdown and then commit it. Fixes #24 --- Makefile | 6 +- README.md | 839 +----------------------------------------------------- 2 files changed, 5 insertions(+), 840 deletions(-) diff --git a/Makefile b/Makefile index 537b6396f..8387f0608 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,10 @@ -.PHONEY: all docs test install get_vendor_deps ensure_tools codegen wordlist +.PHONEY: all test install get_vendor_deps ensure_tools codegen wordlist GOTOOLS = \ github.com/Masterminds/glide \ github.com/jteeuwen/go-bindata/go-bindata REPO:=github.com/tendermint/go-crypto -docs: - @go get github.com/davecheney/godoc2md - godoc2md $(REPO) > README.md - all: get_vendor_deps install test install: diff --git a/README.md b/README.md index ada192080..da76fe823 100644 --- a/README.md +++ b/README.md @@ -1,837 +1,6 @@ +# go-crypto [![GoDoc](https://godoc.org/github.com/tendermint/go-crypto?status.svg)](https://godoc.org/github.com/tendermint/go-crypto) +go-crypto is the cryptographic package adapted for Tendermint's uses -# crypto -`import "github.com/tendermint/go-crypto"` - -* [Overview](#pkg-overview) -* [Index](#pkg-index) -* [Subdirectories](#pkg-subdirectories) - -## Overview - - - -## Index -* [Constants](#pkg-constants) -* [func CRandBytes(numBytes int) []byte](#CRandBytes) -* [func CRandHex(numDigits int) string](#CRandHex) -* [func CReader() io.Reader](#CReader) -* [func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error)](#DecodeArmor) -* [func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error)](#DecryptSymmetric) -* [func EncodeArmor(blockType string, headers map[string]string, data []byte) string](#EncodeArmor) -* [func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte)](#EncryptSymmetric) -* [func MixEntropy(seedBytes []byte)](#MixEntropy) -* [func Ripemd160(bytes []byte) []byte](#Ripemd160) -* [func Sha256(bytes []byte) []byte](#Sha256) -* [type PrivKey](#PrivKey) - * [func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error)](#PrivKeyFromBytes) -* [type PrivKeyEd25519](#PrivKeyEd25519) - * [func GenPrivKeyEd25519() PrivKeyEd25519](#GenPrivKeyEd25519) - * [func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519](#GenPrivKeyEd25519FromSecret) - * [func (privKey PrivKeyEd25519) Bytes() []byte](#PrivKeyEd25519.Bytes) - * [func (privKey PrivKeyEd25519) Equals(other PrivKey) bool](#PrivKeyEd25519.Equals) - * [func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519](#PrivKeyEd25519.Generate) - * [func (p PrivKeyEd25519) MarshalJSON() ([]byte, error)](#PrivKeyEd25519.MarshalJSON) - * [func (privKey PrivKeyEd25519) PubKey() PubKey](#PrivKeyEd25519.PubKey) - * [func (privKey PrivKeyEd25519) Sign(msg []byte) Signature](#PrivKeyEd25519.Sign) - * [func (privKey PrivKeyEd25519) String() string](#PrivKeyEd25519.String) - * [func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte](#PrivKeyEd25519.ToCurve25519) - * [func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error](#PrivKeyEd25519.UnmarshalJSON) -* [type PrivKeyS](#PrivKeyS) - * [func (p PrivKeyS) Empty() bool](#PrivKeyS.Empty) - * [func (p PrivKeyS) MarshalJSON() ([]byte, error)](#PrivKeyS.MarshalJSON) - * [func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error)](#PrivKeyS.UnmarshalJSON) -* [type PrivKeySecp256k1](#PrivKeySecp256k1) - * [func GenPrivKeySecp256k1() PrivKeySecp256k1](#GenPrivKeySecp256k1) - * [func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1](#GenPrivKeySecp256k1FromSecret) - * [func (privKey PrivKeySecp256k1) Bytes() []byte](#PrivKeySecp256k1.Bytes) - * [func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool](#PrivKeySecp256k1.Equals) - * [func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error)](#PrivKeySecp256k1.MarshalJSON) - * [func (privKey PrivKeySecp256k1) PubKey() PubKey](#PrivKeySecp256k1.PubKey) - * [func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature](#PrivKeySecp256k1.Sign) - * [func (privKey PrivKeySecp256k1) String() string](#PrivKeySecp256k1.String) - * [func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error](#PrivKeySecp256k1.UnmarshalJSON) -* [type PubKey](#PubKey) - * [func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error)](#PubKeyFromBytes) -* [type PubKeyEd25519](#PubKeyEd25519) - * [func (pubKey PubKeyEd25519) Address() []byte](#PubKeyEd25519.Address) - * [func (pubKey PubKeyEd25519) Bytes() []byte](#PubKeyEd25519.Bytes) - * [func (pubKey PubKeyEd25519) Equals(other PubKey) bool](#PubKeyEd25519.Equals) - * [func (pubKey PubKeyEd25519) KeyString() string](#PubKeyEd25519.KeyString) - * [func (p PubKeyEd25519) MarshalJSON() ([]byte, error)](#PubKeyEd25519.MarshalJSON) - * [func (pubKey PubKeyEd25519) String() string](#PubKeyEd25519.String) - * [func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte](#PubKeyEd25519.ToCurve25519) - * [func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error](#PubKeyEd25519.UnmarshalJSON) - * [func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool](#PubKeyEd25519.VerifyBytes) -* [type PubKeyS](#PubKeyS) - * [func (p PubKeyS) Empty() bool](#PubKeyS.Empty) - * [func (p PubKeyS) MarshalJSON() ([]byte, error)](#PubKeyS.MarshalJSON) - * [func (p *PubKeyS) UnmarshalJSON(data []byte) (err error)](#PubKeyS.UnmarshalJSON) -* [type PubKeySecp256k1](#PubKeySecp256k1) - * [func (pubKey PubKeySecp256k1) Address() []byte](#PubKeySecp256k1.Address) - * [func (pubKey PubKeySecp256k1) Bytes() []byte](#PubKeySecp256k1.Bytes) - * [func (pubKey PubKeySecp256k1) Equals(other PubKey) bool](#PubKeySecp256k1.Equals) - * [func (pubKey PubKeySecp256k1) KeyString() string](#PubKeySecp256k1.KeyString) - * [func (p PubKeySecp256k1) MarshalJSON() ([]byte, error)](#PubKeySecp256k1.MarshalJSON) - * [func (pubKey PubKeySecp256k1) String() string](#PubKeySecp256k1.String) - * [func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error](#PubKeySecp256k1.UnmarshalJSON) - * [func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool](#PubKeySecp256k1.VerifyBytes) -* [type Signature](#Signature) - * [func SignatureFromBytes(sigBytes []byte) (sig Signature, err error)](#SignatureFromBytes) -* [type SignatureEd25519](#SignatureEd25519) - * [func (sig SignatureEd25519) Bytes() []byte](#SignatureEd25519.Bytes) - * [func (sig SignatureEd25519) Equals(other Signature) bool](#SignatureEd25519.Equals) - * [func (sig SignatureEd25519) IsZero() bool](#SignatureEd25519.IsZero) - * [func (p SignatureEd25519) MarshalJSON() ([]byte, error)](#SignatureEd25519.MarshalJSON) - * [func (sig SignatureEd25519) String() string](#SignatureEd25519.String) - * [func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error](#SignatureEd25519.UnmarshalJSON) -* [type SignatureS](#SignatureS) - * [func (p SignatureS) Empty() bool](#SignatureS.Empty) - * [func (p SignatureS) MarshalJSON() ([]byte, error)](#SignatureS.MarshalJSON) - * [func (p *SignatureS) UnmarshalJSON(data []byte) (err error)](#SignatureS.UnmarshalJSON) -* [type SignatureSecp256k1](#SignatureSecp256k1) - * [func (sig SignatureSecp256k1) Bytes() []byte](#SignatureSecp256k1.Bytes) - * [func (sig SignatureSecp256k1) Equals(other Signature) bool](#SignatureSecp256k1.Equals) - * [func (sig SignatureSecp256k1) IsZero() bool](#SignatureSecp256k1.IsZero) - * [func (p SignatureSecp256k1) MarshalJSON() ([]byte, error)](#SignatureSecp256k1.MarshalJSON) - * [func (sig SignatureSecp256k1) String() string](#SignatureSecp256k1.String) - * [func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error](#SignatureSecp256k1.UnmarshalJSON) - - -#### Package files -[armor.go](/src/github.com/tendermint/go-crypto/armor.go) [hash.go](/src/github.com/tendermint/go-crypto/hash.go) [priv_key.go](/src/github.com/tendermint/go-crypto/priv_key.go) [pub_key.go](/src/github.com/tendermint/go-crypto/pub_key.go) [random.go](/src/github.com/tendermint/go-crypto/random.go) [signature.go](/src/github.com/tendermint/go-crypto/signature.go) [symmetric.go](/src/github.com/tendermint/go-crypto/symmetric.go) - - -## Constants -``` go -const ( - TypeEd25519 = byte(0x01) - TypeSecp256k1 = byte(0x02) - NameEd25519 = "ed25519" - NameSecp256k1 = "secp256k1" -) -``` -Types of implementations - - - - -## func [CRandBytes](/src/target/random.go?s=698:734#L28) -``` go -func CRandBytes(numBytes int) []byte -``` -This uses the OS and the Seed(s). - - - -## func [CRandHex](/src/target/random.go?s=924:959#L38) -``` go -func CRandHex(numDigits int) string -``` -RandHex(24) gives 96 bits of randomness, strong enough for most purposes. - - - -## func [CReader](/src/target/random.go?s=1078:1102#L43) -``` go -func CReader() io.Reader -``` -Returns a crand.Reader mixed with user-supplied entropy - - - -## func [DecodeArmor](/src/target/armor.go?s=596:699#L18) -``` go -func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error) -``` - - -## func [DecryptSymmetric](/src/target/symmetric.go?s=1048:1133#L23) -``` go -func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error) -``` -secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) -The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. - - - -## func [EncodeArmor](/src/target/armor.go?s=125:206#L1) -``` go -func EncodeArmor(blockType string, headers map[string]string, data []byte) string -``` - - -## func [EncryptSymmetric](/src/target/symmetric.go?s=356:430#L6) -``` go -func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte) -``` -secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) -The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. -NOTE: call crypto.MixEntropy() first. - - - -## func [MixEntropy](/src/target/random.go?s=407:440#L13) -``` go -func MixEntropy(seedBytes []byte) -``` -Mix additional bytes of randomness, e.g. from hardware, user-input, etc. -It is OK to call it multiple times. It does not diminish security. - - - -## func [Ripemd160](/src/target/hash.go?s=185:220#L4) -``` go -func Ripemd160(bytes []byte) []byte -``` - - -## func [Sha256](/src/target/hash.go?s=78:110#L1) -``` go -func Sha256(bytes []byte) []byte -``` - - - -## type [PrivKey](/src/target/priv_key.go?s=326:435#L5) -``` go -type PrivKey interface { - Bytes() []byte - Sign(msg []byte) Signature - PubKey() PubKey - Equals(PrivKey) bool -} -``` -PrivKey is part of PrivAccount and state.PrivValidator. - - - - - - - -### func [PrivKeyFromBytes](/src/target/priv_key.go?s=1302:1373#L50) -``` go -func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) -``` - - - - -## type [PrivKeyEd25519](/src/target/priv_key.go?s=1502:1530#L58) -``` go -type PrivKeyEd25519 [64]byte -``` -Implements PrivKey - - - - - - - -### func [GenPrivKeyEd25519](/src/target/priv_key.go?s=3003:3042#L116) -``` go -func GenPrivKeyEd25519() PrivKeyEd25519 -``` - -### func [GenPrivKeyEd25519FromSecret](/src/target/priv_key.go?s=3290:3352#L125) -``` go -func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 -``` -NOTE: secret should be the output of a KDF like bcrypt, -if it's derived from user input. - - - - - -### func (PrivKeyEd25519) [Bytes](/src/target/priv_key.go?s=1532:1576#L60) -``` go -func (privKey PrivKeyEd25519) Bytes() []byte -``` - - - -### func (PrivKeyEd25519) [Equals](/src/target/priv_key.go?s=1973:2029#L75) -``` go -func (privKey PrivKeyEd25519) Equals(other PrivKey) bool -``` - - - -### func (PrivKeyEd25519) [Generate](/src/target/priv_key.go?s=2761:2825#L106) -``` go -func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 -``` -Deterministically generates new priv-key bytes from key. - - - - -### func (PrivKeyEd25519) [MarshalJSON](/src/target/priv_key.go?s=2156:2209#L83) -``` go -func (p PrivKeyEd25519) MarshalJSON() ([]byte, error) -``` - - - -### func (PrivKeyEd25519) [PubKey](/src/target/priv_key.go?s=1826:1871#L70) -``` go -func (privKey PrivKeyEd25519) PubKey() PubKey -``` - - - -### func (PrivKeyEd25519) [Sign](/src/target/priv_key.go?s=1635:1691#L64) -``` go -func (privKey PrivKeyEd25519) Sign(msg []byte) Signature -``` - - - -### func (PrivKeyEd25519) [String](/src/target/priv_key.go?s=2613:2658#L101) -``` go -func (privKey PrivKeyEd25519) String() string -``` - - - -### func (PrivKeyEd25519) [ToCurve25519](/src/target/priv_key.go?s=2399:2453#L94) -``` go -func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte -``` - - - -### func (\*PrivKeyEd25519) [UnmarshalJSON](/src/target/priv_key.go?s=2250:2306#L87) -``` go -func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error -``` - - - -## type [PrivKeyS](/src/target/priv_key.go?s=929:962#L30) -``` go -type PrivKeyS struct { - PrivKey -} -``` -PrivKeyS add json serialization to PrivKey - - - - - - - - - - -### func (PrivKeyS) [Empty](/src/target/priv_key.go?s=1241:1271#L46) -``` go -func (p PrivKeyS) Empty() bool -``` - - - -### func (PrivKeyS) [MarshalJSON](/src/target/priv_key.go?s=964:1011#L34) -``` go -func (p PrivKeyS) MarshalJSON() ([]byte, error) -``` - - - -### func (\*PrivKeyS) [UnmarshalJSON](/src/target/priv_key.go?s=1057:1114#L38) -``` go -func (p *PrivKeyS) UnmarshalJSON(data []byte) (err error) -``` - - - -## type [PrivKeySecp256k1](/src/target/priv_key.go?s=3635:3665#L136) -``` go -type PrivKeySecp256k1 [32]byte -``` -Implements PrivKey - - - - - - - -### func [GenPrivKeySecp256k1](/src/target/priv_key.go?s=5071:5114#L194) -``` go -func GenPrivKeySecp256k1() PrivKeySecp256k1 -``` - -### func [GenPrivKeySecp256k1FromSecret](/src/target/priv_key.go?s=5436:5502#L204) -``` go -func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1 -``` -NOTE: secret should be the output of a KDF like bcrypt, -if it's derived from user input. - - - - - -### func (PrivKeySecp256k1) [Bytes](/src/target/priv_key.go?s=3667:3713#L138) -``` go -func (privKey PrivKeySecp256k1) Bytes() []byte -``` - - - -### func (PrivKeySecp256k1) [Equals](/src/target/priv_key.go?s=4235:4293#L158) -``` go -func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool -``` - - - -### func (PrivKeySecp256k1) [MarshalJSON](/src/target/priv_key.go?s=4426:4481#L166) -``` go -func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error) -``` - - - -### func (PrivKeySecp256k1) [PubKey](/src/target/priv_key.go?s=4032:4079#L151) -``` go -func (privKey PrivKeySecp256k1) PubKey() PubKey -``` - - - -### func (PrivKeySecp256k1) [Sign](/src/target/priv_key.go?s=3772:3830#L142) -``` go -func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature -``` - - - -### func (PrivKeySecp256k1) [String](/src/target/priv_key.go?s=4673:4720#L177) -``` go -func (privKey PrivKeySecp256k1) String() string -``` - - - -### func (\*PrivKeySecp256k1) [UnmarshalJSON](/src/target/priv_key.go?s=4522:4580#L170) -``` go -func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error -``` - - - -## type [PubKey](/src/target/pub_key.go?s=361:506#L7) -``` go -type PubKey interface { - Address() []byte - Bytes() []byte - KeyString() string - VerifyBytes(msg []byte, sig Signature) bool - Equals(PubKey) bool -} -``` -PubKey is part of Account and Validator. - - - - - - - -### func [PubKeyFromBytes](/src/target/pub_key.go?s=1203:1270#L45) -``` go -func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) -``` - - - - -## type [PubKeyEd25519](/src/target/pub_key.go?s=1396:1423#L53) -``` go -type PubKeyEd25519 [32]byte -``` -Implements PubKey - - - - - - - - - - -### func (PubKeyEd25519) [Address](/src/target/pub_key.go?s=1425:1469#L55) -``` go -func (pubKey PubKeyEd25519) Address() []byte -``` - - - -### func (PubKeyEd25519) [Bytes](/src/target/pub_key.go?s=1789:1831#L68) -``` go -func (pubKey PubKeyEd25519) Bytes() []byte -``` - - - -### func (PubKeyEd25519) [Equals](/src/target/pub_key.go?s=3064:3117#L119) -``` go -func (pubKey PubKeyEd25519) Equals(other PubKey) bool -``` - - - -### func (PubKeyEd25519) [KeyString](/src/target/pub_key.go?s=2983:3029#L115) -``` go -func (pubKey PubKeyEd25519) KeyString() string -``` -Must return the full bytes in hex. -Used for map keying, etc. - - - - -### func (PubKeyEd25519) [MarshalJSON](/src/target/pub_key.go?s=2279:2331#L87) -``` go -func (p PubKeyEd25519) MarshalJSON() ([]byte, error) -``` - - - -### func (PubKeyEd25519) [String](/src/target/pub_key.go?s=2823:2866#L109) -``` go -func (pubKey PubKeyEd25519) String() string -``` - - - -### func (PubKeyEd25519) [ToCurve25519](/src/target/pub_key.go?s=2585:2637#L100) -``` go -func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte -``` -For use with golang/crypto/nacl/box -If error, returns nil. - - - - -### func (\*PubKeyEd25519) [UnmarshalJSON](/src/target/pub_key.go?s=2372:2427#L91) -``` go -func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error -``` - - - -### func (PubKeyEd25519) [VerifyBytes](/src/target/pub_key.go?s=1888:1960#L72) -``` go -func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool -``` - - - -## type [PubKeyS](/src/target/pub_key.go?s=841:872#L25) -``` go -type PubKeyS struct { - PubKey -} -``` -PubKeyS add json serialization to PubKey - - - - - - - - - - -### func (PubKeyS) [Empty](/src/target/pub_key.go?s=1144:1173#L41) -``` go -func (p PubKeyS) Empty() bool -``` - - - -### func (PubKeyS) [MarshalJSON](/src/target/pub_key.go?s=874:920#L29) -``` go -func (p PubKeyS) MarshalJSON() ([]byte, error) -``` - - - -### func (\*PubKeyS) [UnmarshalJSON](/src/target/pub_key.go?s=964:1020#L33) -``` go -func (p *PubKeyS) UnmarshalJSON(data []byte) (err error) -``` - - - -## type [PubKeySecp256k1](/src/target/pub_key.go?s=3401:3430#L132) -``` go -type PubKeySecp256k1 [33]byte -``` -Implements PubKey. -Compressed pubkey (just the x-cord), -prefixed with 0x02 or 0x03, depending on the y-cord. - - - - - - - - - - -### func (PubKeySecp256k1) [Address](/src/target/pub_key.go?s=3497:3543#L135) -``` go -func (pubKey PubKeySecp256k1) Address() []byte -``` -Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) - - - - -### func (PubKeySecp256k1) [Bytes](/src/target/pub_key.go?s=3774:3818#L145) -``` go -func (pubKey PubKeySecp256k1) Bytes() []byte -``` - - - -### func (PubKeySecp256k1) [Equals](/src/target/pub_key.go?s=4897:4952#L192) -``` go -func (pubKey PubKeySecp256k1) Equals(other PubKey) bool -``` - - - -### func (PubKeySecp256k1) [KeyString](/src/target/pub_key.go?s=4814:4862#L188) -``` go -func (pubKey PubKeySecp256k1) KeyString() string -``` -Must return the full bytes in hex. -Used for map keying, etc. - - - - -### func (PubKeySecp256k1) [MarshalJSON](/src/target/pub_key.go?s=4405:4459#L171) -``` go -func (p PubKeySecp256k1) MarshalJSON() ([]byte, error) -``` - - - -### func (PubKeySecp256k1) [String](/src/target/pub_key.go?s=4650:4695#L182) -``` go -func (pubKey PubKeySecp256k1) String() string -``` - - - -### func (\*PubKeySecp256k1) [UnmarshalJSON](/src/target/pub_key.go?s=4500:4557#L175) -``` go -func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error -``` - - - -### func (PubKeySecp256k1) [VerifyBytes](/src/target/pub_key.go?s=3875:3949#L149) -``` go -func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool -``` - - - -## type [Signature](/src/target/signature.go?s=204:304#L3) -``` go -type Signature interface { - Bytes() []byte - IsZero() bool - String() string - Equals(Signature) bool -} -``` -Signature is a part of Txs and consensus Votes. - - - - - - - -### func [SignatureFromBytes](/src/target/signature.go?s=1031:1098#L40) -``` go -func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) -``` - - - - -## type [SignatureEd25519](/src/target/signature.go?s=1221:1251#L48) -``` go -type SignatureEd25519 [64]byte -``` -Implements Signature - - - - - - - - - - -### func (SignatureEd25519) [Bytes](/src/target/signature.go?s=1253:1295#L50) -``` go -func (sig SignatureEd25519) Bytes() []byte -``` - - - -### func (SignatureEd25519) [Equals](/src/target/signature.go?s=1520:1576#L58) -``` go -func (sig SignatureEd25519) Equals(other Signature) bool -``` - - - -### func (SignatureEd25519) [IsZero](/src/target/signature.go?s=1352:1393#L54) -``` go -func (sig SignatureEd25519) IsZero() bool -``` - - - -### func (SignatureEd25519) [MarshalJSON](/src/target/signature.go?s=1701:1756#L66) -``` go -func (p SignatureEd25519) MarshalJSON() ([]byte, error) -``` - - - -### func (SignatureEd25519) [String](/src/target/signature.go?s=1420:1463#L56) -``` go -func (sig SignatureEd25519) String() string -``` - - - -### func (\*SignatureEd25519) [UnmarshalJSON](/src/target/signature.go?s=1797:1855#L70) -``` go -func (p *SignatureEd25519) UnmarshalJSON(enc []byte) error -``` - - - -## type [SignatureS](/src/target/signature.go?s=648:685#L20) -``` go -type SignatureS struct { - Signature -} -``` -SignatureS add json serialization to Signature - - - - - - - - - - -### func (SignatureS) [Empty](/src/target/signature.go?s=966:998#L36) -``` go -func (p SignatureS) Empty() bool -``` - - - -### func (SignatureS) [MarshalJSON](/src/target/signature.go?s=687:736#L24) -``` go -func (p SignatureS) MarshalJSON() ([]byte, error) -``` - - - -### func (\*SignatureS) [UnmarshalJSON](/src/target/signature.go?s=780:839#L28) -``` go -func (p *SignatureS) UnmarshalJSON(data []byte) (err error) -``` - - - -## type [SignatureSecp256k1](/src/target/signature.go?s=2013:2043#L80) -``` go -type SignatureSecp256k1 []byte -``` -Implements Signature - - - - - - - - - - -### func (SignatureSecp256k1) [Bytes](/src/target/signature.go?s=2045:2089#L82) -``` go -func (sig SignatureSecp256k1) Bytes() []byte -``` - - - -### func (SignatureSecp256k1) [Equals](/src/target/signature.go?s=2318:2376#L90) -``` go -func (sig SignatureSecp256k1) Equals(other Signature) bool -``` - - - -### func (SignatureSecp256k1) [IsZero](/src/target/signature.go?s=2146:2189#L86) -``` go -func (sig SignatureSecp256k1) IsZero() bool -``` - - - -### func (SignatureSecp256k1) [MarshalJSON](/src/target/signature.go?s=2502:2559#L97) -``` go -func (p SignatureSecp256k1) MarshalJSON() ([]byte, error) -``` - - - -### func (SignatureSecp256k1) [String](/src/target/signature.go?s=2216:2261#L88) -``` go -func (sig SignatureSecp256k1) String() string -``` - - - -### func (\*SignatureSecp256k1) [UnmarshalJSON](/src/target/signature.go?s=2597:2657#L101) -``` go -func (p *SignatureSecp256k1) UnmarshalJSON(enc []byte) error -``` - - - - - - - -- - - -Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md) +## Importing it +`import "github.com/tendermint/go-crypto"` \ No newline at end of file From 1bc8de4caa844f8b64c120e65b047898f22b7f3e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 6 Sep 2017 02:32:37 -0400 Subject: [PATCH 114/273] remove String() from Signature. closes #29 --- signature.go | 1 - 1 file changed, 1 deletion(-) diff --git a/signature.go b/signature.go index 1c5b8d69e..5b1d6cb05 100644 --- a/signature.go +++ b/signature.go @@ -23,7 +23,6 @@ type SignatureInner interface { AssertIsSignatureInner() Bytes() []byte IsZero() bool - String() string Equals(Signature) bool Wrap() Signature } From 54260853d55178ce90c10f2c8b76327386403d9a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 29 Aug 2017 20:42:50 +0200 Subject: [PATCH 115/273] encoder accepts empty string as unencoded bytes --- keys/cryptostore/encoder.go | 18 ++++++++++----- keys/cryptostore/encoder_test.go | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 12792813c..31cbc2e54 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -28,18 +28,24 @@ func secret(passphrase string) []byte { type secretbox struct{} func (e secretbox) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { + if pass == "" { + return key.Bytes(), nil + } s := secret(pass) cipher := crypto.EncryptSymmetric(key.Bytes(), s) return cipher, nil } -func (e secretbox) Decrypt(data []byte, pass string) (crypto.PrivKey, error) { - s := secret(pass) - private, err := crypto.DecryptSymmetric(data, s) - if err != nil { - return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") +func (e secretbox) Decrypt(data []byte, pass string) (key crypto.PrivKey, err error) { + private := data + if pass != "" { + s := secret(pass) + private, err = crypto.DecryptSymmetric(data, s) + if err != nil { + return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") + } } - key, err := crypto.PrivKeyFromBytes(private) + key, err = crypto.PrivKeyFromBytes(private) return key, errors.Wrap(err, "Invalid Passphrase") } diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go index 945e19865..f468591f3 100644 --- a/keys/cryptostore/encoder_test.go +++ b/keys/cryptostore/encoder_test.go @@ -60,3 +60,42 @@ func TestSecretBox(t *testing.T) { require.Nil(err) assert.Equal(key, pk) } + +func TestSecretBoxNoPass(t *testing.T) { + assert, require := assert.New(t), require.New(t) + enc := cryptostore.SecretBox + + key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + + cases := []struct { + encode string + decode string + valid bool + }{ + {"foo", "foo", true}, + {"foo", "food", false}, + {"", "", true}, + {"", "a", false}, + {"a", "", false}, + } + + for i, tc := range cases { + b, err := enc.Encrypt(key, tc.encode) + require.Nil(err, "%d: %+v", i, err) + assert.NotEmpty(b, "%d", i) + + pk, err := enc.Decrypt(b, tc.decode) + if tc.valid { + require.Nil(err, "%d: %+v", i, err) + assert.Equal(key, pk, "%d", i) + } else { + require.NotNil(err, "%d", i) + } + } + + // now let's make sure raw bytes also work... + b := key.Bytes() + pk, err := enc.Decrypt(b, "") + require.Nil(err, "%+v", err) + assert.Equal(key, pk) +} From e283f580b79a18c535efafa11588b641f0017931 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 29 Aug 2017 20:49:04 +0200 Subject: [PATCH 116/273] Test importing raw private key --- keys/cryptostore/holder_test.go | 39 ++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index c17eef24b..434966f46 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -5,6 +5,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + cmn "github.com/tendermint/tmlibs/common" + crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto/keys" "github.com/tendermint/go-crypto/keys/cryptostore" @@ -148,6 +151,32 @@ func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, assert.Nil(err, "%+v", err) } +// TestImportUnencrypted tests accepting raw priv keys bytes as input +func TestImportUnencrypted(t *testing.T) { + require := require.New(t) + + // make the storage with reasonable defaults + cstore := cryptostore.New( + cryptostore.SecretBox, + memstorage.New(), + keys.MustLoadCodec("english"), + ) + + key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + addr := key.PubKey().Address() + name := "john" + pass := "top-secret" + + // import raw bytes + err := cstore.Import(name, pass, "", key.Bytes()) + require.Nil(err, "%+v", err) + + // make sure the address matches + info, err := cstore.Get(name) + require.Nil(err, "%+v", err) + require.EqualValues(addr, info.Address) +} + // TestAdvancedKeyManagement verifies update, import, export functionality func TestAdvancedKeyManagement(t *testing.T) { assert, require := assert.New(t), require.New(t) @@ -190,16 +219,6 @@ func TestAdvancedKeyManagement(t *testing.T) { // import fails on bad transfer pass err = cstore.Import(n2, p3, p2, exported) assert.NotNil(err) - // import cannot overwrite existing keys - err = cstore.Import(n1, p3, pt, exported) - assert.NotNil(err) - // we can now import under another name - err = cstore.Import(n2, p3, pt, exported) - require.Nil(err, "%+v", err) - - // make sure both passwords are now properly set (not to the transfer pass) - assertPassword(assert, cstore, n1, p2, pt) - assertPassword(assert, cstore, n2, p3, pt) } // TestSeedPhrase verifies restoring from a seed phrase From 21f6b346a3799ab05bcf875dbc9149a3b73c587c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 8 Sep 2017 20:26:56 +0200 Subject: [PATCH 117/273] Removed all cli as it goes into cosmos-sdk --- Makefile | 18 +----- cmd/README.md | 117 -------------------------------------- cmd/delete.go | 49 ---------------- cmd/get.go | 42 -------------- cmd/keys/main.go | 30 ---------- cmd/list.go | 34 ----------- cmd/new.go | 94 ------------------------------- cmd/recover.go | 61 -------------------- cmd/root.go | 50 ---------------- cmd/serve.go | 110 ------------------------------------ cmd/update.go | 53 ----------------- cmd/utils.go | 144 ----------------------------------------------- tests/keys.sh | 142 ---------------------------------------------- 13 files changed, 2 insertions(+), 942 deletions(-) delete mode 100644 cmd/README.md delete mode 100644 cmd/delete.go delete mode 100644 cmd/get.go delete mode 100644 cmd/keys/main.go delete mode 100644 cmd/list.go delete mode 100644 cmd/new.go delete mode 100644 cmd/recover.go delete mode 100644 cmd/root.go delete mode 100644 cmd/serve.go delete mode 100644 cmd/update.go delete mode 100644 cmd/utils.go delete mode 100755 tests/keys.sh diff --git a/Makefile b/Makefile index 8387f0608..0f414e1c2 100644 --- a/Makefile +++ b/Makefile @@ -5,24 +5,10 @@ GOTOOLS = \ github.com/jteeuwen/go-bindata/go-bindata REPO:=github.com/tendermint/go-crypto -all: get_vendor_deps install test +all: get_vendor_deps test -install: - go install ./cmd/keys - -test: test_unit test_cli - -test_unit: +test: go test `glide novendor` - #go run tests/tendermint/*.go - -test_cli: tests/shunit2 - # sudo apt-get install jq - @./tests/keys.sh - -tests/shunit2: - wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ - -q -O tests/shunit2 get_vendor_deps: ensure_tools @rm -rf vendor/ diff --git a/cmd/README.md b/cmd/README.md deleted file mode 100644 index 8bf9ca73b..000000000 --- a/cmd/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# Keys CLI - -This is as much an example how to expose cobra/viper, as for a cli itself -(I think this code is overkill for what go-keys needs). But please look at -the commands, and give feedback and changes. - -`RootCmd` calls some initialization functions (`cobra.OnInitialize` and `RootCmd.PersistentPreRunE`) which serve to connect environmental variables and cobra flags, as well as load the config file. It also validates the flags registered on root and creates the cryptomanager, which will be used by all subcommands. - -## Help info - -``` -# keys help - -Keys allows you to manage your local keystore for tendermint. - -These keys may be in any format supported by go-crypto and can be -used by light-clients, full nodes, or any other application that -needs to sign with a private key. - -Usage: - keys [command] - -Available Commands: - get Get details of one key - list List all keys - new Create a new public/private key pair - serve Run the key manager as an http server - update Change the password for a private key - -Flags: - --keydir string Directory to store private keys (subdir of root) (default "keys") - -o, --output string Output format (text|json) (default "text") - -r, --root string root directory for config and data (default "/Users/ethan/.tlc") - -Use "keys [command] --help" for more information about a command. -``` - -## Getting the config file - -The first step is to load in root, by checking the following in order: - -* -r, --root command line flag -* TM_ROOT environmental variable -* default ($HOME/.tlc evaluated at runtime) - -Once the `rootDir` is established, the script looks for a config file named `keys.{json,toml,yaml,hcl}` in that directory and parses it. These values will provide defaults for flags of the same name. - -There is an example config file for testing out locally, which writes keys to `./.mykeys`. You can - -## Getting/Setting variables - -When we want to get the value of a user-defined variable (eg. `output`), we can call `viper.GetString("output")`, which will do the following checks, until it finds a match: - -* Is `--output` command line flag present? -* Is `TM_OUTPUT` environmental variable set? -* Was a config file found and does it have an `output` variable? -* Is there a default set on the command line flag? - -If no variable is set and there was no default, we get back "". - -This setup allows us to have powerful command line flags, but use env variables or config files (local or 12-factor style) to avoid passing these arguments every time. - -## Nesting structures - -Sometimes we don't just need key-value pairs, but actually a multi-level config file, like - -``` -[mail] -from = "no-reply@example.com" -server = "mail.example.com" -port = 567 -password = "XXXXXX" -``` - -This CLI is too simple to warant such a structure, but I think eg. tendermint could benefit from such an approach. Here are some pointers: - -* [Accessing nested keys from config files](https://github.com/spf13/viper#accessing-nested-keys) -* [Overriding nested values with envvars](https://www.netlify.com/blog/2016/09/06/creating-a-microservice-boilerplate-in-go/#nested-config-values) - the mentioned outstanding PR is already merged into master! -* Overriding nested values with cli flags? (use `--log_config.level=info` ??) - -I'd love to see an example of this fully worked out in a more complex CLI. - -## Have your cake and eat it too - -It's easy to render data different ways. Some better for viewing, some better for importing to other programs. You can just add some global (persistent) flags to control the output formatting, and everyone gets what they want. - -``` -# keys list -e hex -All keys: -betty d0789984492b1674e276b590d56b7ae077f81adc -john b77f4720b220d1411a649b6c7f1151eb6b1c226a - -# keys list -e btc -All keys: -betty 3uTF4r29CbtnzsNHZoPSYsE4BDwH -john 3ZGp2Md35iw4XVtRvZDUaAEkCUZP - -# keys list -e b64 -o json -[ - { - "name": "betty", - "address": "0HiZhEkrFnTidrWQ1Wt64Hf4Gtw=", - "pubkey": { - "type": "secp256k1", - "data": "F83WvhT0KwttSoqQqd_0_r2ztUUaQix5EXdO8AZyREoV31Og780NW59HsqTAb2O4hZ-w-j0Z-4b2IjfdqqfhVQ==" - } - }, - { - "name": "john", - "address": "t39HILIg0UEaZJtsfxFR62scImo=", - "pubkey": { - "type": "ed25519", - "data": "t1LFmbg_8UTwj-n1wkqmnTp6NfaOivokEhlYySlGYCY=" - } - } -] -``` diff --git a/cmd/delete.go b/cmd/delete.go deleted file mode 100644 index 033cf2768..000000000 --- a/cmd/delete.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright © 2017 Ethan Frey -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "fmt" - - "github.com/pkg/errors" - - "github.com/spf13/cobra" -) - -// deleteCmd represents the delete command -var deleteCmd = &cobra.Command{ - Use: "delete [name]", - Short: "DANGER: Delete a private key from your system", - RunE: runDeleteCmd, -} - -func runDeleteCmd(cmd *cobra.Command, args []string) error { - if len(args) != 1 || len(args[0]) == 0 { - return errors.New("You must provide a name for the key") - } - name := args[0] - - oldpass, err := getPassword("DANGER - enter password to permanently delete key:") - if err != nil { - return err - } - - err = GetKeyManager().Delete(name, oldpass) - if err != nil { - return err - } - fmt.Println("Password deleted forever (uh oh!)") - return nil -} diff --git a/cmd/get.go b/cmd/get.go deleted file mode 100644 index dfade2b74..000000000 --- a/cmd/get.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright © 2017 Ethan Frey -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "github.com/pkg/errors" - - "github.com/spf13/cobra" -) - -// getCmd represents the get command -var getCmd = &cobra.Command{ - Use: "get [name]", - Short: "Get details of one key", - Long: `Return public details of one local key.`, - RunE: runGetCmd, -} - -func runGetCmd(cmd *cobra.Command, args []string) error { - if len(args) != 1 || len(args[0]) == 0 { - return errors.New("You must provide a name for the key") - } - name := args[0] - - info, err := GetKeyManager().Get(name) - if err == nil { - printInfo(info) - } - return err -} diff --git a/cmd/keys/main.go b/cmd/keys/main.go deleted file mode 100644 index 8780f7bbc..000000000 --- a/cmd/keys/main.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright © 2017 Ethan Frey -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "os" - - "github.com/tendermint/go-crypto/cmd" - "github.com/tendermint/tmlibs/cli" -) - -func main() { - // for demos, we enable the key server, probably don't want this - // in most binaries we embed the key management into - cmd.RegisterServer() - root := cli.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc")) - root.Execute() -} diff --git a/cmd/list.go b/cmd/list.go deleted file mode 100644 index 51eeeda12..000000000 --- a/cmd/list.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright © 2017 Ethan Frey -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import "github.com/spf13/cobra" - -// listCmd represents the list command -var listCmd = &cobra.Command{ - Use: "list", - Short: "List all keys", - Long: `Return a list of all public keys stored by this key manager -along with their associated name and address.`, - RunE: runListCmd, -} - -func runListCmd(cmd *cobra.Command, args []string) error { - infos, err := GetKeyManager().List() - if err == nil { - printInfos(infos) - } - return err -} diff --git a/cmd/new.go b/cmd/new.go deleted file mode 100644 index ce4634074..000000000 --- a/cmd/new.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright © 2017 Ethan Frey -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "fmt" - - "github.com/pkg/errors" - "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-wire/data" - "github.com/tendermint/tmlibs/cli" - - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -const ( - flagType = "type" - flagNoBackup = "no-backup" -) - -// newCmd represents the new command -var newCmd = &cobra.Command{ - Use: "new [name]", - Short: "Create a new public/private key pair", - Long: `Add a public/private key pair to the key store. -The password muts be entered in the terminal and not -passed as a command line argument for security.`, - RunE: runNewCmd, -} - -func init() { - newCmd.Flags().StringP(flagType, "t", "ed25519", "Type of key (ed25519|secp256k1)") - newCmd.Flags().Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)") -} - -func runNewCmd(cmd *cobra.Command, args []string) error { - if len(args) != 1 || len(args[0]) == 0 { - return errors.New("You must provide a name for the key") - } - name := args[0] - algo := viper.GetString(flagType) - - pass, err := getCheckPassword("Enter a passphrase:", "Repeat the passphrase:") - if err != nil { - return err - } - - info, seed, err := GetKeyManager().Create(name, pass, algo) - if err == nil { - printCreate(info, seed) - } - return err -} - -type NewOutput struct { - Key keys.Info `json:"key"` - Seed string `json:"seed"` -} - -func printCreate(info keys.Info, seed string) { - switch viper.Get(cli.OutputFlag) { - case "text": - printInfo(info) - // print seed unless requested not to. - if !viper.GetBool(flagNoBackup) { - fmt.Println("**Important** write this seed phrase in a safe place.") - fmt.Println("It is the only way to recover your account if you ever forget your password.\n") - fmt.Println(seed) - } - case "json": - out := NewOutput{Key: info} - if !viper.GetBool(flagNoBackup) { - out.Seed = seed - } - json, err := data.ToJSON(out) - if err != nil { - panic(err) // really shouldn't happen... - } - fmt.Println(string(json)) - } -} diff --git a/cmd/recover.go b/cmd/recover.go deleted file mode 100644 index 4896c4e05..000000000 --- a/cmd/recover.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright © 2017 Ethan Frey -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "github.com/pkg/errors" - - "github.com/spf13/cobra" -) - -// recoverCmd represents the recover command -var recoverCmd = &cobra.Command{ - Use: "recover [name]", - Short: "Recover a private key from a seed phrase", - Long: `Recover a private key from a seed phrase. - -I really hope you wrote this down when you created the new key. -The seed is only displayed on creation, never again. - -You can also use this to copy a key between multiple testnets, -simply by "recovering" the key in the other nets you want to copy -to. Of course, it has no coins on the other nets, just the same address.`, - RunE: runRecoverCmd, -} - -func runRecoverCmd(cmd *cobra.Command, args []string) error { - if len(args) != 1 || len(args[0]) == 0 { - return errors.New("You must provide a name for the key") - } - name := args[0] - - pass, err := getPassword("Enter the new passphrase:") - if err != nil { - return err - } - - // not really a password... huh? - seed, err := getSeed("Enter your recovery seed phrase:") - if err != nil { - return err - } - - info, err := GetKeyManager().Recover(name, pass, seed) - if err != nil { - return err - } - printInfo(info) - return nil -} diff --git a/cmd/root.go b/cmd/root.go deleted file mode 100644 index cfd3d1adf..000000000 --- a/cmd/root.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright © 2017 Ethan Frey -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "github.com/spf13/cobra" - keys "github.com/tendermint/go-crypto/keys" -) - -const KeySubdir = "keys" - -var ( - manager keys.Manager -) - -// RootCmd represents the base command when called without any subcommands -var RootCmd = &cobra.Command{ - Use: "keys", - Short: "Key manager for tendermint clients", - Long: `Keys allows you to manage your local keystore for tendermint. - -These keys may be in any format supported by go-crypto and can be -used by light-clients, full nodes, or any other application that -needs to sign with a private key.`, -} - -func init() { - RootCmd.AddCommand(getCmd) - RootCmd.AddCommand(listCmd) - RootCmd.AddCommand(newCmd) - RootCmd.AddCommand(updateCmd) - RootCmd.AddCommand(deleteCmd) - RootCmd.AddCommand(recoverCmd) -} - -func RegisterServer() { - RootCmd.AddCommand(serveCmd) -} diff --git a/cmd/serve.go b/cmd/serve.go deleted file mode 100644 index 8cf7d12d4..000000000 --- a/cmd/serve.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright © 2017 Ethan Frey -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "fmt" - "net" - "net/http" - "os" - - "github.com/gorilla/handlers" - "github.com/gorilla/mux" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "github.com/tendermint/go-crypto/keys/server" -) - -const ( - flagPort = "port" - flagSocket = "socket" -) - -// serveCmd represents the serve command -var serveCmd = &cobra.Command{ - Use: "serve", - Short: "Run the key manager as an http server", - Long: `Launch an http server with a rest api to manage the -private keys much more in depth than the cli can perform. -In particular, this will allow you to sign transactions with -the private keys in the store.`, - RunE: runServeCmd, -} - -func init() { - serveCmd.Flags().IntP(flagPort, "p", 8118, "TCP Port for listen for http server") - serveCmd.Flags().StringP(flagSocket, "s", "", "UNIX socket for more secure http server") - serveCmd.Flags().StringP(flagType, "t", "ed25519", "Default key type (ed25519|secp256k1)") -} - -func runServeCmd(cmd *cobra.Command, args []string) error { - var l net.Listener - var err error - socket := viper.GetString(flagSocket) - if socket != "" { - l, err = createSocket(socket) - if err != nil { - return errors.Wrap(err, "Cannot create socket") - } - } else { - port := viper.GetInt(flagPort) - l, err = net.Listen("tcp", fmt.Sprintf(":%d", port)) - if err != nil { - return errors.Errorf("Cannot listen on port %d", port) - } - } - - router := mux.NewRouter() - ks := server.New(GetKeyManager(), viper.GetString(flagType)) - ks.Register(router) - - // only set cors for tcp listener - var h http.Handler - if socket == "" { - allowedHeaders := handlers.AllowedHeaders([]string{"Content-Type"}) - h = handlers.CORS(allowedHeaders)(router) - } else { - h = router - } - - err = http.Serve(l, h) - fmt.Printf("Server Killed: %+v\n", err) - return nil -} - -// createSocket deletes existing socket if there, creates a new one, -// starts a server on the socket, and sets permissions to 0600 -func createSocket(socket string) (net.Listener, error) { - err := os.Remove(socket) - if err != nil && !os.IsNotExist(err) { - // only fail if it does exist and cannot be deleted - return nil, err - } - - l, err := net.Listen("unix", socket) - if err != nil { - return nil, err - } - - mode := os.FileMode(0700) | os.ModeSocket - err = os.Chmod(socket, mode) - if err != nil { - l.Close() - return nil, err - } - - return l, nil -} diff --git a/cmd/update.go b/cmd/update.go deleted file mode 100644 index f31af509c..000000000 --- a/cmd/update.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2017 Ethan Frey -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "fmt" - - "github.com/pkg/errors" - - "github.com/spf13/cobra" -) - -// updateCmd represents the update command -var updateCmd = &cobra.Command{ - Use: "update [name]", - Short: "Change the password for a private key", - RunE: runUpdateCmd, -} - -func runUpdateCmd(cmd *cobra.Command, args []string) error { - if len(args) != 1 || len(args[0]) == 0 { - return errors.New("You must provide a name for the key") - } - name := args[0] - - oldpass, err := getPassword("Enter the current passphrase:") - if err != nil { - return err - } - newpass, err := getCheckPassword("Enter the new passphrase:", "Repeat the new passphrase:") - if err != nil { - return err - } - - err = GetKeyManager().Update(name, oldpass, newpass) - if err != nil { - return err - } - fmt.Println("Password successfully updated!") - return nil -} diff --git a/cmd/utils.go b/cmd/utils.go deleted file mode 100644 index b1550a127..000000000 --- a/cmd/utils.go +++ /dev/null @@ -1,144 +0,0 @@ -package cmd - -import ( - "bufio" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/bgentry/speakeasy" - "github.com/mattn/go-isatty" - "github.com/pkg/errors" - "github.com/spf13/viper" - - data "github.com/tendermint/go-wire/data" - "github.com/tendermint/tmlibs/cli" - - keys "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/cryptostore" - "github.com/tendermint/go-crypto/keys/storage/filestorage" -) - -const MinPassLength = 10 - -// GetKeyManager initializes a key manager based on the configuration -func GetKeyManager() keys.Manager { - if manager == nil { - // store the keys directory - rootDir := viper.GetString(cli.HomeFlag) - keyDir := filepath.Join(rootDir, KeySubdir) - - // TODO: smarter loading??? with language and fallback? - codec := keys.MustLoadCodec("english") - - // and construct the key manager - manager = cryptostore.New( - cryptostore.SecretBox, - filestorage.New(keyDir), - codec, - ) - } - return manager -} - -// if we read from non-tty, we just need to init the buffer reader once, -// in case we try to read multiple passwords (eg. update) -var buf *bufio.Reader - -func inputIsTty() bool { - return isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd()) -} - -func stdinPassword() (string, error) { - if buf == nil { - buf = bufio.NewReader(os.Stdin) - } - pass, err := buf.ReadString('\n') - if err != nil { - return "", err - } - return strings.TrimSpace(pass), nil -} - -func getPassword(prompt string) (pass string, err error) { - if inputIsTty() { - pass, err = speakeasy.Ask(prompt) - } else { - pass, err = stdinPassword() - } - if err != nil { - return "", err - } - if len(pass) < MinPassLength { - return "", errors.Errorf("Password must be at least %d characters", MinPassLength) - } - return pass, nil -} - -func getSeed(prompt string) (seed string, err error) { - if inputIsTty() { - fmt.Println(prompt) - } - seed, err = stdinPassword() - seed = strings.TrimSpace(seed) - return -} - -func getCheckPassword(prompt, prompt2 string) (string, error) { - // simple read on no-tty - if !inputIsTty() { - return getPassword(prompt) - } - - // TODO: own function??? - pass, err := getPassword(prompt) - if err != nil { - return "", err - } - pass2, err := getPassword(prompt2) - if err != nil { - return "", err - } - if pass != pass2 { - return "", errors.New("Passphrases don't match") - } - return pass, nil -} - -func printInfo(info keys.Info) { - switch viper.Get(cli.OutputFlag) { - case "text": - addr, err := data.ToText(info.Address) - if err != nil { - panic(err) // really shouldn't happen... - } - sep := "\t\t" - if len(info.Name) > 7 { - sep = "\t" - } - fmt.Printf("%s%s%s\n", info.Name, sep, addr) - case "json": - json, err := data.ToJSON(info) - if err != nil { - panic(err) // really shouldn't happen... - } - fmt.Println(string(json)) - } -} - -func printInfos(infos keys.Infos) { - switch viper.Get(cli.OutputFlag) { - case "text": - fmt.Println("All keys:") - for _, i := range infos { - printInfo(i) - } - case "json": - json, err := data.ToJSON(infos) - if err != nil { - panic(err) // really shouldn't happen... - } - fmt.Println(string(json)) - } -} diff --git a/tests/keys.sh b/tests/keys.sh deleted file mode 100755 index 599f3d743..000000000 --- a/tests/keys.sh +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/bash - -EXE=keys - -oneTimeSetUp() { - PASS=qwertyuiop - export TM_HOME=$HOME/.keys_test - rm -rf $TM_HOME - assertTrue $? -} - -newKey(){ - assertNotNull "keyname required" "$1" - KEYPASS=${2:-qwertyuiop} - KEY=$(echo $KEYPASS | ${EXE} new $1 -o json) - if ! assertTrue "created $1" $?; then return 1; fi - assertEquals "$1" $(echo $KEY | jq .key.name | tr -d \") - return $? -} - -# updateKey -updateKey() { - (echo $2; echo $3) | keys update $1 > /dev/null - return $? -} - -test00MakeKeys() { - USER=demouser - assertFalse "already user $USER" "${EXE} get $USER" - newKey $USER - assertTrue "no user $USER" "${EXE} get $USER" - # make sure bad password not accepted - assertFalse "accepts short password" "echo 123 | keys new badpass" -} - -test01ListKeys() { - # one line plus the number of keys - assertEquals "2" $(keys list | wc -l) - newKey foobar - assertEquals "3" $(keys list | wc -l) - # we got the proper name here... - assertEquals "foobar" $(keys list -o json | jq .[1].name | tr -d \" ) - # we get all names in normal output - EXPECTEDNAMES=$(echo demouser; echo foobar) - TEXTNAMES=$(keys list | tail -n +2 | cut -f1) - assertEquals "$EXPECTEDNAMES" "$TEXTNAMES" - # let's make sure the addresses match! - assertEquals "text and json addresses don't match" $(keys list | tail -1 | cut -f3) $(keys list -o json | jq .[1].address | tr -d \") -} - -test02updateKeys() { - USER=changer - PASS1=awsedrftgyhu - PASS2=S4H.9j.D9S7hso - PASS3=h8ybO7GY6d2 - - newKey $USER $PASS1 - assertFalse "accepts invalid pass" "updateKey $USER $PASS2 $PASS2" - assertTrue "doesn't update" "updateKey $USER $PASS1 $PASS2" - assertTrue "takes new key after update" "updateKey $USER $PASS2 $PASS3" -} - -test03recoverKeys() { - USER=sleepy - PASS1=S4H.9j.D9S7hso - - USER2=easy - PASS2=1234567890 - - # make a user and check they exist - KEY=$(echo $PASS1 | ${EXE} new $USER -o json) - if ! assertTrue "created $USER" $?; then return 1; fi - if [ -n "$DEBUG" ]; then echo $KEY; echo; fi - - SEED=$(echo $KEY | jq .seed | tr -d \") - ADDR=$(echo $KEY | jq .key.address | tr -d \") - PUBKEY=$(echo $KEY | jq .key.pubkey | tr -d \") - assertTrue "${EXE} get $USER > /dev/null" - - # let's delete this key - assertFalse "echo foo | ${EXE} delete $USER > /dev/null" - assertTrue "echo $PASS1 | ${EXE} delete $USER > /dev/null" - assertFalse "${EXE} get $USER > /dev/null" - - # fails on short password - assertFalse "echo foo; echo $SEED | ${EXE} recover $USER2 -o json > /dev/null" - # fails on bad seed - assertFalse "echo $PASS2; echo \"silly white whale tower bongo\" | ${EXE} recover $USER2 -o json > /dev/null" - # now we got it - KEY2=$((echo $PASS2; echo $SEED) | ${EXE} recover $USER2 -o json) - if ! assertTrue "recovery failed: $KEY2" $?; then return 1; fi - if [ -n "$DEBUG" ]; then echo $KEY2; echo; fi - - # make sure it looks the same - NAME2=$(echo $KEY2 | jq .name | tr -d \") - ADDR2=$(echo $KEY2 | jq .address | tr -d \") - PUBKEY2=$(echo $KEY2 | jq .pubkey | tr -d \") - assertEquals "wrong username" "$USER2" "$NAME2" - assertEquals "address doesn't match" "$ADDR" "$ADDR2" - assertEquals "pubkey doesn't match" "$PUBKEY" "$PUBKEY2" - - # and we can find the info - assertTrue "${EXE} get $USER2 > /dev/null" -} - -# try recovery with secp256k1 keys -test03recoverSecp() { - USER=dings - PASS1=Sbub-U9byS7hso - - USER2=booms - PASS2=1234567890 - - KEY=$(echo $PASS1 | ${EXE} new $USER -o json -t secp256k1) - if ! assertTrue "created $USER" $?; then return 1; fi - if [ -n "$DEBUG" ]; then echo $KEY; echo; fi - - SEED=$(echo $KEY | jq .seed | tr -d \") - ADDR=$(echo $KEY | jq .key.address | tr -d \") - PUBKEY=$(echo $KEY | jq .key.pubkey | tr -d \") - assertTrue "${EXE} get $USER > /dev/null" - - # now we got it - KEY2=$((echo $PASS2; echo $SEED) | ${EXE} recover $USER2 -o json) - if ! assertTrue "recovery failed: $KEY2" $?; then return 1; fi - if [ -n "$DEBUG" ]; then echo $KEY2; echo; fi - - # make sure it looks the same - NAME2=$(echo $KEY2 | jq .name | tr -d \") - ADDR2=$(echo $KEY2 | jq .address | tr -d \") - PUBKEY2=$(echo $KEY2 | jq .pubkey | tr -d \") - assertEquals "wrong username" "$USER2" "$NAME2" - assertEquals "address doesn't match" "$ADDR" "$ADDR2" - assertEquals "pubkey doesn't match" "$PUBKEY" "$PUBKEY2" - - # and we can find the info - assertTrue "${EXE} get $USER2 > /dev/null" -} - -# load and run these tests with shunit2! -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory -. $DIR/shunit2 From c8b6d29161b9f5ca81585d55266916ccc89cd768 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 12 Sep 2017 19:31:00 -0400 Subject: [PATCH 118/273] version bump and changelog --- CHANGELOG.md | 18 ++++++++++++++++++ version.go | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 346d34fd1..798f74335 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## 0.3.0 (N/A) + +BREAKING CHANGES: + +- Remove `cmd` and `keys/tx` packages altogether: move it to the cosmos-sdk +- `cryptostore.Generator` takes a secret +- Remove `String()` from `Signature` interface + +FEATURES: + +- `keys`: add CRC16 error correcting code + +IMPROVEMENTS: + +- Allow no passwords on keys for development convenience + + + ## 0.2.1 (June 21, 2017) - Improve keys command diff --git a/version.go b/version.go index c785b1bca..23d065446 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.2.1" +const Version = "0.3.0" From 50e7c078170975532ca52004cb03a473afdebbff Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Sep 2017 14:03:28 +0200 Subject: [PATCH 119/273] Use longer checksum again --- keys/wordcodec.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keys/wordcodec.go b/keys/wordcodec.go index 214fe7e0b..c551e54ce 100644 --- a/keys/wordcodec.go +++ b/keys/wordcodec.go @@ -34,8 +34,8 @@ func NewCodec(words []string) (codec *WordCodec, err error) { res := &WordCodec{ words: words, // TODO: configure this outside??? - // check: NewIEEECRC32(), - check: NewIBMCRC16(), + check: NewIEEECRC32(), + // check: NewIBMCRC16(), } return res, nil From f6a250976439b2fd5f5b7b9e714d24220afc45e7 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Fri, 15 Sep 2017 17:07:14 -0600 Subject: [PATCH 120/273] doc.go file started Fixes #35 Updates https://github.com/tendermint/coding/issues/27 Started a doc.go file to provide an overview/high level dive into the functionality of this repo. Also added an example_test.go file in which we can put end-to-end code examples/actual usage patterns that can be copied and pasted and will always have to compile when tests are run to ensure that we don't regress. --- doc.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ example_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 doc.go create mode 100644 example_test.go diff --git a/doc.go b/doc.go new file mode 100644 index 000000000..c6701bc58 --- /dev/null +++ b/doc.go @@ -0,0 +1,48 @@ +/* +go-crypto is a customized/convenience cryptography package +for supporting Tendermint. + +It wraps select functionality of equivalent functions in the +Go standard library, for easy usage with our libraries. + +Keys: + +All key generation functions return an instance of the PrivKey interface +which implements methods + + AssertIsPrivKeyInner() + Bytes() []byte + Sign(msg []byte) Signature + PubKey() PubKey + Equals(PrivKey) bool + Wrap() PrivKey + +From the above method we can: +a) Retrieve the public key if needed + + pubKey := key.PubKey() + +For example: + privKey, err := crypto.GenPrivKeyEd25519() + if err != nil { + ... + } + pubKey := privKey.PubKey() + ... + // And then you can use the private and public key + doSomething(privKey, pubKey) + + +We also provide hashing wrappers around algorithms: + +Sha256 + sum := crypto.Sha256([]byte("This is Tendermint")) + fmt.Printf("%x\n", sum) + +Ripemd160 + sum := crypto.Ripemd160([]byte("This is consensus")) + fmt.Printf("%x\n", sum) +*/ +package crypto + +// TODO: Add more docs in here diff --git a/example_test.go b/example_test.go new file mode 100644 index 000000000..c9cd2688d --- /dev/null +++ b/example_test.go @@ -0,0 +1,35 @@ +// Copyright 2017 Tendermint. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package crypto_test + +import ( + "fmt" + + "github.com/tendermint/go-crypto" +) + +func Example_Sha256() { + sum := crypto.Sha256([]byte("This is Tendermint")) + fmt.Printf("%x\n", sum) + // Output: + // f91afb642f3d1c87c17eb01aae5cb65c242dfdbe7cf1066cc260f4ce5d33b94e +} + +func Example_Ripemd160() { + sum := crypto.Ripemd160([]byte("This is Tendermint")) + fmt.Printf("%x\n", sum) + // Output: + // 051e22663e8f0fd2f2302f1210f954adff009005 +} From e6ea9499ff958479e4a921850d2382eb599f204c Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 22 Sep 2017 10:22:55 -0400 Subject: [PATCH 121/273] glide and changelog --- CHANGELOG.md | 3 +-- glide.lock | 69 +++++++++++----------------------------------------- 2 files changed, 15 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 798f74335..63d4af1d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.3.0 (N/A) +## 0.3.0 (September 22, 2017) BREAKING CHANGES: @@ -17,7 +17,6 @@ IMPROVEMENTS: - Allow no passwords on keys for development convenience - ## 0.2.1 (June 21, 2017) - Improve keys command diff --git a/glide.lock b/glide.lock index 4cd7c5670..1c23d8bea 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: c0a2db1b80c6b1b8aab31c526ce43e22e49b23c893c78b8fdb8546aa2e7b7cc6 -updated: 2017-07-22T05:24:42.82932575-04:00 +updated: 2017-09-22T10:21:34.220901552-04:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -11,14 +11,16 @@ imports: - chaincfg/chainhash - wire - name: github.com/btcsuite/btcutil - version: 66871daeb12123ece012a9628d2798d01195c4b3 + version: 86346b5a958c0cf94186b87855469ae991be501c subpackages: - base58 - hdkeychain - name: github.com/btcsuite/fastsha256 version: 637e656429416087660c84436a2a035d69d54e2e -- name: github.com/fsnotify/fsnotify - version: 4da3e2cfbabc9f751898f250b49f2439785783a1 +- name: github.com/btcsuite/golangcrypto + version: 53f62d9b43e87a6c56975cf862af7edf33a8d0df + subpackages: + - ripemd160 - name: github.com/go-kit/kit version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 subpackages: @@ -41,47 +43,14 @@ imports: version: a4043c62cc2329bacda331d33fc908ab11ef0ec3 - name: github.com/gorilla/mux version: bcd8bc72b08df0f70df986b97f95590779502d31 -- name: github.com/hashicorp/hcl - version: 392dba7d905ed5d04a5794ba89f558b27e2ba1ca - subpackages: - - hcl/ast - - hcl/parser - - hcl/scanner - - hcl/strconv - - hcl/token - - json/parser - - json/scanner - - json/token - name: github.com/howeyc/crc16 - version: 58da63c846043d0bea709c8d47039df06577d6d9 -- name: github.com/inconshreveable/mousetrap - version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 + version: 96a97a1abb579c7ff1a8ffa77f2e72d1c314b57f - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 -- name: github.com/magiconair/properties - version: 51463bfca2576e06c62a8504b5c0f06d61312647 -- name: github.com/mattn/go-isatty - version: 9622e0cc9d8f9be434ca605520ff9a16808fee47 -- name: github.com/mitchellh/mapstructure - version: cc8532a8e9a55ea36402aa21efdf403a60d34096 -- name: github.com/pelletier/go-buffruneio - version: c37440a7cf42ac63b919c752ca73a85067e05992 -- name: github.com/pelletier/go-toml - version: 13d49d4606eb801b8f01ae542b4afc4c6ee3d84a - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/spf13/afero - version: 9be650865eab0c12963d8753212f4f9c66cdcf12 - subpackages: - - mem -- name: github.com/spf13/cast - version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 - name: github.com/spf13/cobra version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77 -- name: github.com/spf13/jwalterweatherman - version: 8f07c835e5cc1450c082fe3a439cf87b0cbb2d99 -- name: github.com/spf13/pflag - version: e57e3eeb33f795204c1ca35f56c44f83227c6e66 - name: github.com/spf13/viper version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/tendermint/ed25519 @@ -95,9 +64,8 @@ imports: - data - data/base58 - name: github.com/tendermint/tmlibs - version: 2f6f3e6aa70bb19b70a6e73210273fa127041070 + version: bffe6744ec277d60f707ab442e25513617842f8e subpackages: - - cli - common - log - name: golang.org/x/crypto @@ -112,26 +80,17 @@ imports: - poly1305 - ripemd160 - salsa20/salsa -- name: golang.org/x/sys - version: e62c3de784db939836898e5c19ffd41bece347da - subpackages: - - unix -- name: golang.org/x/text - version: 470f45bf29f4147d6fbd7dfd0a02a848e49f5bf4 - subpackages: - - transform - - unicode/norm - name: gopkg.in/go-playground/validator.v9 - version: 6d8c18553ea1ac493d049edd6f102f52e618f085 -- name: gopkg.in/yaml.v2 - version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b + version: d529ee1b0f30352444f507cc6cdac96bfd12decc testImports: -- name: github.com/cmars/basen - version: fe3947df716ebfda9847eb1b9a48f9592e06478c - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew +- name: github.com/FactomProject/basen + version: fe3947df716ebfda9847eb1b9a48f9592e06478c +- name: github.com/FactomProject/btcutilecc + version: d3a63a5752ecf3fbc06bd97365da752111c263df - name: github.com/mndrix/btcutil version: d3a63a5752ecf3fbc06bd97365da752111c263df - name: github.com/pmezard/go-difflib @@ -144,6 +103,6 @@ testImports: - assert - require - name: github.com/tyler-smith/go-bip32 - version: eb790af526c30f23a7c8b00a48e342f9d0bd6386 + version: 2c9cfd17756470a0b7c3e4b7954bae7d11035504 - name: github.com/tyler-smith/go-bip39 version: 8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc From fe66a683bcbb28d25a07299e45741a835cd13dbd Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 22 Sep 2017 13:31:01 -0400 Subject: [PATCH 122/273] linter: add metalinter to Makefile & apply some fixes --- Makefile | 38 ++++++++++++- _gen.go | 6 -- armor.go | 2 +- bcrypt/bcrypt.go | 2 +- hash.go | 1 + hd/address.go | 19 +------ hd/hd_test.go | 97 +------------------------------- keys/cryptostore/holder.go | 2 + keys/server/helpers.go | 4 +- keys/storage/filestorage/main.go | 5 +- keys/storage/memstorage/main.go | 1 + keys/wordcodec_test.go | 4 +- keys/wordlist/wordlist.go | 15 ++--- 13 files changed, 65 insertions(+), 131 deletions(-) delete mode 100644 _gen.go diff --git a/Makefile b/Makefile index 0f414e1c2..cdfee009b 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,9 @@ GOTOOLS = \ github.com/Masterminds/glide \ - github.com/jteeuwen/go-bindata/go-bindata + github.com/jteeuwen/go-bindata/go-bindata \ + github.com/alecthomas/gometalinter + REPO:=github.com/tendermint/go-crypto all: get_vendor_deps test @@ -31,3 +33,37 @@ codegen: @echo "--> regenerating all interface wrappers" @gen @echo "Done!" + +metalinter: ensure_tools + @gometalinter --install + gometalinter --vendor --deadline=600s --enable-all --disable=lll ./... + +metalinter_test: ensure_tools + @gometalinter --install + gometalinter --vendor --deadline=600s --disable-all \ + --enable=aligncheck \ + --enable=deadcode \ + --enable=gas \ + --enable=goconst \ + --enable=gocyclo \ + --enable=goimports \ + --enable=gosimple \ + --enable=gotype \ + --enable=ineffassign \ + --enable=interfacer \ + --enable=megacheck \ + --enable=misspell \ + --enable=safesql \ + --enable=staticcheck \ + --enable=structcheck \ + --enable=unconvert \ + --enable=unused \ + --enable=vetshadow \ + --enable=vet \ + --enable=unparam \ + --enable=varcheck \ + ./... + + #--enable=dupl \ + #--enable=errcheck \ + #--enable=golint \ <== comments on anything exported diff --git a/_gen.go b/_gen.go deleted file mode 100644 index a98feaf4e..000000000 --- a/_gen.go +++ /dev/null @@ -1,6 +0,0 @@ -package main - -import ( - _ "github.com/tendermint/go-wire/gen" - _ "github.com/clipperhouse/stringer" -) diff --git a/armor.go b/armor.go index 3d2eff5e7..5f199df43 100644 --- a/armor.go +++ b/armor.go @@ -22,7 +22,7 @@ func EncodeArmor(blockType string, headers map[string]string, data []byte) strin if err != nil { PanicSanity("Error encoding ascii armor: " + err.Error()) } - return string(buf.Bytes()) + return buf.String() } func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error) { diff --git a/bcrypt/bcrypt.go b/bcrypt/bcrypt.go index a6b4a2cf6..6b23b7a9d 100644 --- a/bcrypt/bcrypt.go +++ b/bcrypt/bcrypt.go @@ -50,7 +50,7 @@ func (ih InvalidHashPrefixError) Error() string { type InvalidCostError int func (ic InvalidCostError) Error() string { - return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) + return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) // nolint: unconvert } const ( diff --git a/hash.go b/hash.go index 165b1e153..b04afe085 100644 --- a/hash.go +++ b/hash.go @@ -1,3 +1,4 @@ +// nolint: goimports package crypto import ( diff --git a/hd/address.go b/hd/address.go index d7553a4d7..b6532e351 100644 --- a/hd/address.go +++ b/hd/address.go @@ -11,7 +11,6 @@ import ( "errors" "fmt" "hash" - "log" "math/big" "strconv" "strings" @@ -88,18 +87,6 @@ func ComputeTxId(rawTxHex string) string { // Private methods... -func printKeyInfo(privKeyBytes []byte, pubKeyBytes []byte, chain []byte) { - if pubKeyBytes == nil { - pubKeyBytes = PubKeyBytesFromPrivKeyBytes(privKeyBytes, true) - } - addr := AddrFromPubKeyBytes(pubKeyBytes) - log.Println("\nprikey:\t%v\npubKeyBytes:\t%v\naddr:\t%v\nchain:\t%v", - HexEncode(privKeyBytes), - HexEncode(pubKeyBytes), - addr, - HexEncode(chain)) -} - func DerivePrivateKeyForPath(privKeyBytes []byte, chain []byte, path string) []byte { data := privKeyBytes parts := strings.Split(path, "/") @@ -144,7 +131,7 @@ func DerivePublicKeyForPath(pubKeyBytes []byte, chain []byte, path string) []byt } func DerivePrivateKey(privKeyBytes []byte, chain []byte, i uint32, prime bool) ([]byte, []byte) { - data := []byte{} + data := []byte{} // nolint [ megacheck, deadcode ] if prime { i = i | 0x80000000 data = append([]byte{byte(0)}, privKeyBytes...) @@ -177,7 +164,7 @@ func addPoints(a []byte, b []byte) []byte { panic(err) } sumX, sumY := btcec.S256().Add(ap.X, ap.Y, bp.X, bp.Y) - sum := (*btcec.PublicKey)(&btcec.PublicKey{ + sum := (*btcec.PublicKey)(&btcec.PublicKey{ // nolint: unconvert Curve: btcec.S256(), X: sumX, Y: sumY, @@ -248,7 +235,7 @@ func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string { func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyBytes []byte) { x, y := btcec.S256().ScalarBaseMult(privKeyBytes) - pub := (*btcec.PublicKey)(&btcec.PublicKey{ + pub := (*btcec.PublicKey)(&btcec.PublicKey{ // nolint: unconvert Curve: btcec.S256(), X: x, Y: y, diff --git a/hd/hd_test.go b/hd/hd_test.go index b2f7d2e8f..60d77ad66 100644 --- a/hd/hd_test.go +++ b/hd/hd_test.go @@ -1,10 +1,8 @@ +// nolint: goimports package hd import ( "bytes" - "crypto/hmac" - "crypto/sha512" - "encoding/binary" "encoding/hex" "encoding/json" "fmt" @@ -15,11 +13,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/tyler-smith/go-bip39" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil/hdkeychain" - "github.com/mndrix/btcutil" - "github.com/tyler-smith/go-bip32" - "github.com/tendermint/go-crypto" ) @@ -33,7 +26,7 @@ type addrData struct { } // NOTE: atom fundraiser address -var hdPath string = "m/44'/118'/0'/0/0" +// var hdPath string = "m/44'/118'/0'/0/0" var hdToAddrTable []addrData func init() { @@ -109,13 +102,6 @@ func TestReverseBytes(t *testing.T) { } } -func ifExit(err error, n int) { - if err != nil { - fmt.Println(n, err) - os.Exit(1) - } -} - func gocrypto(seed []byte) ([]byte, []byte, []byte) { _, priv, ch, _ := ComputeMastersFromSeed(string(seed)) @@ -131,83 +117,6 @@ func gocrypto(seed []byte) ([]byte, []byte, []byte) { return HexDecode(priv), privBytes, pubBytes } -func btcsuite(seed []byte) ([]byte, []byte, []byte) { - fmt.Println("HD") - masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) - if err != nil { - hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) - hmac.Write([]byte(seed)) - intermediary := hmac.Sum(nil) - - curve := btcutil.Secp256k1() - curveParams := curve.Params() - - // Split it into our key and chain code - keyBytes := intermediary[:32] - fmt.Printf("\t%X\n", keyBytes) - fmt.Printf("\t%X\n", curveParams.N.Bytes()) - keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes)) - fmt.Printf("\t%d\n", keyInt) - } - fh := hdkeychain.HardenedKeyStart - k, err := masterKey.Child(uint32(fh + 44)) - ifExit(err, 44) - k, err = k.Child(uint32(fh + 118)) - ifExit(err, 118) - k, err = k.Child(uint32(fh + 0)) - ifExit(err, 1) - k, err = k.Child(uint32(0)) - ifExit(err, 2) - k, err = k.Child(uint32(0)) - ifExit(err, 3) - ecpriv, err := k.ECPrivKey() - ifExit(err, 10) - ecpub, err := k.ECPubKey() - ifExit(err, 11) - - priv := ecpriv.Serialize() - pub := ecpub.SerializeCompressed() - mkey, _ := masterKey.ECPrivKey() - return mkey.Serialize(), priv, pub -} - -// return priv and pub -func tylerSmith(seed []byte) ([]byte, []byte, []byte) { - masterKey, err := bip32.NewMasterKey(seed) - if err != nil { - hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) - hmac.Write([]byte(seed)) - intermediary := hmac.Sum(nil) - - curve := btcutil.Secp256k1() - curveParams := curve.Params() - - // Split it into our key and chain code - keyBytes := intermediary[:32] - fmt.Printf("\t%X\n", keyBytes) - fmt.Printf("\t%X\n", curveParams.N.Bytes()) - keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes)) - fmt.Printf("\t%d\n", keyInt) - - } - ifExit(err, 0) - fh := bip32.FirstHardenedChild - k, err := masterKey.NewChildKey(fh + 44) - ifExit(err, 44) - k, err = k.NewChildKey(fh + 118) - ifExit(err, 118) - k, err = k.NewChildKey(fh + 0) - ifExit(err, 1) - k, err = k.NewChildKey(0) - ifExit(err, 2) - k, err = k.NewChildKey(0) - ifExit(err, 3) - - priv := k.Key - pub := k.PublicKey().Key - return masterKey.Key, priv, pub -} - // Benchmarks var revBytesCases = [][]byte{ @@ -237,6 +146,6 @@ func BenchmarkReverseBytes(b *testing.B) { // sink is necessary to ensure if the compiler tries // to smart, that it won't optimize away the benchmarks. - if sink != nil { + if sink != nil { // nolint: megacheck } } diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 18437a9b5..f9e5f5bb3 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -25,11 +25,13 @@ func New(coder Encoder, store keys.Storage, codec keys.Codec) Manager { } // exists just to make sure we fulfill the Signer interface +// nolint [ megacheck, deadcode ] func (s Manager) assertSigner() keys.Signer { return s } // exists just to make sure we fulfill the Manager interface +// nolint [ megacheck, deadcode ] func (s Manager) assertKeyManager() keys.Manager { return s } diff --git a/keys/server/helpers.go b/keys/server/helpers.go index 710e4f392..4820c937e 100644 --- a/keys/server/helpers.go +++ b/keys/server/helpers.go @@ -5,6 +5,8 @@ for key management, transaction signing, and query validation. Please read the README and godoc to see how to configure the server for your application. */ + +// nolint: goimports package server import ( @@ -12,8 +14,8 @@ import ( "io/ioutil" "net/http" - data "github.com/tendermint/go-wire/data" "github.com/tendermint/go-crypto/keys/server/types" + data "github.com/tendermint/go-wire/data" "github.com/pkg/errors" ) diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go index 696b200fc..d8058a5b9 100644 --- a/keys/storage/filestorage/main.go +++ b/keys/storage/filestorage/main.go @@ -22,8 +22,8 @@ const ( PrivExt = "tlc" PubExt = "pub" keyPerm = os.FileMode(0600) - pubPerm = os.FileMode(0644) - dirPerm = os.FileMode(0700) + // pubPerm = os.FileMode(0644) + dirPerm = os.FileMode(0700) ) type FileStore struct { @@ -43,6 +43,7 @@ func New(dir string) FileStore { } // assertStorage just makes sure we implement the proper Storage interface +// nolint [ megacheck, deadcode ] func (s FileStore) assertStorage() keys.Storage { return s } diff --git a/keys/storage/memstorage/main.go b/keys/storage/memstorage/main.go index 195fa7a17..403a01318 100644 --- a/keys/storage/memstorage/main.go +++ b/keys/storage/memstorage/main.go @@ -23,6 +23,7 @@ func New() MemStore { } // assertStorage just makes sure we implement the Storage interface +// nolint [ megacheck, deadcode ] func (s MemStore) assertStorage() keys.Storage { return s } diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index 25c5439a6..a44607be2 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -119,8 +119,8 @@ func TestCheckInvalidLists(t *testing.T) { w, err := codec.BytesToWords(data) if tc.valid { assert.Nil(err, "%d: %+v", i, err) - b, err := codec.WordsToBytes(w) - assert.Nil(err, "%d: %+v", i, err) + b, err1 := codec.WordsToBytes(w) + assert.Nil(err1, "%d: %+v", i, err1) assert.Equal(data, b) } else { assert.NotNil(err, "%d", i) diff --git a/keys/wordlist/wordlist.go b/keys/wordlist/wordlist.go index 97ddb2369..915dda102 100644 --- a/keys/wordlist/wordlist.go +++ b/keys/wordlist/wordlist.go @@ -6,6 +6,7 @@ // keys/wordlist/spanish.txt // DO NOT EDIT! +// nolint: goimports package wordlist import ( @@ -204,9 +205,9 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "keys/wordlist/chinese_simplified.txt": keysWordlistChinese_simplifiedTxt, - "keys/wordlist/english.txt": keysWordlistEnglishTxt, - "keys/wordlist/japanese.txt": keysWordlistJapaneseTxt, - "keys/wordlist/spanish.txt": keysWordlistSpanishTxt, + "keys/wordlist/english.txt": keysWordlistEnglishTxt, + "keys/wordlist/japanese.txt": keysWordlistJapaneseTxt, + "keys/wordlist/spanish.txt": keysWordlistSpanishTxt, } // AssetDir returns the file names below a certain @@ -248,13 +249,14 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ "keys": &bintree{nil, map[string]*bintree{ "wordlist": &bintree{nil, map[string]*bintree{ "chinese_simplified.txt": &bintree{keysWordlistChinese_simplifiedTxt, map[string]*bintree{}}, - "english.txt": &bintree{keysWordlistEnglishTxt, map[string]*bintree{}}, - "japanese.txt": &bintree{keysWordlistJapaneseTxt, map[string]*bintree{}}, - "spanish.txt": &bintree{keysWordlistSpanishTxt, map[string]*bintree{}}, + "english.txt": &bintree{keysWordlistEnglishTxt, map[string]*bintree{}}, + "japanese.txt": &bintree{keysWordlistJapaneseTxt, map[string]*bintree{}}, + "spanish.txt": &bintree{keysWordlistSpanishTxt, map[string]*bintree{}}, }}, }}, }} @@ -305,4 +307,3 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } - From 7921fb0c05c61cf55ad8dca18d492cea741e29dc Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 22 Sep 2017 13:35:02 -0400 Subject: [PATCH 123/273] linter: last fixes & add to circle --- Makefile | 2 +- keys/cryptostore/holder_test.go | 1 + keys/server/keys.go | 1 + keys/server/keys_test.go | 3 +++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cdfee009b..4114de740 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ GOTOOLS = \ REPO:=github.com/tendermint/go-crypto -all: get_vendor_deps test +all: get_vendor_deps metalinter_test test test: go test `glide novendor` diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 434966f46..0ef4ae4ba 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -144,6 +144,7 @@ func TestKeyManagement(t *testing.T) { // } // } +// nolint: unparam func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) assert.NotNil(err) diff --git a/keys/server/keys.go b/keys/server/keys.go index 80852802e..cae3e451d 100644 --- a/keys/server/keys.go +++ b/keys/server/keys.go @@ -52,6 +52,7 @@ func (k Keys) GetKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &key) } +// nolint: unparam func (k Keys) ListKeys(w http.ResponseWriter, r *http.Request) { keys, err := k.manager.List() diff --git a/keys/server/keys_test.go b/keys/server/keys_test.go index 2aa17753c..cad415644 100644 --- a/keys/server/keys_test.go +++ b/keys/server/keys_test.go @@ -120,6 +120,7 @@ func listKeys(h http.Handler) (keys.Infos, int, error) { return data, rr.Code, err } +// nolint: unparam func getKey(h http.Handler, name string) (*keys.Info, int, error) { rr := httptest.NewRecorder() req, err := http.NewRequest("GET", "/keys/"+name, nil) @@ -137,6 +138,7 @@ func getKey(h http.Handler, name string) (*keys.Info, int, error) { return &data, rr.Code, err } +// nolint: unparam func createKey(h http.Handler, name, passphrase, algo string) (*types.CreateKeyResponse, int, error) { rr := httptest.NewRecorder() post := types.CreateKeyRequest{ @@ -165,6 +167,7 @@ func createKey(h http.Handler, name, passphrase, algo string) (*types.CreateKeyR return data, rr.Code, err } +// nolint: unparam func deleteKey(h http.Handler, name, passphrase string) (*types.ErrorResponse, int, error) { rr := httptest.NewRecorder() post := types.DeleteKeyRequest{ From 87cb57c3e5e76cab8b766253c218ec7b68ecec09 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 4 Oct 2017 18:16:48 -0400 Subject: [PATCH 124/273] linting: fixup some stuffs --- Makefile | 4 +- hash.go | 1 - hd/address.go | 24 ++++++-- hd/hd_test.go | 96 +++++++++++++++++++++++++++++++- keys/cryptostore/holder.go | 5 +- keys/cryptostore/holder_test.go | 1 - keys/server/helpers.go | 1 - keys/server/keys.go | 1 - keys/server/keys_test.go | 3 - keys/storage/filestorage/main.go | 3 +- keys/storage/memstorage/main.go | 3 +- keys/wordlist/wordlist.go | 1 - 12 files changed, 121 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 4114de740..b1dc51ae0 100644 --- a/Makefile +++ b/Makefile @@ -46,9 +46,7 @@ metalinter_test: ensure_tools --enable=gas \ --enable=goconst \ --enable=gocyclo \ - --enable=goimports \ --enable=gosimple \ - --enable=gotype \ --enable=ineffassign \ --enable=interfacer \ --enable=megacheck \ @@ -66,4 +64,6 @@ metalinter_test: ensure_tools #--enable=dupl \ #--enable=errcheck \ + #--enable=goimports \ #--enable=golint \ <== comments on anything exported + #--enable=gotype \ diff --git a/hash.go b/hash.go index b04afe085..165b1e153 100644 --- a/hash.go +++ b/hash.go @@ -1,4 +1,3 @@ -// nolint: goimports package crypto import ( diff --git a/hd/address.go b/hd/address.go index b6532e351..5b664b496 100644 --- a/hd/address.go +++ b/hd/address.go @@ -85,7 +85,19 @@ func ComputeTxId(rawTxHex string) string { return HexEncode(ReverseBytes(CalcHash256(HexDecode(rawTxHex)))) } -// Private methods... +/* +func printKeyInfo(privKeyBytes []byte, pubKeyBytes []byte, chain []byte) { + if pubKeyBytes == nil { + pubKeyBytes = PubKeyBytesFromPrivKeyBytes(privKeyBytes, true) + } + addr := AddrFromPubKeyBytes(pubKeyBytes) + log.Println("\nprikey:\t%v\npubKeyBytes:\t%v\naddr:\t%v\nchain:\t%v", + HexEncode(privKeyBytes), + HexEncode(pubKeyBytes), + addr, + HexEncode(chain)) +} +*/ func DerivePrivateKeyForPath(privKeyBytes []byte, chain []byte, path string) []byte { data := privKeyBytes @@ -131,7 +143,7 @@ func DerivePublicKeyForPath(pubKeyBytes []byte, chain []byte, path string) []byt } func DerivePrivateKey(privKeyBytes []byte, chain []byte, i uint32, prime bool) ([]byte, []byte) { - data := []byte{} // nolint [ megacheck, deadcode ] + var data []byte if prime { i = i | 0x80000000 data = append([]byte{byte(0)}, privKeyBytes...) @@ -164,11 +176,11 @@ func addPoints(a []byte, b []byte) []byte { panic(err) } sumX, sumY := btcec.S256().Add(ap.X, ap.Y, bp.X, bp.Y) - sum := (*btcec.PublicKey)(&btcec.PublicKey{ // nolint: unconvert + sum := &btcec.PublicKey{ Curve: btcec.S256(), X: sumX, Y: sumY, - }) + } return sum.SerializeCompressed() } @@ -235,11 +247,11 @@ func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string { func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyBytes []byte) { x, y := btcec.S256().ScalarBaseMult(privKeyBytes) - pub := (*btcec.PublicKey)(&btcec.PublicKey{ // nolint: unconvert + pub := &btcec.PublicKey{ Curve: btcec.S256(), X: x, Y: y, - }) + } if compress { return pub.SerializeCompressed() diff --git a/hd/hd_test.go b/hd/hd_test.go index 60d77ad66..fcb348b5c 100644 --- a/hd/hd_test.go +++ b/hd/hd_test.go @@ -1,8 +1,10 @@ -// nolint: goimports package hd import ( "bytes" + "crypto/hmac" + "crypto/sha512" + "encoding/binary" "encoding/hex" "encoding/json" "fmt" @@ -13,6 +15,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/tyler-smith/go-bip39" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcutil/hdkeychain" + "github.com/mndrix/btcutil" + "github.com/tyler-smith/go-bip32" + "github.com/tendermint/go-crypto" ) @@ -102,6 +109,13 @@ func TestReverseBytes(t *testing.T) { } } +func ifExit(err error, n int) { + if err != nil { + fmt.Println(n, err) + os.Exit(1) + } +} + func gocrypto(seed []byte) ([]byte, []byte, []byte) { _, priv, ch, _ := ComputeMastersFromSeed(string(seed)) @@ -117,6 +131,83 @@ func gocrypto(seed []byte) ([]byte, []byte, []byte) { return HexDecode(priv), privBytes, pubBytes } +func btcsuite(seed []byte) ([]byte, []byte, []byte) { + fmt.Println("HD") + masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) + if err != nil { + hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) + hmac.Write([]byte(seed)) + intermediary := hmac.Sum(nil) + + curve := btcutil.Secp256k1() + curveParams := curve.Params() + + // Split it into our key and chain code + keyBytes := intermediary[:32] + fmt.Printf("\t%X\n", keyBytes) + fmt.Printf("\t%X\n", curveParams.N.Bytes()) + keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes)) + fmt.Printf("\t%d\n", keyInt) + } + fh := hdkeychain.HardenedKeyStart + k, err := masterKey.Child(uint32(fh + 44)) + ifExit(err, 44) + k, err = k.Child(uint32(fh + 118)) + ifExit(err, 118) + k, err = k.Child(uint32(fh + 0)) + ifExit(err, 1) + k, err = k.Child(uint32(0)) + ifExit(err, 2) + k, err = k.Child(uint32(0)) + ifExit(err, 3) + ecpriv, err := k.ECPrivKey() + ifExit(err, 10) + ecpub, err := k.ECPubKey() + ifExit(err, 11) + + priv := ecpriv.Serialize() + pub := ecpub.SerializeCompressed() + mkey, _ := masterKey.ECPrivKey() + return mkey.Serialize(), priv, pub +} + +// return priv and pub +func tylerSmith(seed []byte) ([]byte, []byte, []byte) { + masterKey, err := bip32.NewMasterKey(seed) + if err != nil { + hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) + hmac.Write([]byte(seed)) + intermediary := hmac.Sum(nil) + + curve := btcutil.Secp256k1() + curveParams := curve.Params() + + // Split it into our key and chain code + keyBytes := intermediary[:32] + fmt.Printf("\t%X\n", keyBytes) + fmt.Printf("\t%X\n", curveParams.N.Bytes()) + keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes)) + fmt.Printf("\t%d\n", keyInt) + + } + ifExit(err, 0) + fh := bip32.FirstHardenedChild + k, err := masterKey.NewChildKey(fh + 44) + ifExit(err, 44) + k, err = k.NewChildKey(fh + 118) + ifExit(err, 118) + k, err = k.NewChildKey(fh + 0) + ifExit(err, 1) + k, err = k.NewChildKey(0) + ifExit(err, 2) + k, err = k.NewChildKey(0) + ifExit(err, 3) + + priv := k.Key + pub := k.PublicKey().Key + return masterKey.Key, priv, pub +} + // Benchmarks var revBytesCases = [][]byte{ @@ -146,6 +237,7 @@ func BenchmarkReverseBytes(b *testing.B) { // sink is necessary to ensure if the compiler tries // to smart, that it won't optimize away the benchmarks. - if sink != nil { // nolint: megacheck + if sink != nil { + _ = sink } } diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index f9e5f5bb3..f4d82583b 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -24,14 +24,15 @@ func New(coder Encoder, store keys.Storage, codec keys.Codec) Manager { } } +var _ keys.Signer = Manager{} +var _ keys.Manager = Manager{} + // exists just to make sure we fulfill the Signer interface -// nolint [ megacheck, deadcode ] func (s Manager) assertSigner() keys.Signer { return s } // exists just to make sure we fulfill the Manager interface -// nolint [ megacheck, deadcode ] func (s Manager) assertKeyManager() keys.Manager { return s } diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 0ef4ae4ba..434966f46 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -144,7 +144,6 @@ func TestKeyManagement(t *testing.T) { // } // } -// nolint: unparam func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) assert.NotNil(err) diff --git a/keys/server/helpers.go b/keys/server/helpers.go index 4820c937e..3fb947316 100644 --- a/keys/server/helpers.go +++ b/keys/server/helpers.go @@ -6,7 +6,6 @@ Please read the README and godoc to see how to configure the server for your application. */ -// nolint: goimports package server import ( diff --git a/keys/server/keys.go b/keys/server/keys.go index cae3e451d..80852802e 100644 --- a/keys/server/keys.go +++ b/keys/server/keys.go @@ -52,7 +52,6 @@ func (k Keys) GetKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &key) } -// nolint: unparam func (k Keys) ListKeys(w http.ResponseWriter, r *http.Request) { keys, err := k.manager.List() diff --git a/keys/server/keys_test.go b/keys/server/keys_test.go index cad415644..2aa17753c 100644 --- a/keys/server/keys_test.go +++ b/keys/server/keys_test.go @@ -120,7 +120,6 @@ func listKeys(h http.Handler) (keys.Infos, int, error) { return data, rr.Code, err } -// nolint: unparam func getKey(h http.Handler, name string) (*keys.Info, int, error) { rr := httptest.NewRecorder() req, err := http.NewRequest("GET", "/keys/"+name, nil) @@ -138,7 +137,6 @@ func getKey(h http.Handler, name string) (*keys.Info, int, error) { return &data, rr.Code, err } -// nolint: unparam func createKey(h http.Handler, name, passphrase, algo string) (*types.CreateKeyResponse, int, error) { rr := httptest.NewRecorder() post := types.CreateKeyRequest{ @@ -167,7 +165,6 @@ func createKey(h http.Handler, name, passphrase, algo string) (*types.CreateKeyR return data, rr.Code, err } -// nolint: unparam func deleteKey(h http.Handler, name, passphrase string) (*types.ErrorResponse, int, error) { rr := httptest.NewRecorder() post := types.DeleteKeyRequest{ diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go index d8058a5b9..e33ca5000 100644 --- a/keys/storage/filestorage/main.go +++ b/keys/storage/filestorage/main.go @@ -42,8 +42,9 @@ func New(dir string) FileStore { return FileStore{dir} } +var _ keys.Storage = FileStore{} + // assertStorage just makes sure we implement the proper Storage interface -// nolint [ megacheck, deadcode ] func (s FileStore) assertStorage() keys.Storage { return s } diff --git a/keys/storage/memstorage/main.go b/keys/storage/memstorage/main.go index 403a01318..6464b1308 100644 --- a/keys/storage/memstorage/main.go +++ b/keys/storage/memstorage/main.go @@ -22,8 +22,9 @@ func New() MemStore { return MemStore{} } +var _ keys.Storage = MemStore{} + // assertStorage just makes sure we implement the Storage interface -// nolint [ megacheck, deadcode ] func (s MemStore) assertStorage() keys.Storage { return s } diff --git a/keys/wordlist/wordlist.go b/keys/wordlist/wordlist.go index 915dda102..58ff41181 100644 --- a/keys/wordlist/wordlist.go +++ b/keys/wordlist/wordlist.go @@ -6,7 +6,6 @@ // keys/wordlist/spanish.txt // DO NOT EDIT! -// nolint: goimports package wordlist import ( From 796024f42f215b85ace955538ccbb5c2acddb8ea Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Wed, 4 Oct 2017 18:27:35 -0400 Subject: [PATCH 125/273] linting: little more fixes --- Makefile | 2 +- example_test.go | 10 ++++++---- hd/hd_test.go | 19 +++++++++++-------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index b1dc51ae0..c7d11ce0a 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,6 @@ metalinter_test: ensure_tools --enable=unused \ --enable=vetshadow \ --enable=vet \ - --enable=unparam \ --enable=varcheck \ ./... @@ -67,3 +66,4 @@ metalinter_test: ensure_tools #--enable=goimports \ #--enable=golint \ <== comments on anything exported #--enable=gotype \ + #--enable=unparam \ diff --git a/example_test.go b/example_test.go index c9cd2688d..fff49c84d 100644 --- a/example_test.go +++ b/example_test.go @@ -15,21 +15,23 @@ package crypto_test import ( - "fmt" +//"fmt" - "github.com/tendermint/go-crypto" +//"github.com/tendermint/go-crypto" ) -func Example_Sha256() { +/* +func example_Sha256() { sum := crypto.Sha256([]byte("This is Tendermint")) fmt.Printf("%x\n", sum) // Output: // f91afb642f3d1c87c17eb01aae5cb65c242dfdbe7cf1066cc260f4ce5d33b94e } -func Example_Ripemd160() { +func example_Ripemd160() { sum := crypto.Ripemd160([]byte("This is Tendermint")) fmt.Printf("%x\n", sum) // Output: // 051e22663e8f0fd2f2302f1210f954adff009005 } +*/ diff --git a/hd/hd_test.go b/hd/hd_test.go index fcb348b5c..02d80388c 100644 --- a/hd/hd_test.go +++ b/hd/hd_test.go @@ -2,9 +2,9 @@ package hd import ( "bytes" - "crypto/hmac" - "crypto/sha512" - "encoding/binary" + //"crypto/hmac" + //"crypto/sha512" + //"encoding/binary" "encoding/hex" "encoding/json" "fmt" @@ -15,10 +15,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/tyler-smith/go-bip39" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil/hdkeychain" - "github.com/mndrix/btcutil" - "github.com/tyler-smith/go-bip32" + //"github.com/btcsuite/btcd/chaincfg" + //"github.com/btcsuite/btcutil/hdkeychain" + //"github.com/mndrix/btcutil" + //"github.com/tyler-smith/go-bip32" "github.com/tendermint/go-crypto" ) @@ -109,12 +109,14 @@ func TestReverseBytes(t *testing.T) { } } +/* func ifExit(err error, n int) { if err != nil { fmt.Println(n, err) os.Exit(1) } } +*/ func gocrypto(seed []byte) ([]byte, []byte, []byte) { @@ -131,6 +133,7 @@ func gocrypto(seed []byte) ([]byte, []byte, []byte) { return HexDecode(priv), privBytes, pubBytes } +/* func btcsuite(seed []byte) ([]byte, []byte, []byte) { fmt.Println("HD") masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) @@ -207,9 +210,9 @@ func tylerSmith(seed []byte) ([]byte, []byte, []byte) { pub := k.PublicKey().Key return masterKey.Key, priv, pub } +*/ // Benchmarks - var revBytesCases = [][]byte{ nil, []byte(""), From 1775be1cd93549a48bc3453adb4cfb96fa8d1c60 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 5 Oct 2017 22:19:48 -0400 Subject: [PATCH 126/273] remove some assertXxx funcs --- keys/cryptostore/holder.go | 11 +---------- keys/storage/filestorage/main.go | 6 +----- keys/storage/memstorage/main.go | 6 +----- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index f4d82583b..44332f175 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -24,19 +24,10 @@ func New(coder Encoder, store keys.Storage, codec keys.Codec) Manager { } } +// assert Manager satisfies keys.Signer and keys.Manager interfaces var _ keys.Signer = Manager{} var _ keys.Manager = Manager{} -// exists just to make sure we fulfill the Signer interface -func (s Manager) assertSigner() keys.Signer { - return s -} - -// exists just to make sure we fulfill the Manager interface -func (s Manager) assertKeyManager() keys.Manager { - return s -} - // Create adds a new key to the storage engine, returning error if // another key already stored under this name // diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go index e33ca5000..bed80efb3 100644 --- a/keys/storage/filestorage/main.go +++ b/keys/storage/filestorage/main.go @@ -42,13 +42,9 @@ func New(dir string) FileStore { return FileStore{dir} } +// assert FileStore satisfies keys.Storage var _ keys.Storage = FileStore{} -// assertStorage just makes sure we implement the proper Storage interface -func (s FileStore) assertStorage() keys.Storage { - return s -} - // Put creates two files, one with the public info as json, the other // with the (encoded) private key as gpg ascii-armor style func (s FileStore) Put(name string, key []byte, info keys.Info) error { diff --git a/keys/storage/memstorage/main.go b/keys/storage/memstorage/main.go index 6464b1308..a988fe0ff 100644 --- a/keys/storage/memstorage/main.go +++ b/keys/storage/memstorage/main.go @@ -22,13 +22,9 @@ func New() MemStore { return MemStore{} } +// assert MemStore satisfies keys.Storage var _ keys.Storage = MemStore{} -// assertStorage just makes sure we implement the Storage interface -func (s MemStore) assertStorage() keys.Storage { - return s -} - // Put adds the given key, returns an error if it another key // is already stored under this name func (s MemStore) Put(name string, key []byte, info keys.Info) error { From 32dec98c1c78f9b0cb326e10e167a2d1cf12c515 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Tue, 10 Oct 2017 17:33:51 -0400 Subject: [PATCH 127/273] example: fix func suffix --- example_test.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/example_test.go b/example_test.go index fff49c84d..2c8b94549 100644 --- a/example_test.go +++ b/example_test.go @@ -15,23 +15,21 @@ package crypto_test import ( -//"fmt" + "fmt" -//"github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto" ) -/* -func example_Sha256() { +func ExampleSha256() { sum := crypto.Sha256([]byte("This is Tendermint")) fmt.Printf("%x\n", sum) // Output: // f91afb642f3d1c87c17eb01aae5cb65c242dfdbe7cf1066cc260f4ce5d33b94e } -func example_Ripemd160() { +func ExampleRipemd160() { sum := crypto.Ripemd160([]byte("This is Tendermint")) fmt.Printf("%x\n", sum) // Output: // 051e22663e8f0fd2f2302f1210f954adff009005 } -*/ From 8e7f0e7701f92206679ad093d013b9b162427631 Mon Sep 17 00:00:00 2001 From: Adrian Brink <11320251+adrianbrink@users.noreply.github.com> Date: Thu, 12 Oct 2017 14:26:59 +0200 Subject: [PATCH 128/273] Upgrade keys to use bcrypt with salts (#38) This commit adds salts to the library using bcrypt. --- keys/cryptostore/enc_storage.go | 8 +- keys/cryptostore/encoder.go | 59 +++++++----- keys/cryptostore/encoder_test.go | 20 ++-- keys/cryptostore/generator.go | 1 + keys/cryptostore/holder.go | 18 ++-- keys/cryptostore/holder_test.go | 10 +- keys/cryptostore/storage_test.go | 2 +- keys/storage.go | 4 +- keys/storage/filestorage/main.go | 130 ++++++++++++++++++++------ keys/storage/filestorage/main_test.go | 13 +-- keys/storage/memstorage/main.go | 12 ++- keys/storage/memstorage/main_test.go | 13 +-- 12 files changed, 190 insertions(+), 100 deletions(-) diff --git a/keys/cryptostore/enc_storage.go b/keys/cryptostore/enc_storage.go index daeb220b5..e0c7e59a3 100644 --- a/keys/cryptostore/enc_storage.go +++ b/keys/cryptostore/enc_storage.go @@ -12,21 +12,21 @@ type encryptedStorage struct { } func (es encryptedStorage) Put(name, pass string, key crypto.PrivKey) error { - secret, err := es.coder.Encrypt(key, pass) + saltBytes, encBytes, err := es.coder.Encrypt(key, pass) if err != nil { return err } ki := info(name, key) - return es.store.Put(name, secret, ki) + return es.store.Put(name, saltBytes, encBytes, ki) } func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.Info, error) { - secret, info, err := es.store.Get(name) + saltBytes, encBytes, info, err := es.store.Get(name) if err != nil { return crypto.PrivKey{}, info, err } - key, err := es.coder.Decrypt(secret, pass) + key, err := es.coder.Decrypt(saltBytes, encBytes, pass) return key, info, err } diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 31cbc2e54..251543b60 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -2,7 +2,9 @@ package cryptostore import ( "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto/bcrypt" ) var ( @@ -16,45 +18,54 @@ var ( // // This should use a well-designed symetric encryption algorithm type Encoder interface { - Encrypt(key crypto.PrivKey, pass string) ([]byte, error) - Decrypt(data []byte, pass string) (crypto.PrivKey, error) -} - -func secret(passphrase string) []byte { - // TODO: Sha256(Bcrypt(passphrase)) - return crypto.Sha256([]byte(passphrase)) + Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte, err error) + Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) } type secretbox struct{} -func (e secretbox) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { - if pass == "" { - return key.Bytes(), nil +func (e secretbox) Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte, err error) { + if passphrase == "" { + return nil, privKey.Bytes(), nil + } + + saltBytes = crypto.CRandBytes(16) + key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) + if err != nil { + return nil, nil, errors.Wrap(err, "Couldn't generate bcrypt key from passphrase.") } - s := secret(pass) - cipher := crypto.EncryptSymmetric(key.Bytes(), s) - return cipher, nil + key = crypto.Sha256(key) // Get 32 bytes + privKeyBytes := privKey.Bytes() + return saltBytes, crypto.EncryptSymmetric(privKeyBytes, key), nil } -func (e secretbox) Decrypt(data []byte, pass string) (key crypto.PrivKey, err error) { - private := data - if pass != "" { - s := secret(pass) - private, err = crypto.DecryptSymmetric(data, s) +func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { + privKeyBytes := encBytes + // NOTE: Some keys weren't encrypted with a passphrase and hence we have the conditional + if passphrase != "" { + key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) if err != nil { return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } + key = crypto.Sha256(key) // Get 32 bytes + privKeyBytes, err = crypto.DecryptSymmetric(encBytes, key) + if err != nil { + return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") + } + } + privKey, err = crypto.PrivKeyFromBytes(privKeyBytes) + if err != nil { + return crypto.PrivKey{}, errors.Wrap(err, "Couldn't get privKey from bytes") } - key, err = crypto.PrivKeyFromBytes(private) - return key, errors.Wrap(err, "Invalid Passphrase") + return privKey, nil } type noop struct{} -func (n noop) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { - return key.Bytes(), nil +func (n noop) Encrypt(key crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte, err error) { + return []byte{}, key.Bytes(), nil } -func (n noop) Decrypt(data []byte, pass string) (crypto.PrivKey, error) { - return crypto.PrivKeyFromBytes(data) +func (n noop) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { + return crypto.PrivKeyFromBytes(encBytes) } diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go index f468591f3..ce1118d20 100644 --- a/keys/cryptostore/encoder_test.go +++ b/keys/cryptostore/encoder_test.go @@ -18,22 +18,22 @@ func TestNoopEncoder(t *testing.T) { key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) key2 := cryptostore.GenSecp256k1.Generate(cmn.RandBytes(16)) - b, err := noop.Encrypt(key, "encode") + _, b, err := noop.Encrypt(key, "encode") require.Nil(err) assert.NotEmpty(b) - b2, err := noop.Encrypt(key2, "encode") + _, b2, err := noop.Encrypt(key2, "encode") require.Nil(err) assert.NotEmpty(b2) assert.NotEqual(b, b2) // note the decode with a different password works - not secure! - pk, err := noop.Decrypt(b, "decode") + pk, err := noop.Decrypt(nil, b, "decode") require.Nil(err) require.NotNil(pk) assert.Equal(key, pk) - pk2, err := noop.Decrypt(b2, "kggugougp") + pk2, err := noop.Decrypt(nil, b2, "kggugougp") require.Nil(err) require.NotNil(pk2) assert.Equal(key2, pk2) @@ -46,17 +46,17 @@ func TestSecretBox(t *testing.T) { key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) pass := "some-special-secret" - b, err := enc.Encrypt(key, pass) + s, b, err := enc.Encrypt(key, pass) require.Nil(err) assert.NotEmpty(b) // decoding with a different pass is an error - pk, err := enc.Decrypt(b, "decode") + pk, err := enc.Decrypt(s, b, "decode") require.NotNil(err) require.True(pk.Empty()) // but decoding with the same passphrase gets us our key - pk, err = enc.Decrypt(b, pass) + pk, err = enc.Decrypt(s, b, pass) require.Nil(err) assert.Equal(key, pk) } @@ -80,11 +80,11 @@ func TestSecretBoxNoPass(t *testing.T) { } for i, tc := range cases { - b, err := enc.Encrypt(key, tc.encode) + s, b, err := enc.Encrypt(key, tc.encode) require.Nil(err, "%d: %+v", i, err) assert.NotEmpty(b, "%d", i) - pk, err := enc.Decrypt(b, tc.decode) + pk, err := enc.Decrypt(s, b, tc.decode) if tc.valid { require.Nil(err, "%d: %+v", i, err) assert.Equal(key, pk, "%d", i) @@ -95,7 +95,7 @@ func TestSecretBoxNoPass(t *testing.T) { // now let's make sure raw bytes also work... b := key.Bytes() - pk, err := enc.Decrypt(b, "") + pk, err := enc.Decrypt(nil, b, "") require.Nil(err, "%+v", err) assert.Equal(key, pk) } diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index 0a2bb55c2..1f162ec08 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -2,6 +2,7 @@ package cryptostore import ( "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" ) diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 18437a9b5..2fc617b4e 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -100,7 +100,7 @@ func (s Manager) List() (keys.Infos, error) { // Get returns the public information about one key func (s Manager) Get(name string) (keys.Info, error) { - _, info, err := s.es.store.Get(name) + _, _, info, err := s.es.store.Get(name) return info, err } @@ -124,21 +124,23 @@ func (s Manager) Sign(name, passphrase string, tx keys.Signable) error { // // This is designed to copy from one device to another, or provide backups // during version updates. -func (s Manager) Export(name, oldpass, transferpass string) ([]byte, error) { +// TODO: How to handle Export with salt? +func (s Manager) Export(name, oldpass, transferpass string) (salt, data []byte, err error) { key, _, err := s.es.Get(name, oldpass) if err != nil { - return nil, err + return nil, nil, err } - res, err := s.es.coder.Encrypt(key, transferpass) - return res, err + salt, data, err = s.es.coder.Encrypt(key, transferpass) + return salt, data, err } // Import accepts bytes generated by Export along with the same transferpass -// If they are valid, it stores the password under the given name with the +// If they are valid, it stores the key under the given name with the // new passphrase. -func (s Manager) Import(name, newpass, transferpass string, data []byte) error { - key, err := s.es.coder.Decrypt(data, transferpass) +// TODO: How to handle Import with salt? +func (s Manager) Import(name, newpass, transferpass string, salt, data []byte) error { + key, err := s.es.coder.Decrypt(salt, data, transferpass) if err != nil { return err } diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 434966f46..7484b1517 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -168,7 +168,7 @@ func TestImportUnencrypted(t *testing.T) { pass := "top-secret" // import raw bytes - err := cstore.Import(name, pass, "", key.Bytes()) + err := cstore.Import(name, pass, "", nil, key.Bytes()) require.Nil(err, "%+v", err) // make sure the address matches @@ -209,15 +209,15 @@ func TestAdvancedKeyManagement(t *testing.T) { assertPassword(assert, cstore, n1, p2, p1) // exporting requires the proper name and passphrase - _, err = cstore.Export(n2, p2, pt) + _, _, err = cstore.Export(n2, p2, pt) assert.NotNil(err) - _, err = cstore.Export(n1, p1, pt) + _, _, err = cstore.Export(n1, p1, pt) assert.NotNil(err) - exported, err := cstore.Export(n1, p2, pt) + salt, exported, err := cstore.Export(n1, p2, pt) require.Nil(err, "%+v", err) // import fails on bad transfer pass - err = cstore.Import(n2, p3, p2, exported) + err = cstore.Import(n2, p3, p2, salt, exported) assert.NotNil(err) } diff --git a/keys/cryptostore/storage_test.go b/keys/cryptostore/storage_test.go index 907a19f11..468435143 100644 --- a/keys/cryptostore/storage_test.go +++ b/keys/cryptostore/storage_test.go @@ -5,9 +5,9 @@ import ( "github.com/stretchr/testify/assert" - crypto "github.com/tendermint/go-crypto" cmn "github.com/tendermint/tmlibs/common" + crypto "github.com/tendermint/go-crypto" keys "github.com/tendermint/go-crypto/keys" ) diff --git a/keys/storage.go b/keys/storage.go index 0c25eb8a5..0aba4ebdb 100644 --- a/keys/storage.go +++ b/keys/storage.go @@ -3,8 +3,8 @@ package keys // Storage has many implementation, based on security and sharing requirements // like disk-backed, mem-backed, vault, db, etc. type Storage interface { - Put(name string, key []byte, info Info) error - Get(name string) ([]byte, Info, error) + Put(name string, salt []byte, key []byte, info Info) error + Get(name string) (salt []byte, key []byte, info Info, err error) List() (Infos, error) Delete(name string) error } diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go index 696b200fc..bd29ce41f 100644 --- a/keys/storage/filestorage/main.go +++ b/keys/storage/filestorage/main.go @@ -6,6 +6,7 @@ like standard ssh key storage. package filestorage import ( + "encoding/hex" "fmt" "io/ioutil" "os" @@ -13,19 +14,25 @@ import ( "strings" "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" keys "github.com/tendermint/go-crypto/keys" ) const ( + // BlockType is the type of block. BlockType = "Tendermint Light Client" - PrivExt = "tlc" - PubExt = "pub" - keyPerm = os.FileMode(0600) - pubPerm = os.FileMode(0644) - dirPerm = os.FileMode(0700) + // PrivExt is the extension for private keys. + PrivExt = "tlc" + // PubExt is the extensions for public keys. + PubExt = "pub" + + keyPerm = os.FileMode(0600) + pubPerm = os.FileMode(0644) + dirPerm = os.FileMode(0700) ) +// FileStore is a file-based key storage with tight permissions. type FileStore struct { keyDir string } @@ -36,9 +43,11 @@ type FileStore struct { // be created if it doesn't exist already. func New(dir string) FileStore { err := os.MkdirAll(dir, dirPerm) + if err != nil { panic(err) } + return FileStore{dir} } @@ -49,7 +58,7 @@ func (s FileStore) assertStorage() keys.Storage { // Put creates two files, one with the public info as json, the other // with the (encoded) private key as gpg ascii-armor style -func (s FileStore) Put(name string, key []byte, info keys.Info) error { +func (s FileStore) Put(name string, salt, key []byte, info keys.Info) error { pub, priv := s.nameToPaths(name) // write public info @@ -59,31 +68,34 @@ func (s FileStore) Put(name string, key []byte, info keys.Info) error { } // write private info - return write(priv, name, key) + return write(priv, name, salt, key) } // Get loads the info and (encoded) private key from the directory // It uses `name` to generate the filename, and returns an error if the // files don't exist or are in the incorrect format -func (s FileStore) Get(name string) ([]byte, keys.Info, error) { +func (s FileStore) Get(name string) (salt []byte, key []byte, info keys.Info, err error) { pub, priv := s.nameToPaths(name) - info, err := readInfo(pub) + info, err = readInfo(pub) if err != nil { - return nil, info, err + return nil, nil, info, err } - key, _, err := read(priv) - return key, info.Format(), err + salt, key, _, err = read(priv) + return salt, key, info.Format(), err } // List parses the key directory for public info and returns a list of // Info for all keys located in this directory. func (s FileStore) List() (keys.Infos, error) { dir, err := os.Open(s.keyDir) + defer dir.Close() + if err != nil { return nil, errors.Wrap(err, "List Keys") } + names, err := dir.Readdirnames(0) if err != nil { return nil, errors.Wrap(err, "List Keys") @@ -111,61 +123,121 @@ func (s FileStore) List() (keys.Infos, error) { func (s FileStore) Delete(name string) error { pub, priv := s.nameToPaths(name) err := os.Remove(priv) + if err != nil { return errors.Wrap(err, "Deleting Private Key") } + err = os.Remove(pub) + return errors.Wrap(err, "Deleting Public Key") } func (s FileStore) nameToPaths(name string) (pub, priv string) { privName := fmt.Sprintf("%s.%s", name, PrivExt) pubName := fmt.Sprintf("%s.%s", name, PubExt) - return path.Join(s.keyDir, pubName), path.Join(s.keyDir, privName) -} -func writeInfo(path string, info keys.Info) error { - return write(path, info.Name, info.PubKey.Bytes()) + return path.Join(s.keyDir, pubName), path.Join(s.keyDir, privName) } func readInfo(path string) (info keys.Info, err error) { - var data []byte - data, info.Name, err = read(path) + f, err := os.Open(path) + defer f.Close() + if err != nil { - return + return info, errors.Wrap(err, "Reading data") } - pk, err := crypto.PubKeyFromBytes(data) + + d, err := ioutil.ReadAll(f) + if err != nil { + return info, errors.Wrap(err, "Reading data") + } + + block, headers, key, err := crypto.DecodeArmor(string(d)) + if err != nil { + return info, errors.Wrap(err, "Invalid Armor") + } + + if block != BlockType { + return info, errors.Errorf("Unknown key type: %s", block) + } + + pk, _ := crypto.PubKeyFromBytes(key) + info.Name = headers["name"] info.PubKey = pk - return + + return info, nil } -func read(path string) ([]byte, string, error) { +func read(path string) (salt, key []byte, name string, err error) { f, err := os.Open(path) + defer f.Close() + if err != nil { - return nil, "", errors.Wrap(err, "Reading data") + return nil, nil, "", errors.Wrap(err, "Reading data") } + d, err := ioutil.ReadAll(f) if err != nil { - return nil, "", errors.Wrap(err, "Reading data") + return nil, nil, "", errors.Wrap(err, "Reading data") } + block, headers, key, err := crypto.DecodeArmor(string(d)) if err != nil { - return nil, "", errors.Wrap(err, "Invalid Armor") + return nil, nil, "", errors.Wrap(err, "Invalid Armor") } + if block != BlockType { - return nil, "", errors.Errorf("Unknown key type: %s", block) + return nil, nil, "", errors.Errorf("Unknown key type: %s", block) + } + + if headers["kdf"] != "bcrypt" { + return nil, nil, "", errors.Errorf("Unrecognized KDF type: %v", headers["kdf"]) + } + + if headers["salt"] == "" { + return nil, nil, "", errors.Errorf("Missing salt bytes") } - return key, headers["name"], nil + + salt, err = hex.DecodeString(headers["salt"]) + if err != nil { + return nil, nil, "", errors.Errorf("Error decoding salt: %v", err.Error()) + } + + return salt, key, headers["name"], nil } -func write(path, name string, key []byte) error { +func writeInfo(path string, info keys.Info) error { f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) + defer f.Close() + if err != nil { return errors.Wrap(err, "Writing data") } + + headers := map[string]string{"name": info.Name} + text := crypto.EncodeArmor(BlockType, headers, info.PubKey.Bytes()) + _, err = f.WriteString(text) + + return errors.Wrap(err, "Writing data") +} + +func write(path, name string, salt, key []byte) error { + f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) defer f.Close() - headers := map[string]string{"name": name} + + if err != nil { + return errors.Wrap(err, "Writing data") + } + + headers := map[string]string{ + "name": name, + "kdf": "bcrypt", + "salt": fmt.Sprintf("%X", salt), + } + text := crypto.EncodeArmor(BlockType, headers, key) _, err = f.WriteString(text) + return errors.Wrap(err, "Writing data") } diff --git a/keys/storage/filestorage/main_test.go b/keys/storage/filestorage/main_test.go index 28c950c2c..bed46ab1f 100644 --- a/keys/storage/filestorage/main_test.go +++ b/keys/storage/filestorage/main_test.go @@ -22,6 +22,7 @@ func TestBasicCRUD(t *testing.T) { name := "bar" key := []byte("secret-key-here") + salt := []byte("salt-here") pubkey := crypto.GenPrivKeyEd25519().PubKey() info := keys.Info{ Name: name, @@ -29,7 +30,7 @@ func TestBasicCRUD(t *testing.T) { } // No data: Get and Delete return nothing - _, _, err = store.Get(name) + _, _, _, err = store.Get(name) assert.NotNil(err) err = store.Delete(name) assert.NotNil(err) @@ -39,14 +40,14 @@ func TestBasicCRUD(t *testing.T) { assert.Empty(l) // Putting the key in the store must work - err = store.Put(name, key, info) + err = store.Put(name, salt, key, info) assert.Nil(err) // But a second time is a failure - err = store.Put(name, key, info) + err = store.Put(name, salt, key, info) assert.NotNil(err) // Now, we can get and list properly - k, i, err := store.Get(name) + _, k, i, err := store.Get(name) require.Nil(err, "%+v", err) assert.Equal(key, k) assert.Equal(info.Name, i.Name) @@ -58,7 +59,7 @@ func TestBasicCRUD(t *testing.T) { assert.Equal(i, l[0]) // querying a non-existent key fails - _, _, err = store.Get("badname") + _, _, _, err = store.Get("badname") assert.NotNil(err) // We can only delete once @@ -68,7 +69,7 @@ func TestBasicCRUD(t *testing.T) { assert.NotNil(err) // and then Get and List don't work - _, _, err = store.Get(name) + _, _, _, err = store.Get(name) assert.NotNil(err) // List returns empty list l, err = store.List() diff --git a/keys/storage/memstorage/main.go b/keys/storage/memstorage/main.go index 195fa7a17..ddc46afc9 100644 --- a/keys/storage/memstorage/main.go +++ b/keys/storage/memstorage/main.go @@ -7,11 +7,13 @@ package memstorage import ( "github.com/pkg/errors" + keys "github.com/tendermint/go-crypto/keys" ) type data struct { info keys.Info + salt []byte key []byte } @@ -29,22 +31,22 @@ func (s MemStore) assertStorage() keys.Storage { // Put adds the given key, returns an error if it another key // is already stored under this name -func (s MemStore) Put(name string, key []byte, info keys.Info) error { +func (s MemStore) Put(name string, salt, key []byte, info keys.Info) error { if _, ok := s[name]; ok { return errors.Errorf("Key named '%s' already exists", name) } - s[name] = data{info, key} + s[name] = data{info, salt, key} return nil } // Get returns the key stored under the name, or returns an error if not present -func (s MemStore) Get(name string) ([]byte, keys.Info, error) { - var err error +func (s MemStore) Get(name string) (salt, key []byte, info keys.Info, err error) { d, ok := s[name] if !ok { err = errors.Errorf("Key named '%s' doesn't exist", name) } - return d.key, d.info.Format(), err + + return d.salt, d.key, d.info.Format(), err } // List returns the public info of all keys in the MemStore in unsorted order diff --git a/keys/storage/memstorage/main_test.go b/keys/storage/memstorage/main_test.go index feccb387f..01975df58 100644 --- a/keys/storage/memstorage/main_test.go +++ b/keys/storage/memstorage/main_test.go @@ -14,6 +14,7 @@ func TestBasicCRUD(t *testing.T) { name := "foo" key := []byte("secret-key-here") + salt := []byte("salt-here") pubkey := crypto.GenPrivKeyEd25519().PubKey() info := keys.Info{ Name: name, @@ -21,7 +22,7 @@ func TestBasicCRUD(t *testing.T) { } // No data: Get and Delete return nothing - _, _, err := store.Get(name) + _, _, _, err := store.Get(name) assert.NotNil(err) err = store.Delete(name) assert.NotNil(err) @@ -31,14 +32,14 @@ func TestBasicCRUD(t *testing.T) { assert.Empty(l) // Putting the key in the store must work - err = store.Put(name, key, info) + err = store.Put(name, salt, key, info) assert.Nil(err) // But a second time is a failure - err = store.Put(name, key, info) + err = store.Put(name, salt, key, info) assert.NotNil(err) // Now, we can get and list properly - k, i, err := store.Get(name) + _, k, i, err := store.Get(name) assert.Nil(err) assert.Equal(key, k) assert.Equal(info.Name, i.Name) @@ -50,7 +51,7 @@ func TestBasicCRUD(t *testing.T) { assert.Equal(i, l[0]) // querying a non-existent key fails - _, _, err = store.Get("badname") + _, _, _, err = store.Get("badname") assert.NotNil(err) // We can only delete once @@ -60,7 +61,7 @@ func TestBasicCRUD(t *testing.T) { assert.NotNil(err) // and then Get and List don't work - _, _, err = store.Get(name) + _, _, _, err = store.Get(name) assert.NotNil(err) // List returns empty list l, err = store.List() From 47d3fa47419156c3c2f0c6e83d6eb4dfded0eb42 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Mon, 23 Oct 2017 08:30:18 -0400 Subject: [PATCH 129/273] linting: a few fixes --- Makefile | 2 +- embed_test.go | 8 ++++---- keys/cryptostore/holder_test.go | 14 +++++++------- keys/storage/filestorage/main.go | 15 +++++---------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index c7d11ce0a..f775704a9 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,6 @@ metalinter: ensure_tools metalinter_test: ensure_tools @gometalinter --install gometalinter --vendor --deadline=600s --disable-all \ - --enable=aligncheck \ --enable=deadcode \ --enable=gas \ --enable=goconst \ @@ -49,6 +48,7 @@ metalinter_test: ensure_tools --enable=gosimple \ --enable=ineffassign \ --enable=interfacer \ + --enable=maligned \ --enable=megacheck \ --enable=misspell \ --enable=safesql \ diff --git a/embed_test.go b/embed_test.go index e2d2fe504..e5c37c0c1 100644 --- a/embed_test.go +++ b/embed_test.go @@ -73,8 +73,8 @@ func TestEncodeDemo(t *testing.T) { // Try to encode as binary b, err := data.ToWire(tc.in) if assert.Nil(err, "%d: %#v", i, tc.in) { - err := data.FromWire(b, tc.out) - if assert.Nil(err) { + err2 := data.FromWire(b, tc.out) + if assert.Nil(err2) { assert.Equal(tc.expected, tc.out.String()) } } @@ -82,8 +82,8 @@ func TestEncodeDemo(t *testing.T) { // Try to encode it as json j, err := data.ToJSON(tc.in) if assert.Nil(err, "%d: %#v", i, tc.in) { - err := data.FromJSON(j, tc.out) - if assert.Nil(err) { + err2 := data.FromJSON(j, tc.out) + if assert.Nil(err2) { assert.Equal(tc.expected, tc.out.String()) } } diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 7484b1517..a8fc90989 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -50,22 +50,22 @@ func TestKeyManagement(t *testing.T) { assert.NotNil(err) // list shows them in order - keys, err := cstore.List() + keyS, err := cstore.List() require.Nil(err) - require.Equal(2, len(keys)) + require.Equal(2, len(keyS)) // note these are in alphabetical order - assert.Equal(n2, keys[0].Name) - assert.Equal(n1, keys[1].Name) - assert.Equal(i2.PubKey, keys[0].PubKey) + assert.Equal(n2, keyS[0].Name) + assert.Equal(n1, keyS[1].Name) + assert.Equal(i2.PubKey, keyS[0].PubKey) // deleting a key removes it err = cstore.Delete("bad name", "foo") require.NotNil(err) err = cstore.Delete(n1, p1) require.Nil(err) - keys, err = cstore.List() + keyS, err = cstore.List() require.Nil(err) - assert.Equal(1, len(keys)) + assert.Equal(1, len(keyS)) _, err = cstore.Get(n1) assert.NotNil(err) diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go index 70b7e6251..2bd4dcc1f 100644 --- a/keys/storage/filestorage/main.go +++ b/keys/storage/filestorage/main.go @@ -89,11 +89,10 @@ func (s FileStore) Get(name string) (salt []byte, key []byte, info keys.Info, er // Info for all keys located in this directory. func (s FileStore) List() (keys.Infos, error) { dir, err := os.Open(s.keyDir) - defer dir.Close() - if err != nil { return nil, errors.Wrap(err, "List Keys") } + defer dir.Close() names, err := dir.Readdirnames(0) if err != nil { @@ -141,11 +140,10 @@ func (s FileStore) nameToPaths(name string) (pub, priv string) { func readInfo(path string) (info keys.Info, err error) { f, err := os.Open(path) - defer f.Close() - if err != nil { return info, errors.Wrap(err, "Reading data") } + defer f.Close() d, err := ioutil.ReadAll(f) if err != nil { @@ -170,11 +168,10 @@ func readInfo(path string) (info keys.Info, err error) { func read(path string) (salt, key []byte, name string, err error) { f, err := os.Open(path) - defer f.Close() - if err != nil { return nil, nil, "", errors.Wrap(err, "Reading data") } + defer f.Close() d, err := ioutil.ReadAll(f) if err != nil { @@ -208,11 +205,10 @@ func read(path string) (salt, key []byte, name string, err error) { func writeInfo(path string, info keys.Info) error { f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) - defer f.Close() - if err != nil { return errors.Wrap(err, "Writing data") } + defer f.Close() headers := map[string]string{"name": info.Name} text := crypto.EncodeArmor(BlockType, headers, info.PubKey.Bytes()) @@ -223,11 +219,10 @@ func writeInfo(path string, info keys.Info) error { func write(path, name string, salt, key []byte) error { f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) - defer f.Close() - if err != nil { return errors.Wrap(err, "Writing data") } + defer f.Close() headers := map[string]string{ "name": name, From 0781c12ede58390a77f6ea5c7245e120895a6127 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 28 Jul 2017 23:44:16 -0400 Subject: [PATCH 130/273] Message encoding for nano --- nano/sign.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++ nano/sign_test.go | 51 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 nano/sign.go create mode 100644 nano/sign_test.go diff --git a/nano/sign.go b/nano/sign.go new file mode 100644 index 000000000..fbe550548 --- /dev/null +++ b/nano/sign.go @@ -0,0 +1,59 @@ +package nano + +import ( + "bytes" + "fmt" + + "github.com/pkg/errors" +) + +const ( + App = 0x80 + Init = 0x00 + Update = 0x01 + Digest = 0x02 + MaxChunk = 253 + KeyLength = 65 + SigLength = 64 +) + +var separator = []byte{0, 0xCA, 0xFE, 0} + +func generateSignRequests(payload []byte) [][]byte { + // nice one-shot + digest := []byte{App, Digest} + if len(payload) < MaxChunk { + return [][]byte{append(digest, payload...)} + } + + // large payload is multi-chunk + result := [][]byte{{App, Init}} + update := []byte{App, Update} + for len(payload) > MaxChunk { + msg := append(update, payload[:MaxChunk]...) + payload = payload[MaxChunk:] + result = append(result, msg) + } + result = append(result, append(update, payload...)) + result = append(result, digest) + return result +} + +func parseDigest(resp []byte) (key, sig []byte, err error) { + if resp[0] != App || resp[1] != Digest { + return nil, nil, errors.New("Invalid header") + } + resp = resp[2:] + if len(resp) != KeyLength+SigLength+len(separator) { + return nil, nil, errors.Errorf("Incorrect length: %d", len(resp)) + } + + key, resp = resp[:KeyLength], resp[KeyLength:] + if !bytes.Equal(separator, resp[:len(separator)]) { + return nil, nil, errors.New("Cannot find 0xCAFE") + } + fmt.Println("successs") + + sig = resp[len(separator):] + return key, sig, nil +} diff --git a/nano/sign_test.go b/nano/sign_test.go new file mode 100644 index 000000000..8029ef828 --- /dev/null +++ b/nano/sign_test.go @@ -0,0 +1,51 @@ +package nano + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseDigest(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + cases := []struct { + output string + key string + sig string + valid bool + }{ + { + output: "800204338EB1DD3CCDEE1F6FB586F66E640F56FFDD14537A3F0ED9EEEDF10B528FE4195FD17AC9EDAE9718A50196A1459E2434C1E53F1238F4CFDF177FAFBA8B39249B00CAFE00FFDEA42A699205B217004E7E2FFB884E174A548D644116F4B20469CBC32F60A9CB0EEB5BB6A7F266BD0F6A0A99A45B4F18F0F477AED7C854C404EF43530DAB00", + key: "04338EB1DD3CCDEE1F6FB586F66E640F56FFDD14537A3F0ED9EEEDF10B528FE4195FD17AC9EDAE9718A50196A1459E2434C1E53F1238F4CFDF177FAFBA8B39249B", + sig: "FFDEA42A699205B217004E7E2FFB884E174A548D644116F4B20469CBC32F60A9CB0EEB5BB6A7F266BD0F6A0A99A45B4F18F0F477AED7C854C404EF43530DAB00", + valid: true, + }, + { + output: "800235467890876543525437890796574535467890", + key: "", + sig: "", + valid: false, + }, + } + + for i, tc := range cases { + msg, err := hex.DecodeString(tc.output) + require.Nil(err, "%d: %+v", i, err) + + lKey, lSig, err := parseDigest(msg) + if !tc.valid { + assert.NotNil(err, "%d", i) + } else if assert.Nil(err, "%d: %+v", i, err) { + key, err := hex.DecodeString(tc.key) + require.Nil(err, "%d: %+v", i, err) + sig, err := hex.DecodeString(tc.sig) + require.Nil(err, "%d: %+v", i, err) + + assert.Equal(key, lKey, "%d", i) + assert.Equal(sig, lSig, "%d", i) + } + } +} From 8220d591784cfa064e003c4344dc7d1aa138882a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Sat, 29 Jul 2017 13:35:52 -0400 Subject: [PATCH 131/273] Work on using returned bytes as crypto keys --- nano/sign.go | 19 +++++++++++++++++++ nano/sign_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/nano/sign.go b/nano/sign.go index fbe550548..b98b7f469 100644 --- a/nano/sign.go +++ b/nano/sign.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" ) const ( @@ -57,3 +58,21 @@ func parseDigest(resp []byte) (key, sig []byte, err error) { sig = resp[len(separator):] return key, sig, nil } + +func parseKey(data []byte) (key crypto.PubKey, err error) { + ed := crypto.PubKeyEd25519{} + if len(data) < len(ed) { + return key, errors.Errorf("Key length too short: %d", len(data)) + } + copy(ed[:], data) + return ed.Wrap(), nil +} + +func parseSig(data []byte) (key crypto.Signature, err error) { + ed := crypto.SignatureEd25519{} + if len(data) < len(ed) { + return key, errors.Errorf("Sig length too short: %d", len(data)) + } + copy(ed[:], data) + return ed.Wrap(), nil +} diff --git a/nano/sign_test.go b/nano/sign_test.go index 8029ef828..be1e66c86 100644 --- a/nano/sign_test.go +++ b/nano/sign_test.go @@ -49,3 +49,50 @@ func TestParseDigest(t *testing.T) { } } } + +type cryptoCase struct { + msg string + key string + sig string + valid bool +} + +func toBytes(c cryptoCase) (msg, key, sig []byte, err error) { + msg, err = hex.DecodeString(c.msg) + if err != nil { + return + } + key, err = hex.DecodeString(c.key) + if err != nil { + return + } + sig, err = hex.DecodeString(c.sig) + return +} + +func TestCryptoConvert(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + cases := []cryptoCase{ + { + msg: "00", + key: "04338EB1DD3CCDEE1F6FB586F66E640F56FFDD14537A3F0ED9EEEDF10B528FE4195FD17AC9EDAE9718A50196A1459E2434C1E53F1238F4CFDF177FAFBA8B39249B", + sig: "FFDEA42A699205B217004E7E2FFB884E174A548D644116F4B20469CBC32F60A9CB0EEB5BB6A7F266BD0F6A0A99A45B4F18F0F477AED7C854C404EF43530DAB00", + valid: true, + }, + } + + for i, tc := range cases { + msg, key, sig, err := toBytes(tc) + require.Nil(err, "%d: %+v", i, err) + + pk, err := parseKey(key) + require.Nil(err, "%d: %+v", i, err) + psig, err := parseSig(sig) + require.Nil(err, "%d: %+v", i, err) + + // how do i make this valid? + valid := pk.VerifyBytes(msg, psig) + assert.Equal(tc.valid, valid, "%d", i) + } +} From 74878ee3130cff56dcd096a69ed7a3b97e7d233f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 12 Sep 2017 09:50:07 +0200 Subject: [PATCH 132/273] Update code to work with current nano implementation --- nano/sign.go | 9 ++++++++- nano/sign_test.go | 19 ++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/nano/sign.go b/nano/sign.go index b98b7f469..50b874d15 100644 --- a/nano/sign.go +++ b/nano/sign.go @@ -2,9 +2,11 @@ package nano import ( "bytes" + "crypto/sha512" "fmt" "github.com/pkg/errors" + crypto "github.com/tendermint/go-crypto" ) @@ -14,7 +16,7 @@ const ( Update = 0x01 Digest = 0x02 MaxChunk = 253 - KeyLength = 65 + KeyLength = 32 SigLength = 64 ) @@ -76,3 +78,8 @@ func parseSig(data []byte) (key crypto.Signature, err error) { copy(ed[:], data) return ed.Wrap(), nil } + +func hashMsg(data []byte) []byte { + res := sha512.Sum512(data) + return res[:] +} diff --git a/nano/sign_test.go b/nano/sign_test.go index be1e66c86..2f94c5e6f 100644 --- a/nano/sign_test.go +++ b/nano/sign_test.go @@ -18,9 +18,9 @@ func TestParseDigest(t *testing.T) { valid bool }{ { - output: "800204338EB1DD3CCDEE1F6FB586F66E640F56FFDD14537A3F0ED9EEEDF10B528FE4195FD17AC9EDAE9718A50196A1459E2434C1E53F1238F4CFDF177FAFBA8B39249B00CAFE00FFDEA42A699205B217004E7E2FFB884E174A548D644116F4B20469CBC32F60A9CB0EEB5BB6A7F266BD0F6A0A99A45B4F18F0F477AED7C854C404EF43530DAB00", - key: "04338EB1DD3CCDEE1F6FB586F66E640F56FFDD14537A3F0ED9EEEDF10B528FE4195FD17AC9EDAE9718A50196A1459E2434C1E53F1238F4CFDF177FAFBA8B39249B", - sig: "FFDEA42A699205B217004E7E2FFB884E174A548D644116F4B20469CBC32F60A9CB0EEB5BB6A7F266BD0F6A0A99A45B4F18F0F477AED7C854C404EF43530DAB00", + output: "80028E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C9300CAFE00787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", + key: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", + sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", valid: true, }, { @@ -75,9 +75,9 @@ func TestCryptoConvert(t *testing.T) { cases := []cryptoCase{ { - msg: "00", - key: "04338EB1DD3CCDEE1F6FB586F66E640F56FFDD14537A3F0ED9EEEDF10B528FE4195FD17AC9EDAE9718A50196A1459E2434C1E53F1238F4CFDF177FAFBA8B39249B", - sig: "FFDEA42A699205B217004E7E2FFB884E174A548D644116F4B20469CBC32F60A9CB0EEB5BB6A7F266BD0F6A0A99A45B4F18F0F477AED7C854C404EF43530DAB00", + msg: "F00D", + key: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", + sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", valid: true, }, } @@ -91,8 +91,13 @@ func TestCryptoConvert(t *testing.T) { psig, err := parseSig(sig) require.Nil(err, "%d: %+v", i, err) - // how do i make this valid? + // it is not the signature of the message itself valid := pk.VerifyBytes(msg, psig) + assert.NotEqual(tc.valid, valid, "%d", i) + + // but rather of the hash of the msg + hmsg := hashMsg(msg) + valid = pk.VerifyBytes(hmsg, psig) assert.Equal(tc.valid, valid, "%d", i) } } From 06d74b24dd3fc80ff7b63b5dca2afe89142a5558 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 12 Sep 2017 10:37:01 +0200 Subject: [PATCH 133/273] Wrote PrivKey/PubKey for ledger --- nano/keys.go | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 nano/keys.go diff --git a/nano/keys.go b/nano/keys.go new file mode 100644 index 000000000..7b76fa87f --- /dev/null +++ b/nano/keys.go @@ -0,0 +1,150 @@ +package nano + +import ( + "bytes" + "encoding/hex" + + crypto "github.com/tendermint/go-crypto" +) + +// // Implements PrivKey, calling the ledger nano +// type PrivKeyLedger struct{} + +// var _ PrivKeyInner = PrivKeyLedger{} + +// func (privKey PrivKeyLedger) AssertIsPrivKeyInner() {} + +// func (privKey PrivKeyLedger) Bytes() []byte { +// return wire.BinaryBytes(PrivKey{privKey}) +// } + +// func (privKey PrivKeyLedger) Sign(msg []byte) Signature { +// privKeyBytes := [64]byte(privKey) +// signatureBytes := ed25519.Sign(&privKeyBytes, msg) +// return SignatureEd25519(*signatureBytes).Wrap() +// } + +// func (privKey PrivKeyLedger) PubKey() PubKey { +// privKeyBytes := [64]byte(privKey) +// pubBytes := *ed25519.MakePublicKey(&privKeyBytes) +// return PubKeyEd25519(pubBytes).Wrap() +// } + +// func (privKey PrivKeyLedger) Equals(other PrivKey) bool { +// if otherEd, ok := other.Unwrap().(PrivKeyLedger); ok { +// return bytes.Equal(privKey[:], otherEd[:]) +// } else { +// return false +// } +// } + +// MockPrivKeyLedger behaves as the ledger, but stores a pre-packaged call-response +// for use in test cases +type MockPrivKeyLedger struct { + Msg []byte + Pub [KeyLength]byte + Sig [SigLength]byte +} + +// NewMockKey returns +func NewMockKey(msg, pubkey, sig string) (pk MockPrivKeyLedger) { + var err error + pk.Msg, err = hex.DecodeString(msg) + if err != nil { + panic(err) + } + + bpk, err := hex.DecodeString(pubkey) + if err != nil { + panic(err) + } + bsig, err := hex.DecodeString(sig) + if err != nil { + panic(err) + } + + copy(pk.Pub[:], bpk) + copy(pk.Sig[:], bsig) + return pk +} + +var _ crypto.PrivKeyInner = MockPrivKeyLedger{} + +// AssertIsPrivKeyInner fulfils PrivKey Interface +func (pk MockPrivKeyLedger) AssertIsPrivKeyInner() {} + +// Bytes fulfils PrivKey Interface - not supported +func (pk MockPrivKeyLedger) Bytes() []byte { + return nil +} + +// Sign returns a real SignatureLedger, if the msg matches what we expect +func (pk MockPrivKeyLedger) Sign(msg []byte) crypto.Signature { + if !bytes.Equal(pk.Msg, msg) { + panic("Mock key is for different msg") + } + return crypto.SignatureEd25519(pk.Sig).Wrap() +} + +// PubKey returns a real PubKeyLedger, that will verify this signature +func (pk MockPrivKeyLedger) PubKey() crypto.PubKey { + return PubKeyLedger{crypto.PubKeyEd25519(pk.Pub)}.Wrap() +} + +// Equals compares that two Mocks have the same data +func (pk MockPrivKeyLedger) Equals(other crypto.PrivKey) bool { + if mock, ok := other.Unwrap().(MockPrivKeyLedger); ok { + return bytes.Equal(mock.Pub[:], pk.Pub[:]) && + bytes.Equal(mock.Sig[:], pk.Sig[:]) && + bytes.Equal(mock.Msg, pk.Msg) + } + return false +} + +//////////////////////////////////////////// +// pubkey + +// PubKeyLedger works like a normal Ed25519 except a hash before the verify bytes +type PubKeyLedger struct { + crypto.PubKeyEd25519 +} + +// VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand +func (pk PubKeyLedger) VerifyBytes(msg []byte, sig crypto.Signature) bool { + hmsg := hashMsg(msg) + return pk.PubKeyEd25519.VerifyBytes(hmsg, sig) +} + +// Equals implements PubKey interface +func (pk PubKeyLedger) Equals(other crypto.PubKey) bool { + if ledger, ok := other.Unwrap().(PubKeyLedger); ok { + return bytes.Equal(pk.PubKeyEd25519[:], ledger.PubKeyEd25519[:]) + } + return false +} + +/*** registration with go-data ***/ + +func init() { + crypto.PrivKeyMapper. + // RegisterImplementation(PrivKeyLedger{}, "ledger", 0x10). + RegisterImplementation(MockPrivKeyLedger{}, "mock-ledger", 0x11) + + crypto.PubKeyMapper. + RegisterImplementation(PubKeyLedger{}, "ledger", 0x10) +} + +// // Wrap fulfils interface for PrivKey struct +// func (hi PrivKeyLedger) Wrap() crypto.PrivKey { +// return PrivKey{hi} +// } + +// Wrap fulfils interface for PrivKey struct +func (pk MockPrivKeyLedger) Wrap() crypto.PrivKey { + return crypto.PrivKey{pk} +} + +// Wrap fulfils interface for PubKey struct +func (pk PubKeyLedger) Wrap() crypto.PubKey { + return crypto.PubKey{pk} +} From 7c5a10a7d49f2e908237644c496e90fa4fd2eb1d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 12 Sep 2017 10:42:12 +0200 Subject: [PATCH 134/273] Add tests for pub/priv key validation --- nano/keys_test.go | 38 ++++++++++++++++++++++++++++++++++++++ nano/sign.go | 2 +- nano/sign_test.go | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 nano/keys_test.go diff --git a/nano/keys_test.go b/nano/keys_test.go new file mode 100644 index 000000000..32a0d444b --- /dev/null +++ b/nano/keys_test.go @@ -0,0 +1,38 @@ +package nano + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestLedgerKeys(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + // cryptoCase from sign_test + cases := []struct { + msg, pubkey, sig string + valid bool + }{ + { + msg: "F00D", + pubkey: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", + sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", + valid: true, + }, + } + + for i, tc := range cases { + bmsg, err := hex.DecodeString(tc.msg) + require.NoError(err, "%d", i) + + priv := NewMockKey(tc.msg, tc.pubkey, tc.sig) + pub := priv.PubKey() + sig := priv.Sign(bmsg) + + valid := pub.VerifyBytes(bmsg, sig) + assert.Equal(tc.valid, valid, "%d", i) + } +} diff --git a/nano/sign.go b/nano/sign.go index 50b874d15..3f0df9ee5 100644 --- a/nano/sign.go +++ b/nano/sign.go @@ -61,7 +61,7 @@ func parseDigest(resp []byte) (key, sig []byte, err error) { return key, sig, nil } -func parseKey(data []byte) (key crypto.PubKey, err error) { +func parseEdKey(data []byte) (key crypto.PubKey, err error) { ed := crypto.PubKeyEd25519{} if len(data) < len(ed) { return key, errors.Errorf("Key length too short: %d", len(data)) diff --git a/nano/sign_test.go b/nano/sign_test.go index 2f94c5e6f..2521514eb 100644 --- a/nano/sign_test.go +++ b/nano/sign_test.go @@ -86,7 +86,7 @@ func TestCryptoConvert(t *testing.T) { msg, key, sig, err := toBytes(tc) require.Nil(err, "%d: %+v", i, err) - pk, err := parseKey(key) + pk, err := parseEdKey(key) require.Nil(err, "%d: %+v", i, err) psig, err := parseSig(sig) require.Nil(err, "%d: %+v", i, err) From 265e261c6352e5b72d372e4bb8ed4eaff1fa2b09 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 12 Sep 2017 10:47:16 +0200 Subject: [PATCH 135/273] Add more test cases from running the ledger --- nano/keys_test.go | 39 +++++++++++++++++++++++++++++++++++++-- nano/sign_test.go | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/nano/keys_test.go b/nano/keys_test.go index 32a0d444b..b46e4c9ff 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -11,17 +11,52 @@ import ( func TestLedgerKeys(t *testing.T) { assert, require := assert.New(t), require.New(t) - // cryptoCase from sign_test cases := []struct { msg, pubkey, sig string valid bool }{ - { + 0: { msg: "F00D", pubkey: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", valid: true, }, + 1: { + msg: "DEADBEEF", + pubkey: "0C45ADC887A5463F668533443C829ED13EA8E2E890C778957DC28DB9D2AD5A6C", + sig: "00ED74EED8FDAC7988A14BF6BC222120CBAC249D569AF4C2ADABFC86B792F97DF73C4919BE4B6B0ACB53547273BF29FBF0A9E0992FFAB6CB6C9B09311FC86A00", + valid: true, + }, + 2: { + msg: "1234567890AA", + pubkey: "598FC1F0C76363D14D7480736DEEF390D85863360F075792A6975EFA149FD7EA", + sig: "59AAB7D7BDC4F936B6415DE672A8B77FA6B8B3451CD95B3A631F31F9A05DAEEE5E7E4F89B64DDEBB5F63DC042CA13B8FCB8185F82AD7FD5636FFDA6B0DC9570B", + valid: true, + }, + 3: { + msg: "1234432112344321", + pubkey: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", + sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", + valid: true, + }, + 4: { + msg: "12344321123443", + pubkey: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", + sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", + valid: false, + }, + 5: { + msg: "1234432112344321", + pubkey: "459E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", + sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", + valid: false, + }, + 6: { + msg: "1234432112344321", + pubkey: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", + sig: "716B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", + valid: false, + }, } for i, tc := range cases { diff --git a/nano/sign_test.go b/nano/sign_test.go index 2521514eb..89bd7568e 100644 --- a/nano/sign_test.go +++ b/nano/sign_test.go @@ -74,12 +74,48 @@ func TestCryptoConvert(t *testing.T) { assert, require := assert.New(t), require.New(t) cases := []cryptoCase{ - { + 0: { msg: "F00D", key: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", valid: true, }, + 1: { + msg: "DEADBEEF", + key: "0C45ADC887A5463F668533443C829ED13EA8E2E890C778957DC28DB9D2AD5A6C", + sig: "00ED74EED8FDAC7988A14BF6BC222120CBAC249D569AF4C2ADABFC86B792F97DF73C4919BE4B6B0ACB53547273BF29FBF0A9E0992FFAB6CB6C9B09311FC86A00", + valid: true, + }, + 2: { + msg: "1234567890AA", + key: "598FC1F0C76363D14D7480736DEEF390D85863360F075792A6975EFA149FD7EA", + sig: "59AAB7D7BDC4F936B6415DE672A8B77FA6B8B3451CD95B3A631F31F9A05DAEEE5E7E4F89B64DDEBB5F63DC042CA13B8FCB8185F82AD7FD5636FFDA6B0DC9570B", + valid: true, + }, + 3: { + msg: "1234432112344321", + key: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", + sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", + valid: true, + }, + 4: { + msg: "12344321123443", + key: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", + sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", + valid: false, + }, + 5: { + msg: "1234432112344321", + key: "459E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", + sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", + valid: false, + }, + 6: { + msg: "1234432112344321", + key: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", + sig: "716B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", + valid: false, + }, } for i, tc := range cases { @@ -93,7 +129,7 @@ func TestCryptoConvert(t *testing.T) { // it is not the signature of the message itself valid := pk.VerifyBytes(msg, psig) - assert.NotEqual(tc.valid, valid, "%d", i) + assert.False(valid, "%d", i) // but rather of the hash of the msg hmsg := hashMsg(msg) From 623bd803c283d742f28f7ae46058b9b105628fbf Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 12 Sep 2017 11:40:30 +0200 Subject: [PATCH 136/273] write code to actually call ledger app --- nano/keys.go | 117 ++++++++++++++++++++++++++++++++++------------ nano/keys_test.go | 8 ++++ signature.go | 6 +++ 3 files changed, 101 insertions(+), 30 deletions(-) diff --git a/nano/keys.go b/nano/keys.go index 7b76fa87f..cd5c90317 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -4,39 +4,91 @@ import ( "bytes" "encoding/hex" + ledger "github.com/ethanfrey/ledger" + crypto "github.com/tendermint/go-crypto" ) -// // Implements PrivKey, calling the ledger nano -// type PrivKeyLedger struct{} +var device *ledger.Ledger + +// getLedger gets a copy of the device, and caches it +func getLedger() (*ledger.Ledger, error) { + var err error + if device == nil { + device, err = ledger.FindLedger() + } + return device, err +} + +func signLedger(device *ledger.Ledger, msg []byte) (pk crypto.PubKey, sig crypto.Signature, err error) { + var resp []byte + + packets := generateSignRequests(msg) + for _, pack := range packets { + resp, err = device.Exchange(pack, 100) + if err != nil { + return pk, sig, err + } + } + + // the last call is the result we want and needs to be parsed + key, bsig, err := parseDigest(resp) + if err != nil { + return pk, sig, err + } + + var b [32]byte + copy(b[:], key) + return PubKeyLedgerFromBytes(b), crypto.SignatureEd25519FromBytes(bsig), nil +} + +// PrivKeyLedger implements PrivKey, calling the ledger nano +// we cache the PubKey from the first call to use it later +type PrivKeyLedger struct { + pubKey crypto.PubKey +} + +var _ crypto.PrivKeyInner = &PrivKeyLedger{} + +// AssertIsPrivKeyInner fulfils PrivKey Interface +func (pk *PrivKeyLedger) AssertIsPrivKeyInner() {} -// var _ PrivKeyInner = PrivKeyLedger{} +// Bytes fulfils pk Interface - not supported +func (pk *PrivKeyLedger) Bytes() []byte { + return nil +} -// func (privKey PrivKeyLedger) AssertIsPrivKeyInner() {} +// Sign calls the ledger and stores the pk for future use +func (pk *PrivKeyLedger) Sign(msg []byte) crypto.Signature { + // oh, I wish there was better error handling + dev, err := getLedger() + if err != nil { + panic(err) + } -// func (privKey PrivKeyLedger) Bytes() []byte { -// return wire.BinaryBytes(PrivKey{privKey}) -// } + pub, sig, err := signLedger(dev, msg) + if err != nil { + panic(err) + } -// func (privKey PrivKeyLedger) Sign(msg []byte) Signature { -// privKeyBytes := [64]byte(privKey) -// signatureBytes := ed25519.Sign(&privKeyBytes, msg) -// return SignatureEd25519(*signatureBytes).Wrap() -// } + pk.pubKey = pub + return sig +} -// func (privKey PrivKeyLedger) PubKey() PubKey { -// privKeyBytes := [64]byte(privKey) -// pubBytes := *ed25519.MakePublicKey(&privKeyBytes) -// return PubKeyEd25519(pubBytes).Wrap() -// } +// PubKey returns the stored PubKey +// TODO: query the ledger if not there, once it is not volatile +func (pk *PrivKeyLedger) PubKey() crypto.PubKey { + return pk.pubKey +} -// func (privKey PrivKeyLedger) Equals(other PrivKey) bool { -// if otherEd, ok := other.Unwrap().(PrivKeyLedger); ok { -// return bytes.Equal(privKey[:], otherEd[:]) -// } else { -// return false -// } -// } +// Equals fulfils PrivKey Interface +// TODO: needs to be fixed +func (pk *PrivKeyLedger) Equals(other crypto.PrivKey) bool { + if _, ok := other.Unwrap().(*PrivKeyLedger); ok { + return true + } + return false +} // MockPrivKeyLedger behaves as the ledger, but stores a pre-packaged call-response // for use in test cases @@ -88,7 +140,7 @@ func (pk MockPrivKeyLedger) Sign(msg []byte) crypto.Signature { // PubKey returns a real PubKeyLedger, that will verify this signature func (pk MockPrivKeyLedger) PubKey() crypto.PubKey { - return PubKeyLedger{crypto.PubKeyEd25519(pk.Pub)}.Wrap() + return PubKeyLedgerFromBytes(pk.Pub) } // Equals compares that two Mocks have the same data @@ -109,6 +161,11 @@ type PubKeyLedger struct { crypto.PubKeyEd25519 } +// PubKeyLedgerFromBytes creates a PubKey from the raw bytes +func PubKeyLedgerFromBytes(key [32]byte) crypto.PubKey { + return PubKeyLedger{crypto.PubKeyEd25519(key)}.Wrap() +} + // VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand func (pk PubKeyLedger) VerifyBytes(msg []byte, sig crypto.Signature) bool { hmsg := hashMsg(msg) @@ -127,17 +184,17 @@ func (pk PubKeyLedger) Equals(other crypto.PubKey) bool { func init() { crypto.PrivKeyMapper. - // RegisterImplementation(PrivKeyLedger{}, "ledger", 0x10). + RegisterImplementation(&PrivKeyLedger{}, "ledger", 0x10). RegisterImplementation(MockPrivKeyLedger{}, "mock-ledger", 0x11) crypto.PubKeyMapper. RegisterImplementation(PubKeyLedger{}, "ledger", 0x10) } -// // Wrap fulfils interface for PrivKey struct -// func (hi PrivKeyLedger) Wrap() crypto.PrivKey { -// return PrivKey{hi} -// } +// Wrap fulfils interface for PrivKey struct +func (pk *PrivKeyLedger) Wrap() crypto.PrivKey { + return crypto.PrivKey{pk} +} // Wrap fulfils interface for PrivKey struct func (pk MockPrivKeyLedger) Wrap() crypto.PrivKey { diff --git a/nano/keys_test.go b/nano/keys_test.go index b46e4c9ff..5ceae2afa 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -2,6 +2,7 @@ package nano import ( "encoding/hex" + "os" "testing" "github.com/stretchr/testify/assert" @@ -71,3 +72,10 @@ func TestLedgerKeys(t *testing.T) { assert.Equal(tc.valid, valid, "%d", i) } } + +func TestRealLedger(t *testing.T) { + if os.Getenv("WITH_LEDGER") == "" { + t.Skip("Set WITH_LEDGER to run code on real ledger") + } + // let's try for real.... +} diff --git a/signature.go b/signature.go index 5b1d6cb05..d2ea45132 100644 --- a/signature.go +++ b/signature.go @@ -63,6 +63,12 @@ func (sig *SignatureEd25519) UnmarshalJSON(enc []byte) error { return err } +func SignatureEd25519FromBytes(data []byte) Signature { + var sig SignatureEd25519 + copy(sig[:], data) + return sig.Wrap() +} + //------------------------------------- var _ SignatureInner = SignatureSecp256k1{} From 008dba3af821bacf599da3c282f387fb9394119d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 12 Sep 2017 11:48:43 +0200 Subject: [PATCH 137/273] Test ledger calls --- nano/keys.go | 5 ++++- nano/keys_test.go | 10 +++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/nano/keys.go b/nano/keys.go index cd5c90317..55af915cb 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -48,7 +48,10 @@ type PrivKeyLedger struct { pubKey crypto.PubKey } -var _ crypto.PrivKeyInner = &PrivKeyLedger{} +func NewPrivKeyLedger() crypto.PrivKey { + var pk PrivKeyLedger + return pk.Wrap() +} // AssertIsPrivKeyInner fulfils PrivKey Interface func (pk *PrivKeyLedger) AssertIsPrivKeyInner() {} diff --git a/nano/keys_test.go b/nano/keys_test.go index 5ceae2afa..3f2eb9a1f 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -77,5 +77,13 @@ func TestRealLedger(t *testing.T) { if os.Getenv("WITH_LEDGER") == "" { t.Skip("Set WITH_LEDGER to run code on real ledger") } - // let's try for real.... + + priv := NewPrivKeyLedger() + msg := []byte("kuhehfeohg") + + sig := priv.Sign(msg) + pub := priv.PubKey() + + valid := pub.VerifyBytes(msg, sig) + assert.True(t, valid) } From 081f21af119b8d748c42c049e2b81815c93ae323 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 12 Sep 2017 12:57:30 +0200 Subject: [PATCH 138/273] Add glide version for ledger drivers --- glide.lock | 30 ++++++++++++++---------------- glide.yaml | 1 + 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/glide.lock b/glide.lock index 1c23d8bea..29124c3db 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: c0a2db1b80c6b1b8aab31c526ce43e22e49b23c893c78b8fdb8546aa2e7b7cc6 -updated: 2017-09-22T10:21:34.220901552-04:00 +hash: a2243bfd21937edf660778300855e7cb72185164641cb278dbf0c220e8a0f60a +updated: 2017-10-23T17:21:02.40831023+02:00 imports: - name: github.com/bgentry/speakeasy version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd @@ -11,16 +11,16 @@ imports: - chaincfg/chainhash - wire - name: github.com/btcsuite/btcutil - version: 86346b5a958c0cf94186b87855469ae991be501c + version: 66871daeb12123ece012a9628d2798d01195c4b3 subpackages: - base58 - hdkeychain - name: github.com/btcsuite/fastsha256 version: 637e656429416087660c84436a2a035d69d54e2e -- name: github.com/btcsuite/golangcrypto - version: 53f62d9b43e87a6c56975cf862af7edf33a8d0df - subpackages: - - ripemd160 +- name: github.com/ethanfrey/ledger + version: 5e432577be582bd18a3b4a9cd75dae7a317ade36 +- name: github.com/flynn/hid + version: ed06a31c6245d4552e8dbba7e32e5b010b875d65 - name: github.com/go-kit/kit version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 subpackages: @@ -44,7 +44,7 @@ imports: - name: github.com/gorilla/mux version: bcd8bc72b08df0f70df986b97f95590779502d31 - name: github.com/howeyc/crc16 - version: 96a97a1abb579c7ff1a8ffa77f2e72d1c314b57f + version: 58da63c846043d0bea709c8d47039df06577d6d9 - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors @@ -59,12 +59,12 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 5f88da3dbc1a72844e6dfaf274ce87f851d488eb + version: 55ae61f1fc83cfaa57ab7d54250d7a1a2be0b83c subpackages: - data - data/base58 - name: github.com/tendermint/tmlibs - version: bffe6744ec277d60f707ab442e25513617842f8e + version: 8e5266a9ef2527e68a1571f932db8228a331b556 subpackages: - common - log @@ -81,16 +81,14 @@ imports: - ripemd160 - salsa20/salsa - name: gopkg.in/go-playground/validator.v9 - version: d529ee1b0f30352444f507cc6cdac96bfd12decc + version: 6d8c18553ea1ac493d049edd6f102f52e618f085 testImports: +- name: github.com/cmars/basen + version: fe3947df716ebfda9847eb1b9a48f9592e06478c - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew -- name: github.com/FactomProject/basen - version: fe3947df716ebfda9847eb1b9a48f9592e06478c -- name: github.com/FactomProject/btcutilecc - version: d3a63a5752ecf3fbc06bd97365da752111c263df - name: github.com/mndrix/btcutil version: d3a63a5752ecf3fbc06bd97365da752111c263df - name: github.com/pmezard/go-difflib @@ -103,6 +101,6 @@ testImports: - assert - require - name: github.com/tyler-smith/go-bip32 - version: 2c9cfd17756470a0b7c3e4b7954bae7d11035504 + version: eb790af526c30f23a7c8b00a48e342f9d0bd6386 - name: github.com/tyler-smith/go-bip39 version: 8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc diff --git a/glide.yaml b/glide.yaml index a99d3b63f..9f20ddefc 100644 --- a/glide.yaml +++ b/glide.yaml @@ -30,6 +30,7 @@ import: - package: github.com/spf13/viper - package: gopkg.in/go-playground/validator.v9 - package: github.com/howeyc/crc16 +- package: github.com/ethanfrey/ledger testImport: - package: github.com/mndrix/btcutil - package: github.com/stretchr/testify From 3edeb0cd45a9a8a97dbafb901894a51c8f8af688 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Sep 2017 11:53:14 +0200 Subject: [PATCH 139/273] Ledger caches pubkey, works with newer firmware --- nano/keys.go | 39 +++++++++++++++++++++++++++++++++++---- nano/keys_test.go | 10 ++++++---- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/nano/keys.go b/nano/keys.go index 55af915cb..7cac5eee8 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -4,6 +4,8 @@ import ( "bytes" "encoding/hex" + "github.com/pkg/errors" + ledger "github.com/ethanfrey/ledger" crypto "github.com/tendermint/go-crypto" @@ -48,9 +50,13 @@ type PrivKeyLedger struct { pubKey crypto.PubKey } -func NewPrivKeyLedger() crypto.PrivKey { +func NewPrivKeyLedger() (crypto.PrivKey, error) { var pk PrivKeyLedger - return pk.Wrap() + // getPubKey will cache the pubkey for later use, + // this allows us to return an error early if the ledger + // is not plugged in + _, err := pk.getPubKey() + return pk.Wrap(), err } // AssertIsPrivKeyInner fulfils PrivKey Interface @@ -74,14 +80,39 @@ func (pk *PrivKeyLedger) Sign(msg []byte) crypto.Signature { panic(err) } - pk.pubKey = pub + // if we have no pubkey yet, store it for future queries + if pk.pubKey.Empty() { + pk.pubKey = pub + } return sig } // PubKey returns the stored PubKey // TODO: query the ledger if not there, once it is not volatile func (pk *PrivKeyLedger) PubKey() crypto.PubKey { - return pk.pubKey + key, err := pk.getPubKey() + if err != nil { + panic(err) + } + return key +} + +// getPubKey reads the pubkey from cache or from the ledger itself +// since this involves IO, it may return an error, which is not exposed +// in the PubKey interface, so this function allows better error handling +func (pk *PrivKeyLedger) getPubKey() (key crypto.PubKey, err error) { + // if we have no pubkey, set it + if pk.pubKey.Empty() { + dev, err := getLedger() + if err != nil { + return key, errors.WithMessage(err, "Can't connect to ledger") + } + pk.pubKey, _, err = signLedger(dev, []byte{0}) + if err != nil { + return key, errors.WithMessage(err, "Can't sign with app") + } + } + return pk.pubKey, nil } // Equals fulfils PrivKey Interface diff --git a/nano/keys_test.go b/nano/keys_test.go index 3f2eb9a1f..3a4d9c1eb 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -74,16 +74,18 @@ func TestLedgerKeys(t *testing.T) { } func TestRealLedger(t *testing.T) { + assert, require := assert.New(t), require.New(t) + if os.Getenv("WITH_LEDGER") == "" { t.Skip("Set WITH_LEDGER to run code on real ledger") } - - priv := NewPrivKeyLedger() msg := []byte("kuhehfeohg") - sig := priv.Sign(msg) + priv, err := NewPrivKeyLedger() + require.Nil(err, "%+v", err) pub := priv.PubKey() + sig := priv.Sign(msg) valid := pub.VerifyBytes(msg, sig) - assert.True(t, valid) + assert.True(valid) } From 0383feab494f1a8a3d4d1327890375fa123f3f07 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Sep 2017 11:59:17 +0200 Subject: [PATCH 140/273] Add and test serialization of ledger privkey --- nano/keys.go | 5 +++-- nano/keys_test.go | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/nano/keys.go b/nano/keys.go index 7cac5eee8..6b337e8b7 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -9,6 +9,7 @@ import ( ledger "github.com/ethanfrey/ledger" crypto "github.com/tendermint/go-crypto" + wire "github.com/tendermint/go-wire" ) var device *ledger.Ledger @@ -62,9 +63,9 @@ func NewPrivKeyLedger() (crypto.PrivKey, error) { // AssertIsPrivKeyInner fulfils PrivKey Interface func (pk *PrivKeyLedger) AssertIsPrivKeyInner() {} -// Bytes fulfils pk Interface - not supported +// Bytes fulfils pk Interface - no data, just type info func (pk *PrivKeyLedger) Bytes() []byte { - return nil + return wire.BinaryBytes(pk.Wrap()) } // Sign calls the ledger and stores the pk for future use diff --git a/nano/keys_test.go b/nano/keys_test.go index 3a4d9c1eb..b42b091f0 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" ) func TestLedgerKeys(t *testing.T) { @@ -88,4 +89,19 @@ func TestRealLedger(t *testing.T) { valid := pub.VerifyBytes(msg, sig) assert.True(valid) + + // now, let's serialize the key and make sure it still works + bs := priv.Bytes() + priv2, err := crypto.PrivKeyFromBytes(bs) + require.Nil(err, "%+v", err) + + // make sure we get the same pubkey when we load from disk + pub2 := priv2.PubKey() + require.Equal(pub, pub2) + + // signing with the loaded key should match the original pubkey + sig = priv2.Sign(msg) + valid = pub.VerifyBytes(msg, sig) + assert.True(valid) + } From 8c98c4fdf46aafc3b9d8690902ad38b8835a636a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Sep 2017 12:41:54 +0200 Subject: [PATCH 141/273] Add nano ledger to key manager --- keys/cryptostore/generator.go | 18 ++++++++++++++++++ nano/keys.go | 24 ++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index 1f162ec08..c1984fc82 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -4,6 +4,7 @@ import ( "github.com/pkg/errors" crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto/nano" ) var ( @@ -11,6 +12,8 @@ var ( GenEd25519 Generator = GenFunc(genEd25519) // GenSecp256k1 produces Secp256k1 private keys GenSecp256k1 Generator = GenFunc(genSecp256) + // GenLedger used Ed25519 keys stored on nano ledger s with cosmos app + GenLedger Generator = GenFunc(genLedger) ) // Generator determines the type of private key the keystore creates @@ -33,12 +36,25 @@ func genSecp256(secret []byte) crypto.PrivKey { return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap() } +// secret is completely ignored for the ledger... +// just for interface compatibility +func genLedger(secret []byte) crypto.PrivKey { + key, err := nano.NewPrivKeyLedger() + if err != nil { + // TODO: cleaner error handling + panic(err) + } + return key +} + func getGenerator(algo string) (Generator, error) { switch algo { case crypto.NameEd25519: return GenEd25519, nil case crypto.NameSecp256k1: return GenSecp256k1, nil + case nano.NameLedger: + return GenLedger, nil default: return nil, errors.Errorf("Cannot generate keys for algorithm: %s", algo) } @@ -50,6 +66,8 @@ func getGeneratorByType(typ byte) (Generator, error) { return GenEd25519, nil case crypto.TypeSecp256k1: return GenSecp256k1, nil + case nano.TypeLedger: + return GenLedger, nil default: return nil, errors.Errorf("Cannot generate keys for algorithm: %X", typ) } diff --git a/nano/keys.go b/nano/keys.go index 6b337e8b7..2ab4d59a8 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -12,6 +12,11 @@ import ( wire "github.com/tendermint/go-wire" ) +const ( + NameLedger = "ledger" + TypeLedger = 0x10 +) + var device *ledger.Ledger // getLedger gets a copy of the device, and caches it @@ -48,7 +53,10 @@ func signLedger(device *ledger.Ledger, msg []byte) (pk crypto.PubKey, sig crypto // PrivKeyLedger implements PrivKey, calling the ledger nano // we cache the PubKey from the first call to use it later type PrivKeyLedger struct { - pubKey crypto.PubKey + // PubKey should be private, but we want to encode it via go-wire + // so we can view the address later, even without having the ledger + // attached + CachedPubKey crypto.PubKey } func NewPrivKeyLedger() (crypto.PrivKey, error) { @@ -82,8 +90,8 @@ func (pk *PrivKeyLedger) Sign(msg []byte) crypto.Signature { } // if we have no pubkey yet, store it for future queries - if pk.pubKey.Empty() { - pk.pubKey = pub + if pk.CachedPubKey.Empty() { + pk.CachedPubKey = pub } return sig } @@ -103,17 +111,17 @@ func (pk *PrivKeyLedger) PubKey() crypto.PubKey { // in the PubKey interface, so this function allows better error handling func (pk *PrivKeyLedger) getPubKey() (key crypto.PubKey, err error) { // if we have no pubkey, set it - if pk.pubKey.Empty() { + if pk.CachedPubKey.Empty() { dev, err := getLedger() if err != nil { return key, errors.WithMessage(err, "Can't connect to ledger") } - pk.pubKey, _, err = signLedger(dev, []byte{0}) + pk.CachedPubKey, _, err = signLedger(dev, []byte{0}) if err != nil { return key, errors.WithMessage(err, "Can't sign with app") } } - return pk.pubKey, nil + return pk.CachedPubKey, nil } // Equals fulfils PrivKey Interface @@ -219,11 +227,11 @@ func (pk PubKeyLedger) Equals(other crypto.PubKey) bool { func init() { crypto.PrivKeyMapper. - RegisterImplementation(&PrivKeyLedger{}, "ledger", 0x10). + RegisterImplementation(&PrivKeyLedger{}, NameLedger, TypeLedger). RegisterImplementation(MockPrivKeyLedger{}, "mock-ledger", 0x11) crypto.PubKeyMapper. - RegisterImplementation(PubKeyLedger{}, "ledger", 0x10) + RegisterImplementation(PubKeyLedger{}, NameLedger, TypeLedger) } // Wrap fulfils interface for PrivKey struct From 34b9309f245df9bfdcd2697e7cd148f57e57fa2a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Sep 2017 13:13:38 +0200 Subject: [PATCH 142/273] Re-enable signing tests with cryptostore --- keys/cryptostore/holder_test.go | 118 +++++++++++++++++--------------- keys/transactions.go | 51 ++++++++++++++ 2 files changed, 112 insertions(+), 57 deletions(-) diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index a8fc90989..d9e2783af 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -84,65 +84,69 @@ func TestKeyManagement(t *testing.T) { // TestSignVerify does some detailed checks on how we sign and validate // signatures -// func TestSignVerify(t *testing.T) { -// assert, require := assert.New(t), require.New(t) +func TestSignVerify(t *testing.T) { + assert, require := assert.New(t), require.New(t) -// // make the storage with reasonable defaults -// cstore := cryptostore.New( -// cryptostore.GenSecp256k1, -// cryptostore.SecretBox, -// memstorage.New(), -// ) + // make the storage with reasonable defaults + cstore := cryptostore.New( + cryptostore.SecretBox, + memstorage.New(), + keys.MustLoadCodec("english"), + ) + algo := crypto.NameSecp256k1 -// n1, n2 := "some dude", "a dudette" -// p1, p2 := "1234", "foobar" - -// // create two users and get their info -// err := cstore.Create(n1, p1) -// require.Nil(err) -// i1, err := cstore.Get(n1) -// require.Nil(err) - -// err = cstore.Create(n2, p2) -// require.Nil(err) -// i2, err := cstore.Get(n2) -// require.Nil(err) - -// // let's try to sign some messages -// d1 := []byte("my first message") -// d2 := []byte("some other important info!") - -// // try signing both data with both keys... -// s11, err := cstore.Signature(n1, p1, d1) -// require.Nil(err) -// s12, err := cstore.Signature(n1, p1, d2) -// require.Nil(err) -// s21, err := cstore.Signature(n2, p2, d1) -// require.Nil(err) -// s22, err := cstore.Signature(n2, p2, d2) -// require.Nil(err) - -// // let's try to validate and make sure it only works when everything is proper -// keys := [][]byte{i1.PubKey, i2.PubKey} -// data := [][]byte{d1, d2} -// sigs := [][]byte{s11, s12, s21, s22} - -// // loop over keys and data -// for k := 0; k < 2; k++ { -// for d := 0; d < 2; d++ { -// // make sure only the proper sig works -// good := 2*k + d -// for s := 0; s < 4; s++ { -// err = cstore.Verify(data[d], sigs[s], keys[k]) -// if s == good { -// assert.Nil(err, "%+v", err) -// } else { -// assert.NotNil(err) -// } -// } -// } -// } -// } + n1, n2 := "some dude", "a dudette" + p1, p2 := "1234", "foobar" + + // create two users and get their info + i1, _, err := cstore.Create(n1, p1, algo) + require.Nil(err) + + i2, _, err := cstore.Create(n2, p2, algo) + require.Nil(err) + + // let's try to sign some messages + d1 := []byte("my first message") + d2 := []byte("some other important info!") + + // try signing both data with both keys... + s11 := keys.NewMockSignable(d1) + err = cstore.Sign(n1, p1, s11) + require.Nil(err) + s12 := keys.NewMockSignable(d2) + err = cstore.Sign(n1, p1, s12) + require.Nil(err) + s21 := keys.NewMockSignable(d1) + err = cstore.Sign(n2, p2, s21) + require.Nil(err) + s22 := keys.NewMockSignable(d2) + err = cstore.Sign(n2, p2, s22) + require.Nil(err) + + // let's try to validate and make sure it only works when everything is proper + cases := []struct { + key crypto.PubKey + data []byte + sig crypto.Signature + valid bool + }{ + // proper matches + {i1.PubKey, d1, s11.Signature, true}, + // change data, pubkey, or signature leads to fail + {i1.PubKey, d2, s11.Signature, false}, + {i2.PubKey, d1, s11.Signature, false}, + {i1.PubKey, d1, s21.Signature, false}, + // make sure other successes + {i1.PubKey, d2, s12.Signature, true}, + {i2.PubKey, d1, s21.Signature, true}, + {i2.PubKey, d2, s22.Signature, true}, + } + + for i, tc := range cases { + valid := tc.key.VerifyBytes(tc.data, tc.sig) + assert.Equal(tc.valid, valid, "%d", i) + } +} func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) diff --git a/keys/transactions.go b/keys/transactions.go index 10da7a6fa..1834ada26 100644 --- a/keys/transactions.go +++ b/keys/transactions.go @@ -1,9 +1,11 @@ package keys import ( + "fmt" "sort" crypto "github.com/tendermint/go-crypto" + wire "github.com/tendermint/go-wire" data "github.com/tendermint/go-wire/data" ) @@ -72,3 +74,52 @@ type Manager interface { Update(name, oldpass, newpass string) error Delete(name, passphrase string) error } + +/**** MockSignable allows us to view data ***/ + +// MockSignable lets us wrap arbitrary data with a go-crypto signature +type MockSignable struct { + Data []byte + PubKey crypto.PubKey + Signature crypto.Signature +} + +var _ Signable = &MockSignable{} + +// NewMockSignable sets the data to sign +func NewMockSignable(data []byte) *MockSignable { + return &MockSignable{Data: data} +} + +// TxBytes returns the full data with signatures +func (s *MockSignable) TxBytes() ([]byte, error) { + return wire.BinaryBytes(s), nil +} + +// SignBytes returns the original data passed into `NewSig` +func (s *MockSignable) SignBytes() []byte { + return s.Data +} + +// Sign will add a signature and pubkey. +// +// Depending on the Signable, one may be able to call this multiple times for multisig +// Returns error if called with invalid data or too many times +func (s *MockSignable) Sign(pubkey crypto.PubKey, sig crypto.Signature) error { + s.PubKey = pubkey + s.Signature = sig + return nil +} + +// Signers will return the public key(s) that signed if the signature +// is valid, or an error if there is any issue with the signature, +// including if there are no signatures +func (s *MockSignable) Signers() ([]crypto.PubKey, error) { + if s.PubKey.Empty() { + return nil, fmt.Errorf("no signers") + } + if !s.PubKey.VerifyBytes(s.SignBytes(), s.Signature) { + return nil, fmt.Errorf("invalid signature") + } + return []crypto.PubKey{s.PubKey}, nil +} From 88475230c46274bfde4f58649d3228622b7c8eba Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Sep 2017 13:23:18 +0200 Subject: [PATCH 143/273] Re-enabled crypostore example usage --- keys/cryptostore/holder_test.go | 100 ++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index d9e2783af..59d3663ae 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -1,6 +1,8 @@ package cryptostore_test import ( + "bytes" + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -260,45 +262,59 @@ func TestSeedPhrase(t *testing.T) { assert.Equal(info.PubKey, newInfo.PubKey) } -// func ExampleStore() { -// // Select the encryption and storage for your cryptostore -// cstore := cryptostore.New( -// cryptostore.GenEd25519, -// cryptostore.SecretBox, -// // Note: use filestorage.New(dir) for real data -// memstorage.New(), -// ) - -// // Add keys and see they return in alphabetical order -// cstore.Create("Bob", "friend") -// cstore.Create("Alice", "secret") -// cstore.Create("Carl", "mitm") -// info, _ := cstore.List() -// for _, i := range info { -// fmt.Println(i.Name) -// } - -// // We need to use passphrase to generate a signature -// tx := mock.NewSig([]byte("deadbeef")) -// err := cstore.Sign("Bob", "friend", tx) -// if err != nil { -// fmt.Println("don't accept real passphrase") -// } - -// // and we can validate the signature with publically available info -// binfo, _ := cstore.Get("Bob") -// sigs, err := tx.Signers() -// if err != nil { -// fmt.Println("badly signed") -// } else if bytes.Equal(sigs[0].Bytes(), binfo.PubKey.Bytes()) { -// fmt.Println("signed by Bob") -// } else { -// fmt.Println("signed by someone else") -// } - -// // Output: -// // Alice -// // Bob -// // Carl -// // signed by Bob -// } +func ExampleStore() { + // Select the encryption and storage for your cryptostore + cstore := cryptostore.New( + cryptostore.SecretBox, + // Note: use filestorage.New(dir) for real data + memstorage.New(), + keys.MustLoadCodec("english"), + ) + ed := crypto.NameEd25519 + sec := crypto.NameSecp256k1 + + // Add keys and see they return in alphabetical order + bob, _, err := cstore.Create("Bob", "friend", ed) + if err != nil { + // this should never happen + fmt.Println(err) + } else { + // return info here just like in List + fmt.Println(bob.Name) + } + cstore.Create("Alice", "secret", sec) + cstore.Create("Carl", "mitm", ed) + info, _ := cstore.List() + for _, i := range info { + fmt.Println(i.Name) + } + + // We need to use passphrase to generate a signature + tx := keys.NewMockSignable([]byte("deadbeef")) + err = cstore.Sign("Bob", "friend", tx) + if err != nil { + fmt.Println("don't accept real passphrase") + } + + // and we can validate the signature with publically available info + binfo, _ := cstore.Get("Bob") + if !binfo.PubKey.Equals(bob.PubKey) { + fmt.Println("Get and Create return different keys") + } + + sigs, err := tx.Signers() + if err != nil { + fmt.Println("badly signed") + } else if bytes.Equal(sigs[0].Bytes(), binfo.PubKey.Bytes()) { + fmt.Println("signed by Bob") + } else { + fmt.Println("signed by someone else") + } + + // Output: + // Bob + // Alice + // Bob + // Carl + // signed by Bob +} From 91fccb8b14574c7a7041ed221663bcdc3f225939 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Sep 2017 13:34:04 +0200 Subject: [PATCH 144/273] Add test for cryptostore working with ledger --- keys/cryptostore/holder_test.go | 55 +++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 59d3663ae..dbd269717 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -3,6 +3,7 @@ package cryptostore_test import ( "bytes" "fmt" + "os" "testing" "github.com/stretchr/testify/assert" @@ -14,6 +15,7 @@ import ( "github.com/tendermint/go-crypto/keys" "github.com/tendermint/go-crypto/keys/cryptostore" "github.com/tendermint/go-crypto/keys/storage/memstorage" + "github.com/tendermint/go-crypto/nano" ) // TestKeyManagement makes sure we can manipulate these keys well @@ -150,6 +152,59 @@ func TestSignVerify(t *testing.T) { } } +// TestSignWithLedger makes sure we have ledger compatibility with +// the crypto store. +// +// This test will only succeed with a ledger attached to the computer +// and the cosmos app open +func TestSignWithLedger(t *testing.T) { + assert, require := assert.New(t), require.New(t) + if os.Getenv("WITH_LEDGER") == "" { + t.Skip("Set WITH_LEDGER to run code on real ledger") + } + + // make the storage with reasonable defaults + cstore := cryptostore.New( + cryptostore.SecretBox, + memstorage.New(), + keys.MustLoadCodec("english"), + ) + n := "nano-s" + p := "hard2hack" + + // create a nano user + c, _, err := cstore.Create(n, p, nano.NameLedger) + require.Nil(err, "%+v", err) + assert.Equal(c.Name, n) + _, ok := c.PubKey.Unwrap().(nano.PubKeyLedger) + require.True(ok) + + // make sure we can get it back + info, err := cstore.Get(n) + require.Nil(err, "%+v", err) + assert.Equal(info.Name, n) + key := info.PubKey + require.False(key.Empty()) + + // let's try to sign some messages + d1 := []byte("welcome to cosmos") + d2 := []byte("please turn on the app") + + // try signing both data with the ledger... + s1 := keys.NewMockSignable(d1) + err = cstore.Sign(n, p, s1) + require.Nil(err) + s2 := keys.NewMockSignable(d2) + err = cstore.Sign(n, p, s2) + require.Nil(err) + + // now, let's check those signatures work + assert.True(key.VerifyBytes(d1, s1.Signature)) + assert.True(key.VerifyBytes(d2, s2.Signature)) + // and mismatched signatures don't + assert.False(key.VerifyBytes(d1, s2.Signature)) +} + func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) assert.NotNil(err) From 085d72d212b72aea196ffd1b32f06df908b09a9b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 13 Sep 2017 13:53:08 +0200 Subject: [PATCH 145/273] Cleanup nano calls, cannot run parallel test on one hardware device --- Makefile | 2 +- keys/cryptostore/holder_test.go | 1 + nano/keys.go | 2 ++ nano/sign.go | 2 -- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index f775704a9..c1974c410 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ REPO:=github.com/tendermint/go-crypto all: get_vendor_deps metalinter_test test test: - go test `glide novendor` + go test -p 1 `glide novendor` get_vendor_deps: ensure_tools @rm -rf vendor/ diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index dbd269717..f0dc77c4d 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -185,6 +185,7 @@ func TestSignWithLedger(t *testing.T) { assert.Equal(info.Name, n) key := info.PubKey require.False(key.Empty()) + require.True(key.Equals(c.PubKey)) // let's try to sign some messages d1 := []byte("welcome to cosmos") diff --git a/nano/keys.go b/nano/keys.go index 2ab4d59a8..c0eccc492 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -92,6 +92,8 @@ func (pk *PrivKeyLedger) Sign(msg []byte) crypto.Signature { // if we have no pubkey yet, store it for future queries if pk.CachedPubKey.Empty() { pk.CachedPubKey = pub + } else if !pk.CachedPubKey.Equals(pub) { + panic("signed with a different key than stored") } return sig } diff --git a/nano/sign.go b/nano/sign.go index 3f0df9ee5..874d134e8 100644 --- a/nano/sign.go +++ b/nano/sign.go @@ -3,7 +3,6 @@ package nano import ( "bytes" "crypto/sha512" - "fmt" "github.com/pkg/errors" @@ -55,7 +54,6 @@ func parseDigest(resp []byte) (key, sig []byte, err error) { if !bytes.Equal(separator, resp[:len(separator)]) { return nil, nil, errors.New("Cannot find 0xCAFE") } - fmt.Println("successs") sig = resp[len(separator):] return key, sig, nil From ae078ee915c8387bae25fd9104754a7b2342e68b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 16:35:26 +0200 Subject: [PATCH 146/273] Generate/recover can return error, not panic on ledger --- keys/cryptostore/encoder_test.go | 12 ++++-- keys/cryptostore/generator.go | 63 ++++++++++++++++++++------------ keys/cryptostore/holder.go | 13 ++++--- keys/cryptostore/holder_test.go | 6 ++- keys/cryptostore/storage_test.go | 5 ++- 5 files changed, 62 insertions(+), 37 deletions(-) diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go index ce1118d20..9cde95a12 100644 --- a/keys/cryptostore/encoder_test.go +++ b/keys/cryptostore/encoder_test.go @@ -15,8 +15,10 @@ func TestNoopEncoder(t *testing.T) { assert, require := assert.New(t), require.New(t) noop := cryptostore.Noop - key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) - key2 := cryptostore.GenSecp256k1.Generate(cmn.RandBytes(16)) + key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + require.NoError(err) + key2, err := cryptostore.GenSecp256k1.Generate(cmn.RandBytes(16)) + require.NoError(err) _, b, err := noop.Encrypt(key, "encode") require.Nil(err) @@ -43,7 +45,8 @@ func TestSecretBox(t *testing.T) { assert, require := assert.New(t), require.New(t) enc := cryptostore.SecretBox - key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + require.NoError(err) pass := "some-special-secret" s, b, err := enc.Encrypt(key, pass) @@ -65,7 +68,8 @@ func TestSecretBoxNoPass(t *testing.T) { assert, require := assert.New(t), require.New(t) enc := cryptostore.SecretBox - key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + require.NoError(err) cases := []struct { encode string diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index c1984fc82..5a05b7e6e 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -18,57 +18,72 @@ var ( // Generator determines the type of private key the keystore creates type Generator interface { - Generate(secret []byte) crypto.PrivKey + Generate(secret []byte) (crypto.PrivKey, error) } // GenFunc is a helper to transform a function into a Generator -type GenFunc func(secret []byte) crypto.PrivKey +type GenFunc func(secret []byte) (crypto.PrivKey, error) -func (f GenFunc) Generate(secret []byte) crypto.PrivKey { +func (f GenFunc) Generate(secret []byte) (crypto.PrivKey, error) { return f(secret) } -func genEd25519(secret []byte) crypto.PrivKey { - return crypto.GenPrivKeyEd25519FromSecret(secret).Wrap() +func genEd25519(secret []byte) (crypto.PrivKey, error) { + key := crypto.GenPrivKeyEd25519FromSecret(secret).Wrap() + return key, nil } -func genSecp256(secret []byte) crypto.PrivKey { - return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap() +func genSecp256(secret []byte) (crypto.PrivKey, error) { + key := crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap() + return key, nil } // secret is completely ignored for the ledger... // just for interface compatibility -func genLedger(secret []byte) crypto.PrivKey { - key, err := nano.NewPrivKeyLedger() - if err != nil { - // TODO: cleaner error handling - panic(err) - } - return key +func genLedger(secret []byte) (crypto.PrivKey, error) { + return nano.NewPrivKeyLedger() +} + +type genInvalidByte struct { + typ byte +} + +func (g genInvalidByte) Generate(secret []byte) (crypto.PrivKey, error) { + err := errors.Errorf("Cannot generate keys for algorithm: %X", g.typ) + return crypto.PrivKey{}, err +} + +type genInvalidAlgo struct { + algo string +} + +func (g genInvalidAlgo) Generate(secret []byte) (crypto.PrivKey, error) { + err := errors.Errorf("Cannot generate keys for algorithm: %s", g.algo) + return crypto.PrivKey{}, err } -func getGenerator(algo string) (Generator, error) { +func getGenerator(algo string) Generator { switch algo { case crypto.NameEd25519: - return GenEd25519, nil + return GenEd25519 case crypto.NameSecp256k1: - return GenSecp256k1, nil + return GenSecp256k1 case nano.NameLedger: - return GenLedger, nil + return GenLedger default: - return nil, errors.Errorf("Cannot generate keys for algorithm: %s", algo) + return genInvalidAlgo{algo} } } -func getGeneratorByType(typ byte) (Generator, error) { +func getGeneratorByType(typ byte) Generator { switch typ { case crypto.TypeEd25519: - return GenEd25519, nil + return GenEd25519 case crypto.TypeSecp256k1: - return GenSecp256k1, nil + return GenSecp256k1 case nano.TypeLedger: - return GenLedger, nil + return GenLedger default: - return nil, errors.Errorf("Cannot generate keys for algorithm: %X", typ) + return genInvalidByte{typ} } } diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index cb8a2e149..923190c1b 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -33,14 +33,15 @@ var _ keys.Manager = Manager{} // // algo must be a supported go-crypto algorithm: ed25519, secp256k1 func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error) { - gen, err := getGenerator(algo) + // 128-bits are the all the randomness we can make use of + secret := crypto.CRandBytes(16) + gen := getGenerator(algo) + + key, err := gen.Generate(secret) if err != nil { return keys.Info{}, "", err } - // 128-bits are the all the randomness we can make use of - secret := crypto.CRandBytes(16) - key := gen.Generate(secret) err = s.es.Put(name, passphrase, key) if err != nil { return keys.Info{}, "", err @@ -74,11 +75,11 @@ func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) l := len(secret) secret, typ := secret[:l-1], secret[l-1] - gen, err := getGeneratorByType(typ) + gen := getGeneratorByType(typ) + key, err := gen.Generate(secret) if err != nil { return keys.Info{}, err } - key := gen.Generate(secret) // d00d, it worked! create the bugger.... err = s.es.Put(name, passphrase, key) diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index f0dc77c4d..80ebcc528 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -224,13 +224,15 @@ func TestImportUnencrypted(t *testing.T) { keys.MustLoadCodec("english"), ) - key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + require.NoError(err) + addr := key.PubKey().Address() name := "john" pass := "top-secret" // import raw bytes - err := cstore.Import(name, pass, "", nil, key.Bytes()) + err = cstore.Import(name, pass, "", nil, key.Bytes()) require.Nil(err, "%+v", err) // make sure the address matches diff --git a/keys/cryptostore/storage_test.go b/keys/cryptostore/storage_test.go index 468435143..23931c294 100644 --- a/keys/cryptostore/storage_test.go +++ b/keys/cryptostore/storage_test.go @@ -14,7 +14,10 @@ import ( func TestSortKeys(t *testing.T) { assert := assert.New(t) - gen := func() crypto.PrivKey { return GenEd25519.Generate(cmn.RandBytes(16)) } + gen := func() crypto.PrivKey { + key, _ := GenEd25519.Generate(cmn.RandBytes(16)) + return key + } assert.NotEqual(gen(), gen()) // alphabetical order is n3, n1, n2 From 1b8d52bb8258c1490e3bc57a30b8b18a2cb25d40 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 16:38:57 +0200 Subject: [PATCH 147/273] Rename NameLedger to NameLedgerEd25519 --- keys/cryptostore/generator.go | 4 ++-- keys/cryptostore/holder_test.go | 2 +- nano/keys.go | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index 5a05b7e6e..6b2d47a1a 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -68,7 +68,7 @@ func getGenerator(algo string) Generator { return GenEd25519 case crypto.NameSecp256k1: return GenSecp256k1 - case nano.NameLedger: + case nano.NameLedgerEd25519: return GenLedger default: return genInvalidAlgo{algo} @@ -81,7 +81,7 @@ func getGeneratorByType(typ byte) Generator { return GenEd25519 case crypto.TypeSecp256k1: return GenSecp256k1 - case nano.TypeLedger: + case nano.TypeLedgerEd25519: return GenLedger default: return genInvalidByte{typ} diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 80ebcc528..831fa251e 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -173,7 +173,7 @@ func TestSignWithLedger(t *testing.T) { p := "hard2hack" // create a nano user - c, _, err := cstore.Create(n, p, nano.NameLedger) + c, _, err := cstore.Create(n, p, nano.NameLedgerEd25519) require.Nil(err, "%+v", err) assert.Equal(c.Name, n) _, ok := c.PubKey.Unwrap().(nano.PubKeyLedger) diff --git a/nano/keys.go b/nano/keys.go index c0eccc492..bd56af6db 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -13,8 +13,8 @@ import ( ) const ( - NameLedger = "ledger" - TypeLedger = 0x10 + NameLedgerEd25519 = "ledger" + TypeLedgerEd25519 = 0x10 ) var device *ledger.Ledger @@ -229,11 +229,11 @@ func (pk PubKeyLedger) Equals(other crypto.PubKey) bool { func init() { crypto.PrivKeyMapper. - RegisterImplementation(&PrivKeyLedger{}, NameLedger, TypeLedger). + RegisterImplementation(&PrivKeyLedger{}, NameLedgerEd25519, TypeLedgerEd25519). RegisterImplementation(MockPrivKeyLedger{}, "mock-ledger", 0x11) crypto.PubKeyMapper. - RegisterImplementation(PubKeyLedger{}, NameLedger, TypeLedger) + RegisterImplementation(PubKeyLedger{}, NameLedgerEd25519, TypeLedgerEd25519) } // Wrap fulfils interface for PrivKey struct From bce88a20df7d06408453b99127e8b09e1b385933 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 17:11:12 +0200 Subject: [PATCH 148/273] Enable privkey validity checking on load --- priv_key.go | 16 +++++++++++- priv_key_test.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 priv_key_test.go diff --git a/priv_key.go b/priv_key.go index 0c6bd2ae7..e6e7ac036 100644 --- a/priv_key.go +++ b/priv_key.go @@ -13,13 +13,27 @@ import ( func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { err = wire.ReadBinaryBytes(privKeyBytes, &privKey) + if err == nil { + // add support for a ValidateKey method on PrivKeys + // to make sure they load correctly + val, ok := privKey.Unwrap().(validatable) + if ok { + err = val.ValidateKey() + } + } return } +// validatable is an optional interface for keys that want to +// check integrity +type validatable interface { + ValidateKey() error +} + //---------------------------------------- // DO NOT USE THIS INTERFACE. -// You probably want to use PubKey +// You probably want to use PrivKey // +gen wrapper:"PrivKey,Impl[PrivKeyEd25519,PrivKeySecp256k1],ed25519,secp256k1" type PrivKeyInner interface { AssertIsPrivKeyInner() diff --git a/priv_key_test.go b/priv_key_test.go new file mode 100644 index 000000000..154df5593 --- /dev/null +++ b/priv_key_test.go @@ -0,0 +1,65 @@ +package crypto + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + wire "github.com/tendermint/go-wire" +) + +type BadKey struct { + PrivKeyEd25519 +} + +// Wrap fulfils interface for PrivKey struct +func (pk BadKey) Wrap() PrivKey { + return PrivKey{pk} +} + +func (pk BadKey) Bytes() []byte { + return wire.BinaryBytes(pk.Wrap()) +} + +func (pk BadKey) ValidateKey() error { + return fmt.Errorf("fuggly key") +} + +func init() { + PrivKeyMapper. + RegisterImplementation(BadKey{}, "bad", 0x66) +} + +func TestReadPrivKey(t *testing.T) { + assert, require := assert.New(t), require.New(t) + + // garbage in, garbage out + garbage := []byte("hjgewugfbiewgofwgewr") + _, err := PrivKeyFromBytes(garbage) + require.Error(err) + + edKey := GenPrivKeyEd25519() + badKey := BadKey{edKey} + + cases := []struct { + key PrivKey + valid bool + }{ + {edKey.Wrap(), true}, + {badKey.Wrap(), false}, + } + + for i, tc := range cases { + data := tc.key.Bytes() + key, err := PrivKeyFromBytes(data) + if tc.valid { + assert.NoError(err, "%d", i) + assert.Equal(tc.key, key, "%d", i) + } else { + assert.Error(err, "%d: %#v", i, key) + } + } + +} From 2490952515786d308cd5097d4c789afc940f2a3b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 17:19:35 +0200 Subject: [PATCH 149/273] nano validates key on load --- nano/keys.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/nano/keys.go b/nano/keys.go index bd56af6db..4bb0e97c5 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -59,6 +59,8 @@ type PrivKeyLedger struct { CachedPubKey crypto.PubKey } +// NewPrivKeyLedger will generate a new key and store the +// public key for later use. func NewPrivKeyLedger() (crypto.PrivKey, error) { var pk PrivKeyLedger // getPubKey will cache the pubkey for later use, @@ -68,6 +70,22 @@ func NewPrivKeyLedger() (crypto.PrivKey, error) { return pk.Wrap(), err } +// ValidateKey allows us to verify the sanity of a key +// after loading it from disk +func (pk *PrivKeyLedger) ValidateKey() error { + // getPubKey will return an error if the ledger is not + // properly set up... + pub, err := pk.getPubKey() + if err != nil { + return err + } + // verify this matches cached address + if !pub.Equals(pk.CachedPubKey) { + return errors.New("ledger doesn't match cached key") + } + return nil +} + // AssertIsPrivKeyInner fulfils PrivKey Interface func (pk *PrivKeyLedger) AssertIsPrivKeyInner() {} From 9afceb7ee844443cb41c2378f88871ec3c0dddce Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 18:14:28 +0200 Subject: [PATCH 150/273] ledger pubkey serializes properly, better load checks --- nano/keys.go | 31 ++++++++++++++++++++++--------- nano/keys_test.go | 6 ++++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/nano/keys.go b/nano/keys.go index 4bb0e97c5..a3337f1e5 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -12,6 +12,7 @@ import ( wire "github.com/tendermint/go-wire" ) +//nolint const ( NameLedgerEd25519 = "ledger" TypeLedgerEd25519 = 0x10 @@ -132,16 +133,23 @@ func (pk *PrivKeyLedger) PubKey() crypto.PubKey { func (pk *PrivKeyLedger) getPubKey() (key crypto.PubKey, err error) { // if we have no pubkey, set it if pk.CachedPubKey.Empty() { - dev, err := getLedger() - if err != nil { - return key, errors.WithMessage(err, "Can't connect to ledger") - } - pk.CachedPubKey, _, err = signLedger(dev, []byte{0}) - if err != nil { - return key, errors.WithMessage(err, "Can't sign with app") - } + pk.CachedPubKey, err = pk.forceGetPubKey() } - return pk.CachedPubKey, nil + return pk.CachedPubKey, err +} + +// forceGetPubKey is like getPubKey but ignores any cached key +// and ensures we get it from the ledger itself. +func (pk *PrivKeyLedger) forceGetPubKey() (key crypto.PubKey, err error) { + dev, err := getLedger() + if err != nil { + return key, errors.New("Can't connect to ledger device") + } + key, _, err = signLedger(dev, []byte{0}) + if err != nil { + return key, errors.New("Please open cosmos app on the ledger") + } + return key, err } // Equals fulfils PrivKey Interface @@ -229,6 +237,11 @@ func PubKeyLedgerFromBytes(key [32]byte) crypto.PubKey { return PubKeyLedger{crypto.PubKeyEd25519(key)}.Wrap() } +// Bytes fulfils pk Interface - no data, just type info +func (pk PubKeyLedger) Bytes() []byte { + return wire.BinaryBytes(pk.Wrap()) +} + // VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand func (pk PubKeyLedger) VerifyBytes(msg []byte, sig crypto.Signature) bool { hmsg := hashMsg(msg) diff --git a/nano/keys_test.go b/nano/keys_test.go index b42b091f0..40cd1b486 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -104,4 +104,10 @@ func TestRealLedger(t *testing.T) { valid = pub.VerifyBytes(msg, sig) assert.True(valid) + // make sure pubkeys serialize properly as well + bs = pub.Bytes() + bpub, err := crypto.PubKeyFromBytes(bs) + require.NoError(err) + assert.Equal(pub, bpub) + } From 61d1bdb5eda2a335da51ed51fd286b404ea85087 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 18:32:29 +0200 Subject: [PATCH 151/273] Test error handling, load without ledger --- nano/keys.go | 2 +- nano/keys_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/nano/keys.go b/nano/keys.go index a3337f1e5..8d4d3d06d 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -76,7 +76,7 @@ func NewPrivKeyLedger() (crypto.PrivKey, error) { func (pk *PrivKeyLedger) ValidateKey() error { // getPubKey will return an error if the ledger is not // properly set up... - pub, err := pk.getPubKey() + pub, err := pk.forceGetPubKey() if err != nil { return err } diff --git a/nano/keys_test.go b/nano/keys_test.go index 40cd1b486..3815d3944 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" ) @@ -109,5 +110,33 @@ func TestRealLedger(t *testing.T) { bpub, err := crypto.PubKeyFromBytes(bs) require.NoError(err) assert.Equal(pub, bpub) +} + +// TestRealLedgerErrorHandling calls. These tests assume +// the ledger is not plugged in.... +func TestRealLedgerErrorHandling(t *testing.T) { + require := require.New(t) + + if os.Getenv("WITH_LEDGER") != "" { + t.Skip("Skipping on WITH_LEDGER as it tests unplugged cases") + } + + // first, try to generate a key, must return an error + // (no panic) + _, err := NewPrivKeyLedger() + require.Error(err) + + led := PrivKeyLedger{} // empty + // or with some pub key + ed := crypto.GenPrivKeyEd25519() + led2 := PrivKeyLedger{CachedPubKey: ed.PubKey()} + + // loading these should return errors + bs := led.Bytes() + _, err = crypto.PrivKeyFromBytes(bs) + require.Error(err) + bs = led2.Bytes() + _, err = crypto.PrivKeyFromBytes(bs) + require.Error(err) } From 9601e48ab40a5a871992651b6e881b82fb88a26c Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 23 Oct 2017 18:39:34 +0200 Subject: [PATCH 152/273] Improve error message --- keys/cryptostore/encoder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 251543b60..0b957d826 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -55,7 +55,7 @@ func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) } privKey, err = crypto.PrivKeyFromBytes(privKeyBytes) if err != nil { - return crypto.PrivKey{}, errors.Wrap(err, "Couldn't get privKey from bytes") + return crypto.PrivKey{}, errors.Wrap(err, "Private Key") } return privKey, nil } From 4a2c63f5e17f2278f31024112484454a75a7bf86 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 24 Oct 2017 11:23:09 +0200 Subject: [PATCH 153/273] Update ledger names to specify ed25519 --- keys/cryptostore/generator.go | 12 ++--- keys/cryptostore/holder_test.go | 2 +- nano/keys.go | 86 ++++++++++++++++----------------- nano/keys_test.go | 8 +-- 4 files changed, 54 insertions(+), 54 deletions(-) diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index 6b2d47a1a..65cc8e58b 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -12,8 +12,8 @@ var ( GenEd25519 Generator = GenFunc(genEd25519) // GenSecp256k1 produces Secp256k1 private keys GenSecp256k1 Generator = GenFunc(genSecp256) - // GenLedger used Ed25519 keys stored on nano ledger s with cosmos app - GenLedger Generator = GenFunc(genLedger) + // GenLedgerEd25519 used Ed25519 keys stored on nano ledger s with cosmos app + GenLedgerEd25519 Generator = GenFunc(genLedgerEd25519) ) // Generator determines the type of private key the keystore creates @@ -40,8 +40,8 @@ func genSecp256(secret []byte) (crypto.PrivKey, error) { // secret is completely ignored for the ledger... // just for interface compatibility -func genLedger(secret []byte) (crypto.PrivKey, error) { - return nano.NewPrivKeyLedger() +func genLedgerEd25519(secret []byte) (crypto.PrivKey, error) { + return nano.NewPrivKeyLedgerEd25519Ed25519() } type genInvalidByte struct { @@ -69,7 +69,7 @@ func getGenerator(algo string) Generator { case crypto.NameSecp256k1: return GenSecp256k1 case nano.NameLedgerEd25519: - return GenLedger + return GenLedgerEd25519 default: return genInvalidAlgo{algo} } @@ -82,7 +82,7 @@ func getGeneratorByType(typ byte) Generator { case crypto.TypeSecp256k1: return GenSecp256k1 case nano.TypeLedgerEd25519: - return GenLedger + return GenLedgerEd25519 default: return genInvalidByte{typ} } diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 831fa251e..899f51f02 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -176,7 +176,7 @@ func TestSignWithLedger(t *testing.T) { c, _, err := cstore.Create(n, p, nano.NameLedgerEd25519) require.Nil(err, "%+v", err) assert.Equal(c.Name, n) - _, ok := c.PubKey.Unwrap().(nano.PubKeyLedger) + _, ok := c.PubKey.Unwrap().(nano.PubKeyLedgerEd25519) require.True(ok) // make sure we can get it back diff --git a/nano/keys.go b/nano/keys.go index 8d4d3d06d..dc1eec950 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -14,7 +14,7 @@ import ( //nolint const ( - NameLedgerEd25519 = "ledger" + NameLedgerEd25519 = "ledger-ed25519" TypeLedgerEd25519 = 0x10 ) @@ -48,22 +48,22 @@ func signLedger(device *ledger.Ledger, msg []byte) (pk crypto.PubKey, sig crypto var b [32]byte copy(b[:], key) - return PubKeyLedgerFromBytes(b), crypto.SignatureEd25519FromBytes(bsig), nil + return PubKeyLedgerEd25519FromBytes(b), crypto.SignatureEd25519FromBytes(bsig), nil } -// PrivKeyLedger implements PrivKey, calling the ledger nano +// PrivKeyLedgerEd25519 implements PrivKey, calling the ledger nano // we cache the PubKey from the first call to use it later -type PrivKeyLedger struct { +type PrivKeyLedgerEd25519 struct { // PubKey should be private, but we want to encode it via go-wire // so we can view the address later, even without having the ledger // attached CachedPubKey crypto.PubKey } -// NewPrivKeyLedger will generate a new key and store the +// NewPrivKeyLedgerEd25519Ed25519 will generate a new key and store the // public key for later use. -func NewPrivKeyLedger() (crypto.PrivKey, error) { - var pk PrivKeyLedger +func NewPrivKeyLedgerEd25519Ed25519() (crypto.PrivKey, error) { + var pk PrivKeyLedgerEd25519 // getPubKey will cache the pubkey for later use, // this allows us to return an error early if the ledger // is not plugged in @@ -73,7 +73,7 @@ func NewPrivKeyLedger() (crypto.PrivKey, error) { // ValidateKey allows us to verify the sanity of a key // after loading it from disk -func (pk *PrivKeyLedger) ValidateKey() error { +func (pk *PrivKeyLedgerEd25519) ValidateKey() error { // getPubKey will return an error if the ledger is not // properly set up... pub, err := pk.forceGetPubKey() @@ -88,15 +88,15 @@ func (pk *PrivKeyLedger) ValidateKey() error { } // AssertIsPrivKeyInner fulfils PrivKey Interface -func (pk *PrivKeyLedger) AssertIsPrivKeyInner() {} +func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} // Bytes fulfils pk Interface - no data, just type info -func (pk *PrivKeyLedger) Bytes() []byte { +func (pk *PrivKeyLedgerEd25519) Bytes() []byte { return wire.BinaryBytes(pk.Wrap()) } // Sign calls the ledger and stores the pk for future use -func (pk *PrivKeyLedger) Sign(msg []byte) crypto.Signature { +func (pk *PrivKeyLedgerEd25519) Sign(msg []byte) crypto.Signature { // oh, I wish there was better error handling dev, err := getLedger() if err != nil { @@ -119,7 +119,7 @@ func (pk *PrivKeyLedger) Sign(msg []byte) crypto.Signature { // PubKey returns the stored PubKey // TODO: query the ledger if not there, once it is not volatile -func (pk *PrivKeyLedger) PubKey() crypto.PubKey { +func (pk *PrivKeyLedgerEd25519) PubKey() crypto.PubKey { key, err := pk.getPubKey() if err != nil { panic(err) @@ -130,7 +130,7 @@ func (pk *PrivKeyLedger) PubKey() crypto.PubKey { // getPubKey reads the pubkey from cache or from the ledger itself // since this involves IO, it may return an error, which is not exposed // in the PubKey interface, so this function allows better error handling -func (pk *PrivKeyLedger) getPubKey() (key crypto.PubKey, err error) { +func (pk *PrivKeyLedgerEd25519) getPubKey() (key crypto.PubKey, err error) { // if we have no pubkey, set it if pk.CachedPubKey.Empty() { pk.CachedPubKey, err = pk.forceGetPubKey() @@ -140,7 +140,7 @@ func (pk *PrivKeyLedger) getPubKey() (key crypto.PubKey, err error) { // forceGetPubKey is like getPubKey but ignores any cached key // and ensures we get it from the ledger itself. -func (pk *PrivKeyLedger) forceGetPubKey() (key crypto.PubKey, err error) { +func (pk *PrivKeyLedgerEd25519) forceGetPubKey() (key crypto.PubKey, err error) { dev, err := getLedger() if err != nil { return key, errors.New("Can't connect to ledger device") @@ -154,23 +154,23 @@ func (pk *PrivKeyLedger) forceGetPubKey() (key crypto.PubKey, err error) { // Equals fulfils PrivKey Interface // TODO: needs to be fixed -func (pk *PrivKeyLedger) Equals(other crypto.PrivKey) bool { - if _, ok := other.Unwrap().(*PrivKeyLedger); ok { +func (pk *PrivKeyLedgerEd25519) Equals(other crypto.PrivKey) bool { + if _, ok := other.Unwrap().(*PrivKeyLedgerEd25519); ok { return true } return false } -// MockPrivKeyLedger behaves as the ledger, but stores a pre-packaged call-response +// MockPrivKeyLedgerEd25519 behaves as the ledger, but stores a pre-packaged call-response // for use in test cases -type MockPrivKeyLedger struct { +type MockPrivKeyLedgerEd25519 struct { Msg []byte Pub [KeyLength]byte Sig [SigLength]byte } // NewMockKey returns -func NewMockKey(msg, pubkey, sig string) (pk MockPrivKeyLedger) { +func NewMockKey(msg, pubkey, sig string) (pk MockPrivKeyLedgerEd25519) { var err error pk.Msg, err = hex.DecodeString(msg) if err != nil { @@ -191,32 +191,32 @@ func NewMockKey(msg, pubkey, sig string) (pk MockPrivKeyLedger) { return pk } -var _ crypto.PrivKeyInner = MockPrivKeyLedger{} +var _ crypto.PrivKeyInner = MockPrivKeyLedgerEd25519{} // AssertIsPrivKeyInner fulfils PrivKey Interface -func (pk MockPrivKeyLedger) AssertIsPrivKeyInner() {} +func (pk MockPrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} // Bytes fulfils PrivKey Interface - not supported -func (pk MockPrivKeyLedger) Bytes() []byte { +func (pk MockPrivKeyLedgerEd25519) Bytes() []byte { return nil } // Sign returns a real SignatureLedger, if the msg matches what we expect -func (pk MockPrivKeyLedger) Sign(msg []byte) crypto.Signature { +func (pk MockPrivKeyLedgerEd25519) Sign(msg []byte) crypto.Signature { if !bytes.Equal(pk.Msg, msg) { panic("Mock key is for different msg") } return crypto.SignatureEd25519(pk.Sig).Wrap() } -// PubKey returns a real PubKeyLedger, that will verify this signature -func (pk MockPrivKeyLedger) PubKey() crypto.PubKey { - return PubKeyLedgerFromBytes(pk.Pub) +// PubKey returns a real PubKeyLedgerEd25519, that will verify this signature +func (pk MockPrivKeyLedgerEd25519) PubKey() crypto.PubKey { + return PubKeyLedgerEd25519FromBytes(pk.Pub) } // Equals compares that two Mocks have the same data -func (pk MockPrivKeyLedger) Equals(other crypto.PrivKey) bool { - if mock, ok := other.Unwrap().(MockPrivKeyLedger); ok { +func (pk MockPrivKeyLedgerEd25519) Equals(other crypto.PrivKey) bool { + if mock, ok := other.Unwrap().(MockPrivKeyLedgerEd25519); ok { return bytes.Equal(mock.Pub[:], pk.Pub[:]) && bytes.Equal(mock.Sig[:], pk.Sig[:]) && bytes.Equal(mock.Msg, pk.Msg) @@ -227,30 +227,30 @@ func (pk MockPrivKeyLedger) Equals(other crypto.PrivKey) bool { //////////////////////////////////////////// // pubkey -// PubKeyLedger works like a normal Ed25519 except a hash before the verify bytes -type PubKeyLedger struct { +// PubKeyLedgerEd25519 works like a normal Ed25519 except a hash before the verify bytes +type PubKeyLedgerEd25519 struct { crypto.PubKeyEd25519 } -// PubKeyLedgerFromBytes creates a PubKey from the raw bytes -func PubKeyLedgerFromBytes(key [32]byte) crypto.PubKey { - return PubKeyLedger{crypto.PubKeyEd25519(key)}.Wrap() +// PubKeyLedgerEd25519FromBytes creates a PubKey from the raw bytes +func PubKeyLedgerEd25519FromBytes(key [32]byte) crypto.PubKey { + return PubKeyLedgerEd25519{crypto.PubKeyEd25519(key)}.Wrap() } // Bytes fulfils pk Interface - no data, just type info -func (pk PubKeyLedger) Bytes() []byte { +func (pk PubKeyLedgerEd25519) Bytes() []byte { return wire.BinaryBytes(pk.Wrap()) } // VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand -func (pk PubKeyLedger) VerifyBytes(msg []byte, sig crypto.Signature) bool { +func (pk PubKeyLedgerEd25519) VerifyBytes(msg []byte, sig crypto.Signature) bool { hmsg := hashMsg(msg) return pk.PubKeyEd25519.VerifyBytes(hmsg, sig) } // Equals implements PubKey interface -func (pk PubKeyLedger) Equals(other crypto.PubKey) bool { - if ledger, ok := other.Unwrap().(PubKeyLedger); ok { +func (pk PubKeyLedgerEd25519) Equals(other crypto.PubKey) bool { + if ledger, ok := other.Unwrap().(PubKeyLedgerEd25519); ok { return bytes.Equal(pk.PubKeyEd25519[:], ledger.PubKeyEd25519[:]) } return false @@ -260,24 +260,24 @@ func (pk PubKeyLedger) Equals(other crypto.PubKey) bool { func init() { crypto.PrivKeyMapper. - RegisterImplementation(&PrivKeyLedger{}, NameLedgerEd25519, TypeLedgerEd25519). - RegisterImplementation(MockPrivKeyLedger{}, "mock-ledger", 0x11) + RegisterImplementation(&PrivKeyLedgerEd25519{}, NameLedgerEd25519, TypeLedgerEd25519). + RegisterImplementation(MockPrivKeyLedgerEd25519{}, "mock-ledger", 0x11) crypto.PubKeyMapper. - RegisterImplementation(PubKeyLedger{}, NameLedgerEd25519, TypeLedgerEd25519) + RegisterImplementation(PubKeyLedgerEd25519{}, NameLedgerEd25519, TypeLedgerEd25519) } // Wrap fulfils interface for PrivKey struct -func (pk *PrivKeyLedger) Wrap() crypto.PrivKey { +func (pk *PrivKeyLedgerEd25519) Wrap() crypto.PrivKey { return crypto.PrivKey{pk} } // Wrap fulfils interface for PrivKey struct -func (pk MockPrivKeyLedger) Wrap() crypto.PrivKey { +func (pk MockPrivKeyLedgerEd25519) Wrap() crypto.PrivKey { return crypto.PrivKey{pk} } // Wrap fulfils interface for PubKey struct -func (pk PubKeyLedger) Wrap() crypto.PubKey { +func (pk PubKeyLedgerEd25519) Wrap() crypto.PubKey { return crypto.PubKey{pk} } diff --git a/nano/keys_test.go b/nano/keys_test.go index 3815d3944..15aa0d545 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -83,7 +83,7 @@ func TestRealLedger(t *testing.T) { } msg := []byte("kuhehfeohg") - priv, err := NewPrivKeyLedger() + priv, err := NewPrivKeyLedgerEd25519Ed25519() require.Nil(err, "%+v", err) pub := priv.PubKey() sig := priv.Sign(msg) @@ -123,13 +123,13 @@ func TestRealLedgerErrorHandling(t *testing.T) { // first, try to generate a key, must return an error // (no panic) - _, err := NewPrivKeyLedger() + _, err := NewPrivKeyLedgerEd25519Ed25519() require.Error(err) - led := PrivKeyLedger{} // empty + led := PrivKeyLedgerEd25519{} // empty // or with some pub key ed := crypto.GenPrivKeyEd25519() - led2 := PrivKeyLedger{CachedPubKey: ed.PubKey()} + led2 := PrivKeyLedgerEd25519{CachedPubKey: ed.PubKey()} // loading these should return errors bs := led.Bytes() From 2d0454408878ef3fa011ccc159e7bff16d13e543 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 24 Oct 2017 11:31:38 +0200 Subject: [PATCH 154/273] Addressed Buckys PR review comments --- nano/keys.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/nano/keys.go b/nano/keys.go index dc1eec950..eb531ef41 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -16,6 +16,10 @@ import ( const ( NameLedgerEd25519 = "ledger-ed25519" TypeLedgerEd25519 = 0x10 + + // Timeout is the number of seconds to wait for a response from the ledger + // if eg. waiting for user confirmation on button push + Timeout = 20 ) var device *ledger.Ledger @@ -34,7 +38,7 @@ func signLedger(device *ledger.Ledger, msg []byte) (pk crypto.PubKey, sig crypto packets := generateSignRequests(msg) for _, pack := range packets { - resp, err = device.Exchange(pack, 100) + resp, err = device.Exchange(pack, Timeout) if err != nil { return pk, sig, err } @@ -90,12 +94,19 @@ func (pk *PrivKeyLedgerEd25519) ValidateKey() error { // AssertIsPrivKeyInner fulfils PrivKey Interface func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} -// Bytes fulfils pk Interface - no data, just type info +// Bytes fulfils pk Interface - stores the cached pubkey so we can verify +// the same key when we reconnect to a ledger func (pk *PrivKeyLedgerEd25519) Bytes() []byte { return wire.BinaryBytes(pk.Wrap()) } // Sign calls the ledger and stores the pk for future use +// +// XXX/TODO: panics if there is an error communicating with the ledger. +// +// Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, +// returning an error, so this should only trigger if the privkey is held +// in memory for a while before use. func (pk *PrivKeyLedgerEd25519) Sign(msg []byte) crypto.Signature { // oh, I wish there was better error handling dev, err := getLedger() @@ -152,11 +163,11 @@ func (pk *PrivKeyLedgerEd25519) forceGetPubKey() (key crypto.PubKey, err error) return key, err } -// Equals fulfils PrivKey Interface -// TODO: needs to be fixed +// Equals fulfils PrivKey Interface - makes sure both keys refer to the +// same func (pk *PrivKeyLedgerEd25519) Equals(other crypto.PrivKey) bool { - if _, ok := other.Unwrap().(*PrivKeyLedgerEd25519); ok { - return true + if ledger, ok := other.Unwrap().(*PrivKeyLedgerEd25519); ok { + return pk.CachedPubKey.Equals(ledger.CachedPubKey) } return false } @@ -251,7 +262,7 @@ func (pk PubKeyLedgerEd25519) VerifyBytes(msg []byte, sig crypto.Signature) bool // Equals implements PubKey interface func (pk PubKeyLedgerEd25519) Equals(other crypto.PubKey) bool { if ledger, ok := other.Unwrap().(PubKeyLedgerEd25519); ok { - return bytes.Equal(pk.PubKeyEd25519[:], ledger.PubKeyEd25519[:]) + return pk.PubKeyEd25519.Equals(ledger.PubKeyEd25519.Wrap()) } return false } From 6f6bbf718e4769fb321af88533769b2c1a154b72 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 24 Oct 2017 11:56:37 +0200 Subject: [PATCH 155/273] Fix metalinter complaints --- keys/cryptostore/encoder.go | 4 ++-- keys/cryptostore/encoder_test.go | 8 ++++---- keys/cryptostore/holder_test.go | 2 +- nano/keys.go | 6 +++--- nano/sign.go | 20 -------------------- nano/sign_test.go | 20 ++++++++++++++++++++ 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 0b957d826..531a534ad 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -39,7 +39,7 @@ func (e secretbox) Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes return saltBytes, crypto.EncryptSymmetric(privKeyBytes, key), nil } -func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { +func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (crypto.PrivKey, error) { privKeyBytes := encBytes // NOTE: Some keys weren't encrypted with a passphrase and hence we have the conditional if passphrase != "" { @@ -53,7 +53,7 @@ func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } } - privKey, err = crypto.PrivKeyFromBytes(privKeyBytes) + privKey, err := crypto.PrivKeyFromBytes(privKeyBytes) if err != nil { return crypto.PrivKey{}, errors.Wrap(err, "Private Key") } diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go index 9cde95a12..614286a19 100644 --- a/keys/cryptostore/encoder_test.go +++ b/keys/cryptostore/encoder_test.go @@ -68,8 +68,8 @@ func TestSecretBoxNoPass(t *testing.T) { assert, require := assert.New(t), require.New(t) enc := cryptostore.SecretBox - key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) - require.NoError(err) + key, rerr := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + require.NoError(rerr) cases := []struct { encode string @@ -99,7 +99,7 @@ func TestSecretBoxNoPass(t *testing.T) { // now let's make sure raw bytes also work... b := key.Bytes() - pk, err := enc.Decrypt(nil, b, "") - require.Nil(err, "%+v", err) + pk, rerr := enc.Decrypt(nil, b, "") + require.NoError(rerr) assert.Equal(key, pk) } diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 899f51f02..3709cc55d 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -320,7 +320,7 @@ func TestSeedPhrase(t *testing.T) { assert.Equal(info.PubKey, newInfo.PubKey) } -func ExampleStore() { +func ExampleNew() { // Select the encryption and storage for your cryptostore cstore := cryptostore.New( cryptostore.SecretBox, diff --git a/nano/keys.go b/nano/keys.go index eb531ef41..a6d3ea8e4 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -280,15 +280,15 @@ func init() { // Wrap fulfils interface for PrivKey struct func (pk *PrivKeyLedgerEd25519) Wrap() crypto.PrivKey { - return crypto.PrivKey{pk} + return crypto.PrivKey{PrivKeyInner: pk} } // Wrap fulfils interface for PrivKey struct func (pk MockPrivKeyLedgerEd25519) Wrap() crypto.PrivKey { - return crypto.PrivKey{pk} + return crypto.PrivKey{PrivKeyInner: pk} } // Wrap fulfils interface for PubKey struct func (pk PubKeyLedgerEd25519) Wrap() crypto.PubKey { - return crypto.PubKey{pk} + return crypto.PubKey{PubKeyInner: pk} } diff --git a/nano/sign.go b/nano/sign.go index 874d134e8..c40801583 100644 --- a/nano/sign.go +++ b/nano/sign.go @@ -5,8 +5,6 @@ import ( "crypto/sha512" "github.com/pkg/errors" - - crypto "github.com/tendermint/go-crypto" ) const ( @@ -59,24 +57,6 @@ func parseDigest(resp []byte) (key, sig []byte, err error) { return key, sig, nil } -func parseEdKey(data []byte) (key crypto.PubKey, err error) { - ed := crypto.PubKeyEd25519{} - if len(data) < len(ed) { - return key, errors.Errorf("Key length too short: %d", len(data)) - } - copy(ed[:], data) - return ed.Wrap(), nil -} - -func parseSig(data []byte) (key crypto.Signature, err error) { - ed := crypto.SignatureEd25519{} - if len(data) < len(ed) { - return key, errors.Errorf("Sig length too short: %d", len(data)) - } - copy(ed[:], data) - return ed.Wrap(), nil -} - func hashMsg(data []byte) []byte { res := sha512.Sum512(data) return res[:] diff --git a/nano/sign_test.go b/nano/sign_test.go index 89bd7568e..04a6d0be7 100644 --- a/nano/sign_test.go +++ b/nano/sign_test.go @@ -4,10 +4,30 @@ import ( "encoding/hex" "testing" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" ) +func parseEdKey(data []byte) (key crypto.PubKey, err error) { + ed := crypto.PubKeyEd25519{} + if len(data) < len(ed) { + return key, errors.Errorf("Key length too short: %d", len(data)) + } + copy(ed[:], data) + return ed.Wrap(), nil +} + +func parseSig(data []byte) (key crypto.Signature, err error) { + ed := crypto.SignatureEd25519{} + if len(data) < len(ed) { + return key, errors.Errorf("Sig length too short: %d", len(data)) + } + copy(ed[:], data) + return ed.Wrap(), nil +} + func TestParseDigest(t *testing.T) { assert, require := assert.New(t), require.New(t) From 69a7b389b87f0218f367f16eb156f23867246dc0 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 24 Oct 2017 11:59:44 +0200 Subject: [PATCH 156/273] Removed keys/server as it is now in cosmos-sdk --- keys/server/README.md | 13 --- keys/server/helpers.go | 59 ------------ keys/server/keys.go | 128 ------------------------- keys/server/keys_test.go | 193 -------------------------------------- keys/server/types/keys.go | 35 ------- keys/server/valid.go | 12 --- 6 files changed, 440 deletions(-) delete mode 100644 keys/server/README.md delete mode 100644 keys/server/helpers.go delete mode 100644 keys/server/keys.go delete mode 100644 keys/server/keys_test.go delete mode 100644 keys/server/types/keys.go delete mode 100644 keys/server/valid.go diff --git a/keys/server/README.md b/keys/server/README.md deleted file mode 100644 index 032cf574e..000000000 --- a/keys/server/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Proxy Server - -This package provides all the functionality for a local http server, providing access to key management functionality (creating, listing, updating, and deleting keys). This is a nice building block for larger apps, and the HTTP handlers here can be embedded in a larger server that does nice things like signing transactions and posting them to a tendermint chain (which requires domain-knowledge of the transactions types and out of scope of this generic app). - -## Key Management - -We expose a number of methods for safely managing your keychain. If you are embedding this in a larger server, you will typically want to mount all these paths under `/keys`. - -* `POST /` - provide a name and passphrase and create a brand new key -* `GET /` - get a list of all available key names, along with their public key and address -* `GET /{name}` - get public key and address for this named key -* `PUT /{name}` - update the passphrase for the given key. requires you to correctly provide the current passphrase, as well as a new one. -* `DELETE /{name}` - permanently delete this private key. requires you to correctly provide the current passphrase diff --git a/keys/server/helpers.go b/keys/server/helpers.go deleted file mode 100644 index 3fb947316..000000000 --- a/keys/server/helpers.go +++ /dev/null @@ -1,59 +0,0 @@ -/* -package server provides http handlers to construct a server server -for key management, transaction signing, and query validation. - -Please read the README and godoc to see how to -configure the server for your application. -*/ - -package server - -import ( - "encoding/json" - "io/ioutil" - "net/http" - - "github.com/tendermint/go-crypto/keys/server/types" - data "github.com/tendermint/go-wire/data" - - "github.com/pkg/errors" -) - -func readRequest(r *http.Request, o interface{}) error { - defer r.Body.Close() - data, err := ioutil.ReadAll(r.Body) - if err != nil { - return errors.Wrap(err, "Read Request") - } - err = json.Unmarshal(data, o) - if err != nil { - return errors.Wrap(err, "Parse") - } - return validate(o) -} - -// most errors are bad input, so 406... do better.... -func writeError(w http.ResponseWriter, err error) { - // fmt.Printf("Error: %+v\n", err) - res := types.ErrorResponse{ - Code: 406, - Error: err.Error(), - } - writeCode(w, &res, 406) -} - -func writeCode(w http.ResponseWriter, o interface{}, code int) { - // two space indent to make it easier to read - data, err := data.ToJSON(o) - if err != nil { - writeError(w, err) - } else { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(code) - w.Write(data) - } -} - -func writeSuccess(w http.ResponseWriter, o interface{}) { - writeCode(w, o, 200) -} diff --git a/keys/server/keys.go b/keys/server/keys.go deleted file mode 100644 index 80852802e..000000000 --- a/keys/server/keys.go +++ /dev/null @@ -1,128 +0,0 @@ -package server - -import ( - "errors" - "net/http" - - "github.com/gorilla/mux" - keys "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/server/types" -) - -type Keys struct { - manager keys.Manager - algo string -} - -func New(manager keys.Manager, algo string) Keys { - return Keys{ - manager: manager, - algo: algo, - } -} - -func (k Keys) GenerateKey(w http.ResponseWriter, r *http.Request) { - req := types.CreateKeyRequest{ - Algo: k.algo, // default key type from cli - } - err := readRequest(r, &req) - if err != nil { - writeError(w, err) - return - } - - key, seed, err := k.manager.Create(req.Name, req.Passphrase, req.Algo) - if err != nil { - writeError(w, err) - return - } - - res := types.CreateKeyResponse{key, seed} - writeSuccess(w, &res) -} - -func (k Keys) GetKey(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - name := vars["name"] - key, err := k.manager.Get(name) - if err != nil { - writeError(w, err) - return - } - writeSuccess(w, &key) -} - -func (k Keys) ListKeys(w http.ResponseWriter, r *http.Request) { - - keys, err := k.manager.List() - if err != nil { - writeError(w, err) - return - } - writeSuccess(w, keys) -} - -func (k Keys) UpdateKey(w http.ResponseWriter, r *http.Request) { - req := types.UpdateKeyRequest{} - err := readRequest(r, &req) - if err != nil { - writeError(w, err) - return - } - - vars := mux.Vars(r) - name := vars["name"] - if name != req.Name { - writeError(w, errors.New("path and json key names don't match")) - return - } - - err = k.manager.Update(req.Name, req.OldPass, req.NewPass) - if err != nil { - writeError(w, err) - return - } - - key, err := k.manager.Get(req.Name) - if err != nil { - writeError(w, err) - return - } - writeSuccess(w, &key) -} - -func (k Keys) DeleteKey(w http.ResponseWriter, r *http.Request) { - req := types.DeleteKeyRequest{} - err := readRequest(r, &req) - if err != nil { - writeError(w, err) - return - } - - vars := mux.Vars(r) - name := vars["name"] - if name != req.Name { - writeError(w, errors.New("path and json key names don't match")) - return - } - - err = k.manager.Delete(req.Name, req.Passphrase) - if err != nil { - writeError(w, err) - return - } - - // not really an error, but something generic - resp := types.ErrorResponse{ - Success: true, - } - writeSuccess(w, &resp) -} - -func (k Keys) Register(r *mux.Router) { - r.HandleFunc("/", k.GenerateKey).Methods("POST") - r.HandleFunc("/", k.ListKeys).Methods("GET") - r.HandleFunc("/{name}", k.GetKey).Methods("GET") - r.HandleFunc("/{name}", k.UpdateKey).Methods("POST", "PUT") - r.HandleFunc("/{name}", k.DeleteKey).Methods("DELETE") -} diff --git a/keys/server/keys_test.go b/keys/server/keys_test.go deleted file mode 100644 index 2aa17753c..000000000 --- a/keys/server/keys_test.go +++ /dev/null @@ -1,193 +0,0 @@ -package server_test - -import ( - "bytes" - "encoding/json" - "net/http" - "net/http/httptest" - "testing" - - "github.com/gorilla/mux" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - keys "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/cryptostore" - "github.com/tendermint/go-crypto/keys/server" - "github.com/tendermint/go-crypto/keys/server/types" - "github.com/tendermint/go-crypto/keys/storage/memstorage" -) - -func TestKeyServer(t *testing.T) { - assert, require := assert.New(t), require.New(t) - r := setupServer() - - // let's abstract this out a bit.... - keys, code, err := listKeys(r) - require.Nil(err) - require.Equal(http.StatusOK, code) - assert.Equal(0, len(keys)) - - algo := "ed25519" - n1, n2 := "personal", "business" - p0, p1, p2 := "1234", "over10chars...", "really-secure!@#$" - - // this fails for validation - _, code, err = createKey(r, n1, p0, algo) - require.Nil(err, "%+v", err) - require.NotEqual(http.StatusOK, code) - - // new password better - key, code, err := createKey(r, n1, p1, algo) - require.Nil(err, "%+v", err) - require.Equal(http.StatusOK, code) - require.Equal(n1, key.Key.Name) - require.NotEmpty(n1, key.Seed) - - // the other one works - key2, code, err := createKey(r, n2, p2, algo) - require.Nil(err, "%+v", err) - require.Equal(http.StatusOK, code) - require.Equal(key2.Key.Name, n2) - require.NotEmpty(n2, key.Seed) - - // let's abstract this out a bit.... - keys, code, err = listKeys(r) - require.Nil(err) - require.Equal(http.StatusOK, code) - if assert.Equal(2, len(keys)) { - // in alphabetical order - assert.Equal(keys[0].Name, n2) - assert.Equal(keys[1].Name, n1) - } - - // get works - k, code, err := getKey(r, n1) - require.Nil(err, "%+v", err) - require.Equal(http.StatusOK, code) - assert.Equal(n1, k.Name) - assert.NotNil(k.Address) - assert.Equal(key.Key.Address, k.Address) - - // delete with proper key - _, code, err = deleteKey(r, n1, p1) - require.Nil(err, "%+v", err) - require.Equal(http.StatusOK, code) - - // after delete, get and list different - _, code, err = getKey(r, n1) - require.Nil(err, "%+v", err) - require.NotEqual(http.StatusOK, code) - keys, code, err = listKeys(r) - require.Nil(err, "%+v", err) - require.Equal(http.StatusOK, code) - if assert.Equal(1, len(keys)) { - assert.Equal(keys[0].Name, n2) - } - -} - -func setupServer() http.Handler { - // make the storage with reasonable defaults - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), - keys.MustLoadCodec("english"), - ) - - // build your http server - ks := server.New(cstore, "ed25519") - r := mux.NewRouter() - sk := r.PathPrefix("/keys").Subrouter() - ks.Register(sk) - return r -} - -// return data, status code, and error -func listKeys(h http.Handler) (keys.Infos, int, error) { - rr := httptest.NewRecorder() - req, err := http.NewRequest("GET", "/keys/", nil) - if err != nil { - return nil, 0, err - } - - h.ServeHTTP(rr, req) - if http.StatusOK != rr.Code { - return nil, rr.Code, nil - } - - data := keys.Infos{} - err = json.Unmarshal(rr.Body.Bytes(), &data) - return data, rr.Code, err -} - -func getKey(h http.Handler, name string) (*keys.Info, int, error) { - rr := httptest.NewRecorder() - req, err := http.NewRequest("GET", "/keys/"+name, nil) - if err != nil { - return nil, 0, err - } - - h.ServeHTTP(rr, req) - if http.StatusOK != rr.Code { - return nil, rr.Code, nil - } - - data := keys.Info{} - err = json.Unmarshal(rr.Body.Bytes(), &data) - return &data, rr.Code, err -} - -func createKey(h http.Handler, name, passphrase, algo string) (*types.CreateKeyResponse, int, error) { - rr := httptest.NewRecorder() - post := types.CreateKeyRequest{ - Name: name, - Passphrase: passphrase, - Algo: algo, - } - var b bytes.Buffer - err := json.NewEncoder(&b).Encode(&post) - if err != nil { - return nil, 0, err - } - - req, err := http.NewRequest("POST", "/keys/", &b) - if err != nil { - return nil, 0, err - } - - h.ServeHTTP(rr, req) - if http.StatusOK != rr.Code { - return nil, rr.Code, nil - } - - data := new(types.CreateKeyResponse) - err = json.Unmarshal(rr.Body.Bytes(), data) - return data, rr.Code, err -} - -func deleteKey(h http.Handler, name, passphrase string) (*types.ErrorResponse, int, error) { - rr := httptest.NewRecorder() - post := types.DeleteKeyRequest{ - Name: name, - Passphrase: passphrase, - } - var b bytes.Buffer - err := json.NewEncoder(&b).Encode(&post) - if err != nil { - return nil, 0, err - } - - req, err := http.NewRequest("DELETE", "/keys/"+name, &b) - if err != nil { - return nil, 0, err - } - - h.ServeHTTP(rr, req) - if http.StatusOK != rr.Code { - return nil, rr.Code, nil - } - - data := types.ErrorResponse{} - err = json.Unmarshal(rr.Body.Bytes(), &data) - return &data, rr.Code, err -} diff --git a/keys/server/types/keys.go b/keys/server/types/keys.go deleted file mode 100644 index 56ed60ceb..000000000 --- a/keys/server/types/keys.go +++ /dev/null @@ -1,35 +0,0 @@ -package types - -import "github.com/tendermint/go-crypto/keys" - -// CreateKeyRequest is sent to create a new key -type CreateKeyRequest struct { - Name string `json:"name" validate:"required,min=4,printascii"` - Passphrase string `json:"passphrase" validate:"required,min=10"` - Algo string `json:"algo"` -} - -// DeleteKeyRequest to destroy a key permanently (careful!) -type DeleteKeyRequest struct { - Name string `json:"name" validate:"required,min=4,printascii"` - Passphrase string `json:"passphrase" validate:"required,min=10"` -} - -// UpdateKeyRequest is sent to update the passphrase for an existing key -type UpdateKeyRequest struct { - Name string `json:"name" validate:"required,min=4,printascii"` - OldPass string `json:"passphrase" validate:"required,min=10"` - NewPass string `json:"new_passphrase" validate:"required,min=10"` -} - -// ErrorResponse is returned for 4xx and 5xx errors -type ErrorResponse struct { - Success bool `json:"success"` - Error string `json:"error"` // error message if Success is false - Code int `json:"code"` // error code if Success is false -} - -type CreateKeyResponse struct { - Key keys.Info `json:"key"` - Seed string `json:"seed_phrase"` -} diff --git a/keys/server/valid.go b/keys/server/valid.go deleted file mode 100644 index 50b51e21b..000000000 --- a/keys/server/valid.go +++ /dev/null @@ -1,12 +0,0 @@ -package server - -import ( - "github.com/pkg/errors" - "gopkg.in/go-playground/validator.v9" -) - -var v = validator.New() - -func validate(req interface{}) error { - return errors.Wrap(v.Struct(req), "Validate") -} From 0219ba2a63e2dcf027b8af8741900409a962224b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 24 Oct 2017 12:14:20 +0200 Subject: [PATCH 157/273] Fix bug introduced by metalinting... --- keys/cryptostore/encoder.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 531a534ad..31f49c3f7 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -39,11 +39,12 @@ func (e secretbox) Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes return saltBytes, crypto.EncryptSymmetric(privKeyBytes, key), nil } -func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (crypto.PrivKey, error) { +func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { privKeyBytes := encBytes // NOTE: Some keys weren't encrypted with a passphrase and hence we have the conditional if passphrase != "" { - key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) + var key []byte + key, err = bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) if err != nil { return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } @@ -53,7 +54,7 @@ func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } } - privKey, err := crypto.PrivKeyFromBytes(privKeyBytes) + privKey, err = crypto.PrivKeyFromBytes(privKeyBytes) if err != nil { return crypto.PrivKey{}, errors.Wrap(err, "Private Key") } From dfc4cdd2d71513e4a9922d679c74f36357c4c862 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 24 Oct 2017 11:48:13 +0200 Subject: [PATCH 158/273] Parameterize and lower bcrypt cost --- keys/cryptostore/encoder.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 31f49c3f7..99241f1b7 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -7,6 +7,20 @@ import ( "github.com/tendermint/go-crypto/bcrypt" ) +const ( + // BcryptCost is as parameter to increase the resistance of the + // encoded keys to brute force password guessing + // + // Jae: 14 is good today (2016) + // + // Ethan: loading the key (at each signing) takes a second on my desktop, + // this is hard for laptops and deadly for mobile. You can raise it again, + // but for now, I will make this usable + // + // TODO: review value + BCryptCost = 12 +) + var ( // SecretBox uses the algorithm from NaCL to store secrets securely SecretBox Encoder = secretbox{} @@ -30,7 +44,7 @@ func (e secretbox) Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes } saltBytes = crypto.CRandBytes(16) - key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) + key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), BCryptCost) if err != nil { return nil, nil, errors.Wrap(err, "Couldn't generate bcrypt key from passphrase.") } @@ -44,7 +58,7 @@ func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) // NOTE: Some keys weren't encrypted with a passphrase and hence we have the conditional if passphrase != "" { var key []byte - key, err = bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) + key, err = bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), BCryptCost) if err != nil { return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } From 3df2ca128d12a20c63fb05fd20d37132b7576760 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Wed, 25 Oct 2017 19:56:08 -0700 Subject: [PATCH 159/273] make PrivateKey + Signature comparisons use constant time comparisons Fixes https://github.com/tendermint/go-crypto/issues/43 Avoid susceptibility to timing/side channel attacks by ensuring that private key and signature comparisons use `subtle.ConstantTimeCompare` instead of `bytes.Equal` --- priv_key.go | 14 +++++++++++--- signature.go | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/priv_key.go b/priv_key.go index 0c6bd2ae7..456985615 100644 --- a/priv_key.go +++ b/priv_key.go @@ -1,7 +1,7 @@ package crypto import ( - "bytes" + "crypto/subtle" secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" @@ -57,7 +57,11 @@ func (privKey PrivKeyEd25519) PubKey() PubKey { func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { if otherEd, ok := other.Unwrap().(PrivKeyEd25519); ok { - return bytes.Equal(privKey[:], otherEd[:]) + // It is essential that we constant time compare + // private keys and signatures instead of bytes.Equal, + // to avoid susceptibility to timing/side channel attacks. + // See Issue https://github.com/tendermint/go-crypto/issues/43 + return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 0 } else { return false } @@ -144,7 +148,11 @@ func (privKey PrivKeySecp256k1) PubKey() PubKey { func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { if otherSecp, ok := other.Unwrap().(PrivKeySecp256k1); ok { - return bytes.Equal(privKey[:], otherSecp[:]) + // It is essential that we constant time compare + // private keys and signatures instead of bytes.Equal, + // to avoid susceptibility to timing/side channel attacks. + // See Issue https://github.com/tendermint/go-crypto/issues/43 + return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 0 } else { return false } diff --git a/signature.go b/signature.go index 5b1d6cb05..fb07aba96 100644 --- a/signature.go +++ b/signature.go @@ -1,7 +1,7 @@ package crypto import ( - "bytes" + "crypto/subtle" "fmt" "github.com/tendermint/go-wire" @@ -46,7 +46,11 @@ func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fing func (sig SignatureEd25519) Equals(other Signature) bool { if otherEd, ok := other.Unwrap().(SignatureEd25519); ok { - return bytes.Equal(sig[:], otherEd[:]) + // It is essential that we constant time compare + // private keys and signatures instead of bytes.Equal, + // to avoid susceptibility to timing/side channel attacks. + // See Issue https://github.com/tendermint/go-crypto/issues/43 + return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 0 } else { return false } @@ -82,7 +86,11 @@ func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fi func (sig SignatureSecp256k1) Equals(other Signature) bool { if otherEd, ok := other.Unwrap().(SignatureSecp256k1); ok { - return bytes.Equal(sig[:], otherEd[:]) + // It is essential that we constant time compare + // private keys and signatures instead of bytes.Equal, + // to avoid susceptibility to timing/side channel attacks. + // See Issue https://github.com/tendermint/go-crypto/issues/43 + return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 0 } else { return false } From 5d8890530a26d86cb7b7baa179473ebac60e07e6 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 26 Oct 2017 12:00:36 +0200 Subject: [PATCH 160/273] Update glide deps, nano/hid for osx/golang1.9 --- glide.lock | 32 +++++++------------------------- glide.yaml | 6 ------ 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/glide.lock b/glide.lock index 29124c3db..7df64f79f 100644 --- a/glide.lock +++ b/glide.lock @@ -1,26 +1,20 @@ -hash: a2243bfd21937edf660778300855e7cb72185164641cb278dbf0c220e8a0f60a -updated: 2017-10-23T17:21:02.40831023+02:00 +hash: 6e06a42eafe0aeff112cee86aef6b2cab0e2f62c2e6bfccfb629aa22f6b62773 +updated: 2017-10-26T11:57:48.785457739+02:00 imports: -- name: github.com/bgentry/speakeasy - version: 4aabc24848ce5fd31929f7d1e4ea74d3709c14cd - name: github.com/btcsuite/btcd version: b8df516b4b267acf2de46be593a9d948d1d2c420 subpackages: - btcec - - chaincfg - - chaincfg/chainhash - - wire - name: github.com/btcsuite/btcutil version: 66871daeb12123ece012a9628d2798d01195c4b3 subpackages: - base58 - - hdkeychain - name: github.com/btcsuite/fastsha256 version: 637e656429416087660c84436a2a035d69d54e2e +- name: github.com/ethanfrey/hid + version: f379bda1dbc8e79333b04563f71a12e86206efe5 - name: github.com/ethanfrey/ledger - version: 5e432577be582bd18a3b4a9cd75dae7a317ade36 -- name: github.com/flynn/hid - version: ed06a31c6245d4552e8dbba7e32e5b010b875d65 + version: 3689ce9be93e1a5bef836b1cc2abb18381c79176 - name: github.com/go-kit/kit version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 subpackages: @@ -37,34 +31,24 @@ imports: version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 -- name: github.com/gorilla/context - version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 -- name: github.com/gorilla/handlers - version: a4043c62cc2329bacda331d33fc908ab11ef0ec3 -- name: github.com/gorilla/mux - version: bcd8bc72b08df0f70df986b97f95590779502d31 - name: github.com/howeyc/crc16 version: 58da63c846043d0bea709c8d47039df06577d6d9 - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/spf13/cobra - version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77 -- name: github.com/spf13/viper - version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2 - name: github.com/tendermint/ed25519 version: 1f52c6f8b8a5c7908aff4497c186af344b428925 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 55ae61f1fc83cfaa57ab7d54250d7a1a2be0b83c + version: 3180c867ca52bcd9ba6c905ce63613f8d8e9837c subpackages: - data - data/base58 - name: github.com/tendermint/tmlibs - version: 8e5266a9ef2527e68a1571f932db8228a331b556 + version: b30e3ba26d4077edeed83c50a4e0c38b0ec9ddb3 subpackages: - common - log @@ -83,8 +67,6 @@ imports: - name: gopkg.in/go-playground/validator.v9 version: 6d8c18553ea1ac493d049edd6f102f52e618f085 testImports: -- name: github.com/cmars/basen - version: fe3947df716ebfda9847eb1b9a48f9592e06478c - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: diff --git a/glide.yaml b/glide.yaml index 9f20ddefc..2f3e72471 100644 --- a/glide.yaml +++ b/glide.yaml @@ -22,13 +22,7 @@ import: - nacl/secretbox - openpgp/armor - ripemd160 -- package: github.com/bgentry/speakeasy -- package: github.com/gorilla/handlers -- package: github.com/gorilla/mux - package: github.com/pkg/errors -- package: github.com/spf13/cobra -- package: github.com/spf13/viper -- package: gopkg.in/go-playground/validator.v9 - package: github.com/howeyc/crc16 - package: github.com/ethanfrey/ledger testImport: From 57346134a57c16559ce009464a96dfd37547a06c Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 26 Oct 2017 16:43:32 -0400 Subject: [PATCH 161/273] keys: transactions.go -> types.go --- keys/storage.go | 10 ---------- keys/{transactions.go => types.go} | 9 +++++++++ 2 files changed, 9 insertions(+), 10 deletions(-) delete mode 100644 keys/storage.go rename keys/{transactions.go => types.go} (91%) diff --git a/keys/storage.go b/keys/storage.go deleted file mode 100644 index 0aba4ebdb..000000000 --- a/keys/storage.go +++ /dev/null @@ -1,10 +0,0 @@ -package keys - -// Storage has many implementation, based on security and sharing requirements -// like disk-backed, mem-backed, vault, db, etc. -type Storage interface { - Put(name string, salt []byte, key []byte, info Info) error - Get(name string) (salt []byte, key []byte, info Info, err error) - List() (Infos, error) - Delete(name string) error -} diff --git a/keys/transactions.go b/keys/types.go similarity index 91% rename from keys/transactions.go rename to keys/types.go index 1834ada26..008a6f7ae 100644 --- a/keys/transactions.go +++ b/keys/types.go @@ -9,6 +9,15 @@ import ( data "github.com/tendermint/go-wire/data" ) +// Storage has many implementation, based on security and sharing requirements +// like disk-backed, mem-backed, vault, db, etc. +type Storage interface { + Put(name string, salt []byte, key []byte, info Info) error + Get(name string) (salt []byte, key []byte, info Info, err error) + List() (Infos, error) + Delete(name string) error +} + // Info is the public information about a key type Info struct { Name string `json:"name"` From 944d36ab00d5f82ef590ea515d437134e2e161ad Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 12:04:31 -0400 Subject: [PATCH 162/273] changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63d4af1d8..99f1ea7da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.4.0 (October 27, 2017) + +BREAKING CHANGES: + +- `keys`: use bcrypt plus salt + +FEATURES: + +- add support for signing via Ledger Nano + ## 0.3.0 (September 22, 2017) BREAKING CHANGES: From ad31f6a95327a1997e1c75fd57645ee5dd731332 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 27 Oct 2017 18:46:21 +0200 Subject: [PATCH 163/273] osx + hid = <3 --- glide.lock | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/glide.lock b/glide.lock index 7df64f79f..096ec5c15 100644 --- a/glide.lock +++ b/glide.lock @@ -1,22 +1,20 @@ hash: 6e06a42eafe0aeff112cee86aef6b2cab0e2f62c2e6bfccfb629aa22f6b62773 -updated: 2017-10-26T11:57:48.785457739+02:00 +updated: 2017-10-27T18:45:18.350198941+02:00 imports: - name: github.com/btcsuite/btcd - version: b8df516b4b267acf2de46be593a9d948d1d2c420 + version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e subpackages: - btcec - name: github.com/btcsuite/btcutil version: 66871daeb12123ece012a9628d2798d01195c4b3 subpackages: - base58 -- name: github.com/btcsuite/fastsha256 - version: 637e656429416087660c84436a2a035d69d54e2e - name: github.com/ethanfrey/hid - version: f379bda1dbc8e79333b04563f71a12e86206efe5 + version: 660bb717bd4e7cbcdf0f7cd5cadf1cb2e4be452a - name: github.com/ethanfrey/ledger - version: 3689ce9be93e1a5bef836b1cc2abb18381c79176 + version: 23a7bb9d74bc83a862fcb4bddde24215b2295ad9 - name: github.com/go-kit/kit - version: d67bb4c202e3b91377d1079b110a6c9ce23ab2f8 + version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c subpackages: - log - log/level @@ -24,36 +22,36 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-playground/locales - version: 1e5f1161c6416a5ff48840eb8724a394e48cc534 + version: e4cbcb5d0652150d40ad0646651076b6bd2be4f6 subpackages: - currency - name: github.com/go-playground/universal-translator version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack - version: 100eb0c0a9c5b306ca2fb4f165df21d80ada4b82 + version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf - name: github.com/howeyc/crc16 - version: 58da63c846043d0bea709c8d47039df06577d6d9 + version: 96a97a1abb579c7ff1a8ffa77f2e72d1c314b57f - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/tendermint/ed25519 - version: 1f52c6f8b8a5c7908aff4497c186af344b428925 + version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 3180c867ca52bcd9ba6c905ce63613f8d8e9837c + version: 8ee84b5b2581530168daf66fc89c548d27403c57 subpackages: - data - data/base58 - name: github.com/tendermint/tmlibs - version: b30e3ba26d4077edeed83c50a4e0c38b0ec9ddb3 + version: 092eb701c7276907cdbed258750e22ce895b6735 subpackages: - common - log - name: golang.org/x/crypto - version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e + version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 subpackages: - bcrypt - blowfish @@ -65,7 +63,7 @@ imports: - ripemd160 - salsa20/salsa - name: gopkg.in/go-playground/validator.v9 - version: 6d8c18553ea1ac493d049edd6f102f52e618f085 + version: 1304298bf10d085adec514b076772a79c9cadb6b testImports: - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 From 8630b724b2f267940f696885cebda954f9eaa7cd Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 12:57:26 -0400 Subject: [PATCH 164/273] version and changelog --- CHANGELOG.md | 4 ++++ version.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99f1ea7da..64dc9998b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ FEATURES: - add support for signing via Ledger Nano +IMPROVEMENTS: + +- linting and comments + ## 0.3.0 (September 22, 2017) BREAKING CHANGES: diff --git a/version.go b/version.go index 23d065446..585d7e0d7 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.3.0" +const Version = "0.4.0" From 87badb090ff941c5359b4017705f67976e8c3ca2 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 21:58:02 -0400 Subject: [PATCH 165/273] Revert "Parameterize and lower bcrypt cost" This reverts commit dfc4cdd2d71513e4a9922d679c74f36357c4c862. --- keys/cryptostore/encoder.go | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 99241f1b7..31f49c3f7 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -7,20 +7,6 @@ import ( "github.com/tendermint/go-crypto/bcrypt" ) -const ( - // BcryptCost is as parameter to increase the resistance of the - // encoded keys to brute force password guessing - // - // Jae: 14 is good today (2016) - // - // Ethan: loading the key (at each signing) takes a second on my desktop, - // this is hard for laptops and deadly for mobile. You can raise it again, - // but for now, I will make this usable - // - // TODO: review value - BCryptCost = 12 -) - var ( // SecretBox uses the algorithm from NaCL to store secrets securely SecretBox Encoder = secretbox{} @@ -44,7 +30,7 @@ func (e secretbox) Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes } saltBytes = crypto.CRandBytes(16) - key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), BCryptCost) + key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) if err != nil { return nil, nil, errors.Wrap(err, "Couldn't generate bcrypt key from passphrase.") } @@ -58,7 +44,7 @@ func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) // NOTE: Some keys weren't encrypted with a passphrase and hence we have the conditional if passphrase != "" { var key []byte - key, err = bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), BCryptCost) + key, err = bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) if err != nil { return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } From 64056182206e90f16833c1a270414cf82c1856d6 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 22:02:44 -0400 Subject: [PATCH 166/273] Revert "Upgrade keys to use bcrypt with salts (#38)" This reverts commit 8e7f0e7701f92206679ad093d013b9b162427631. --- keys/cryptostore/enc_storage.go | 8 +- keys/cryptostore/encoder.go | 60 ++++++-------- keys/cryptostore/encoder_test.go | 22 +++--- keys/cryptostore/generator.go | 1 - keys/cryptostore/holder.go | 18 ++--- keys/cryptostore/holder_test.go | 10 +-- keys/cryptostore/storage_test.go | 2 +- keys/storage/filestorage/main.go | 108 ++++++-------------------- keys/storage/filestorage/main_test.go | 13 ++-- keys/storage/memstorage/main.go | 12 ++- keys/storage/memstorage/main_test.go | 13 ++-- 11 files changed, 94 insertions(+), 173 deletions(-) diff --git a/keys/cryptostore/enc_storage.go b/keys/cryptostore/enc_storage.go index e0c7e59a3..daeb220b5 100644 --- a/keys/cryptostore/enc_storage.go +++ b/keys/cryptostore/enc_storage.go @@ -12,21 +12,21 @@ type encryptedStorage struct { } func (es encryptedStorage) Put(name, pass string, key crypto.PrivKey) error { - saltBytes, encBytes, err := es.coder.Encrypt(key, pass) + secret, err := es.coder.Encrypt(key, pass) if err != nil { return err } ki := info(name, key) - return es.store.Put(name, saltBytes, encBytes, ki) + return es.store.Put(name, secret, ki) } func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.Info, error) { - saltBytes, encBytes, info, err := es.store.Get(name) + secret, info, err := es.store.Get(name) if err != nil { return crypto.PrivKey{}, info, err } - key, err := es.coder.Decrypt(saltBytes, encBytes, pass) + key, err := es.coder.Decrypt(secret, pass) return key, info, err } diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go index 31f49c3f7..31cbc2e54 100644 --- a/keys/cryptostore/encoder.go +++ b/keys/cryptostore/encoder.go @@ -2,9 +2,7 @@ package cryptostore import ( "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/bcrypt" ) var ( @@ -18,55 +16,45 @@ var ( // // This should use a well-designed symetric encryption algorithm type Encoder interface { - Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte, err error) - Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) + Encrypt(key crypto.PrivKey, pass string) ([]byte, error) + Decrypt(data []byte, pass string) (crypto.PrivKey, error) } -type secretbox struct{} +func secret(passphrase string) []byte { + // TODO: Sha256(Bcrypt(passphrase)) + return crypto.Sha256([]byte(passphrase)) +} -func (e secretbox) Encrypt(privKey crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte, err error) { - if passphrase == "" { - return nil, privKey.Bytes(), nil - } +type secretbox struct{} - saltBytes = crypto.CRandBytes(16) - key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) - if err != nil { - return nil, nil, errors.Wrap(err, "Couldn't generate bcrypt key from passphrase.") +func (e secretbox) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { + if pass == "" { + return key.Bytes(), nil } - key = crypto.Sha256(key) // Get 32 bytes - privKeyBytes := privKey.Bytes() - return saltBytes, crypto.EncryptSymmetric(privKeyBytes, key), nil + s := secret(pass) + cipher := crypto.EncryptSymmetric(key.Bytes(), s) + return cipher, nil } -func (e secretbox) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { - privKeyBytes := encBytes - // NOTE: Some keys weren't encrypted with a passphrase and hence we have the conditional - if passphrase != "" { - var key []byte - key, err = bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 14) // TODO parameterize. 14 is good today (2016) +func (e secretbox) Decrypt(data []byte, pass string) (key crypto.PrivKey, err error) { + private := data + if pass != "" { + s := secret(pass) + private, err = crypto.DecryptSymmetric(data, s) if err != nil { return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") } - key = crypto.Sha256(key) // Get 32 bytes - privKeyBytes, err = crypto.DecryptSymmetric(encBytes, key) - if err != nil { - return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") - } - } - privKey, err = crypto.PrivKeyFromBytes(privKeyBytes) - if err != nil { - return crypto.PrivKey{}, errors.Wrap(err, "Private Key") } - return privKey, nil + key, err = crypto.PrivKeyFromBytes(private) + return key, errors.Wrap(err, "Invalid Passphrase") } type noop struct{} -func (n noop) Encrypt(key crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte, err error) { - return []byte{}, key.Bytes(), nil +func (n noop) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { + return key.Bytes(), nil } -func (n noop) Decrypt(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { - return crypto.PrivKeyFromBytes(encBytes) +func (n noop) Decrypt(data []byte, pass string) (crypto.PrivKey, error) { + return crypto.PrivKeyFromBytes(data) } diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go index 614286a19..9a0757b73 100644 --- a/keys/cryptostore/encoder_test.go +++ b/keys/cryptostore/encoder_test.go @@ -20,22 +20,22 @@ func TestNoopEncoder(t *testing.T) { key2, err := cryptostore.GenSecp256k1.Generate(cmn.RandBytes(16)) require.NoError(err) - _, b, err := noop.Encrypt(key, "encode") + b, err := noop.Encrypt(key, "encode") require.Nil(err) assert.NotEmpty(b) - _, b2, err := noop.Encrypt(key2, "encode") + b2, err := noop.Encrypt(key2, "encode") require.Nil(err) assert.NotEmpty(b2) assert.NotEqual(b, b2) // note the decode with a different password works - not secure! - pk, err := noop.Decrypt(nil, b, "decode") + pk, err := noop.Decrypt(b, "decode") require.Nil(err) require.NotNil(pk) assert.Equal(key, pk) - pk2, err := noop.Decrypt(nil, b2, "kggugougp") + pk2, err := noop.Decrypt(b2, "kggugougp") require.Nil(err) require.NotNil(pk2) assert.Equal(key2, pk2) @@ -49,17 +49,17 @@ func TestSecretBox(t *testing.T) { require.NoError(err) pass := "some-special-secret" - s, b, err := enc.Encrypt(key, pass) + b, err := enc.Encrypt(key, pass) require.Nil(err) assert.NotEmpty(b) // decoding with a different pass is an error - pk, err := enc.Decrypt(s, b, "decode") + pk, err := enc.Decrypt(b, "decode") require.NotNil(err) require.True(pk.Empty()) // but decoding with the same passphrase gets us our key - pk, err = enc.Decrypt(s, b, pass) + pk, err = enc.Decrypt(b, pass) require.Nil(err) assert.Equal(key, pk) } @@ -84,11 +84,11 @@ func TestSecretBoxNoPass(t *testing.T) { } for i, tc := range cases { - s, b, err := enc.Encrypt(key, tc.encode) + b, err := enc.Encrypt(key, tc.encode) require.Nil(err, "%d: %+v", i, err) assert.NotEmpty(b, "%d", i) - pk, err := enc.Decrypt(s, b, tc.decode) + pk, err := enc.Decrypt(b, tc.decode) if tc.valid { require.Nil(err, "%d: %+v", i, err) assert.Equal(key, pk, "%d", i) @@ -99,7 +99,7 @@ func TestSecretBoxNoPass(t *testing.T) { // now let's make sure raw bytes also work... b := key.Bytes() - pk, rerr := enc.Decrypt(nil, b, "") - require.NoError(rerr) + pk, err := enc.Decrypt(b, "") + require.Nil(err, "%+v", err) assert.Equal(key, pk) } diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go index 65cc8e58b..81277eda9 100644 --- a/keys/cryptostore/generator.go +++ b/keys/cryptostore/generator.go @@ -2,7 +2,6 @@ package cryptostore import ( "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto/nano" ) diff --git a/keys/cryptostore/holder.go b/keys/cryptostore/holder.go index 923190c1b..7e89dda38 100644 --- a/keys/cryptostore/holder.go +++ b/keys/cryptostore/holder.go @@ -95,7 +95,7 @@ func (s Manager) List() (keys.Infos, error) { // Get returns the public information about one key func (s Manager) Get(name string) (keys.Info, error) { - _, _, info, err := s.es.store.Get(name) + _, info, err := s.es.store.Get(name) return info, err } @@ -119,23 +119,21 @@ func (s Manager) Sign(name, passphrase string, tx keys.Signable) error { // // This is designed to copy from one device to another, or provide backups // during version updates. -// TODO: How to handle Export with salt? -func (s Manager) Export(name, oldpass, transferpass string) (salt, data []byte, err error) { +func (s Manager) Export(name, oldpass, transferpass string) ([]byte, error) { key, _, err := s.es.Get(name, oldpass) if err != nil { - return nil, nil, err + return nil, err } - salt, data, err = s.es.coder.Encrypt(key, transferpass) - return salt, data, err + res, err := s.es.coder.Encrypt(key, transferpass) + return res, err } // Import accepts bytes generated by Export along with the same transferpass -// If they are valid, it stores the key under the given name with the +// If they are valid, it stores the password under the given name with the // new passphrase. -// TODO: How to handle Import with salt? -func (s Manager) Import(name, newpass, transferpass string, salt, data []byte) error { - key, err := s.es.coder.Decrypt(salt, data, transferpass) +func (s Manager) Import(name, newpass, transferpass string, data []byte) error { + key, err := s.es.coder.Decrypt(data, transferpass) if err != nil { return err } diff --git a/keys/cryptostore/holder_test.go b/keys/cryptostore/holder_test.go index 3709cc55d..a9056f0de 100644 --- a/keys/cryptostore/holder_test.go +++ b/keys/cryptostore/holder_test.go @@ -232,7 +232,7 @@ func TestImportUnencrypted(t *testing.T) { pass := "top-secret" // import raw bytes - err = cstore.Import(name, pass, "", nil, key.Bytes()) + err = cstore.Import(name, pass, "", key.Bytes()) require.Nil(err, "%+v", err) // make sure the address matches @@ -273,15 +273,15 @@ func TestAdvancedKeyManagement(t *testing.T) { assertPassword(assert, cstore, n1, p2, p1) // exporting requires the proper name and passphrase - _, _, err = cstore.Export(n2, p2, pt) + _, err = cstore.Export(n2, p2, pt) assert.NotNil(err) - _, _, err = cstore.Export(n1, p1, pt) + _, err = cstore.Export(n1, p1, pt) assert.NotNil(err) - salt, exported, err := cstore.Export(n1, p2, pt) + exported, err := cstore.Export(n1, p2, pt) require.Nil(err, "%+v", err) // import fails on bad transfer pass - err = cstore.Import(n2, p3, p2, salt, exported) + err = cstore.Import(n2, p3, p2, exported) assert.NotNil(err) } diff --git a/keys/cryptostore/storage_test.go b/keys/cryptostore/storage_test.go index 23931c294..6d475fdc9 100644 --- a/keys/cryptostore/storage_test.go +++ b/keys/cryptostore/storage_test.go @@ -5,9 +5,9 @@ import ( "github.com/stretchr/testify/assert" + crypto "github.com/tendermint/go-crypto" cmn "github.com/tendermint/tmlibs/common" - crypto "github.com/tendermint/go-crypto" keys "github.com/tendermint/go-crypto/keys" ) diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go index 2bd4dcc1f..1f9702995 100644 --- a/keys/storage/filestorage/main.go +++ b/keys/storage/filestorage/main.go @@ -6,7 +6,6 @@ like standard ssh key storage. package filestorage import ( - "encoding/hex" "fmt" "io/ioutil" "os" @@ -14,13 +13,11 @@ import ( "strings" "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" keys "github.com/tendermint/go-crypto/keys" ) const ( - // BlockType is the type of block. BlockType = "Tendermint Light Client" // PrivExt is the extension for private keys. @@ -33,7 +30,6 @@ const ( dirPerm = os.FileMode(0700) ) -// FileStore is a file-based key storage with tight permissions. type FileStore struct { keyDir string } @@ -44,11 +40,9 @@ type FileStore struct { // be created if it doesn't exist already. func New(dir string) FileStore { err := os.MkdirAll(dir, dirPerm) - if err != nil { panic(err) } - return FileStore{dir} } @@ -57,7 +51,7 @@ var _ keys.Storage = FileStore{} // Put creates two files, one with the public info as json, the other // with the (encoded) private key as gpg ascii-armor style -func (s FileStore) Put(name string, salt, key []byte, info keys.Info) error { +func (s FileStore) Put(name string, key []byte, info keys.Info) error { pub, priv := s.nameToPaths(name) // write public info @@ -67,22 +61,22 @@ func (s FileStore) Put(name string, salt, key []byte, info keys.Info) error { } // write private info - return write(priv, name, salt, key) + return write(priv, name, key) } // Get loads the info and (encoded) private key from the directory // It uses `name` to generate the filename, and returns an error if the // files don't exist or are in the incorrect format -func (s FileStore) Get(name string) (salt []byte, key []byte, info keys.Info, err error) { +func (s FileStore) Get(name string) ([]byte, keys.Info, error) { pub, priv := s.nameToPaths(name) - info, err = readInfo(pub) + info, err := readInfo(pub) if err != nil { - return nil, nil, info, err + return nil, info, err } - salt, key, _, err = read(priv) - return salt, key, info.Format(), err + key, _, err := read(priv) + return key, info.Format(), err } // List parses the key directory for public info and returns a list of @@ -121,117 +115,63 @@ func (s FileStore) List() (keys.Infos, error) { func (s FileStore) Delete(name string) error { pub, priv := s.nameToPaths(name) err := os.Remove(priv) - if err != nil { return errors.Wrap(err, "Deleting Private Key") } - err = os.Remove(pub) - return errors.Wrap(err, "Deleting Public Key") } func (s FileStore) nameToPaths(name string) (pub, priv string) { privName := fmt.Sprintf("%s.%s", name, PrivExt) pubName := fmt.Sprintf("%s.%s", name, PubExt) - return path.Join(s.keyDir, pubName), path.Join(s.keyDir, privName) } -func readInfo(path string) (info keys.Info, err error) { - f, err := os.Open(path) - if err != nil { - return info, errors.Wrap(err, "Reading data") - } - defer f.Close() - - d, err := ioutil.ReadAll(f) - if err != nil { - return info, errors.Wrap(err, "Reading data") - } +func writeInfo(path string, info keys.Info) error { + return write(path, info.Name, info.PubKey.Bytes()) +} - block, headers, key, err := crypto.DecodeArmor(string(d)) +func readInfo(path string) (info keys.Info, err error) { + var data []byte + data, info.Name, err = read(path) if err != nil { - return info, errors.Wrap(err, "Invalid Armor") + return } - - if block != BlockType { - return info, errors.Errorf("Unknown key type: %s", block) - } - - pk, _ := crypto.PubKeyFromBytes(key) - info.Name = headers["name"] + pk, err := crypto.PubKeyFromBytes(data) info.PubKey = pk - - return info, nil + return } -func read(path string) (salt, key []byte, name string, err error) { +func read(path string) ([]byte, string, error) { f, err := os.Open(path) if err != nil { - return nil, nil, "", errors.Wrap(err, "Reading data") + return nil, "", errors.Wrap(err, "Reading data") } defer f.Close() d, err := ioutil.ReadAll(f) if err != nil { - return nil, nil, "", errors.Wrap(err, "Reading data") + return nil, "", errors.Wrap(err, "Reading data") } - block, headers, key, err := crypto.DecodeArmor(string(d)) if err != nil { - return nil, nil, "", errors.Wrap(err, "Invalid Armor") + return nil, "", errors.Wrap(err, "Invalid Armor") } - if block != BlockType { - return nil, nil, "", errors.Errorf("Unknown key type: %s", block) - } - - if headers["kdf"] != "bcrypt" { - return nil, nil, "", errors.Errorf("Unrecognized KDF type: %v", headers["kdf"]) + return nil, "", errors.Errorf("Unknown key type: %s", block) } - - if headers["salt"] == "" { - return nil, nil, "", errors.Errorf("Missing salt bytes") - } - - salt, err = hex.DecodeString(headers["salt"]) - if err != nil { - return nil, nil, "", errors.Errorf("Error decoding salt: %v", err.Error()) - } - - return salt, key, headers["name"], nil + return key, headers["name"], nil } -func writeInfo(path string, info keys.Info) error { +func write(path, name string, key []byte) error { f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) if err != nil { return errors.Wrap(err, "Writing data") } defer f.Close() - - headers := map[string]string{"name": info.Name} - text := crypto.EncodeArmor(BlockType, headers, info.PubKey.Bytes()) - _, err = f.WriteString(text) - - return errors.Wrap(err, "Writing data") -} - -func write(path, name string, salt, key []byte) error { - f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) - if err != nil { - return errors.Wrap(err, "Writing data") - } - defer f.Close() - - headers := map[string]string{ - "name": name, - "kdf": "bcrypt", - "salt": fmt.Sprintf("%X", salt), - } - + headers := map[string]string{"name": name} text := crypto.EncodeArmor(BlockType, headers, key) _, err = f.WriteString(text) - return errors.Wrap(err, "Writing data") } diff --git a/keys/storage/filestorage/main_test.go b/keys/storage/filestorage/main_test.go index bed46ab1f..28c950c2c 100644 --- a/keys/storage/filestorage/main_test.go +++ b/keys/storage/filestorage/main_test.go @@ -22,7 +22,6 @@ func TestBasicCRUD(t *testing.T) { name := "bar" key := []byte("secret-key-here") - salt := []byte("salt-here") pubkey := crypto.GenPrivKeyEd25519().PubKey() info := keys.Info{ Name: name, @@ -30,7 +29,7 @@ func TestBasicCRUD(t *testing.T) { } // No data: Get and Delete return nothing - _, _, _, err = store.Get(name) + _, _, err = store.Get(name) assert.NotNil(err) err = store.Delete(name) assert.NotNil(err) @@ -40,14 +39,14 @@ func TestBasicCRUD(t *testing.T) { assert.Empty(l) // Putting the key in the store must work - err = store.Put(name, salt, key, info) + err = store.Put(name, key, info) assert.Nil(err) // But a second time is a failure - err = store.Put(name, salt, key, info) + err = store.Put(name, key, info) assert.NotNil(err) // Now, we can get and list properly - _, k, i, err := store.Get(name) + k, i, err := store.Get(name) require.Nil(err, "%+v", err) assert.Equal(key, k) assert.Equal(info.Name, i.Name) @@ -59,7 +58,7 @@ func TestBasicCRUD(t *testing.T) { assert.Equal(i, l[0]) // querying a non-existent key fails - _, _, _, err = store.Get("badname") + _, _, err = store.Get("badname") assert.NotNil(err) // We can only delete once @@ -69,7 +68,7 @@ func TestBasicCRUD(t *testing.T) { assert.NotNil(err) // and then Get and List don't work - _, _, _, err = store.Get(name) + _, _, err = store.Get(name) assert.NotNil(err) // List returns empty list l, err = store.List() diff --git a/keys/storage/memstorage/main.go b/keys/storage/memstorage/main.go index 516aa40b8..a988fe0ff 100644 --- a/keys/storage/memstorage/main.go +++ b/keys/storage/memstorage/main.go @@ -7,13 +7,11 @@ package memstorage import ( "github.com/pkg/errors" - keys "github.com/tendermint/go-crypto/keys" ) type data struct { info keys.Info - salt []byte key []byte } @@ -29,22 +27,22 @@ var _ keys.Storage = MemStore{} // Put adds the given key, returns an error if it another key // is already stored under this name -func (s MemStore) Put(name string, salt, key []byte, info keys.Info) error { +func (s MemStore) Put(name string, key []byte, info keys.Info) error { if _, ok := s[name]; ok { return errors.Errorf("Key named '%s' already exists", name) } - s[name] = data{info, salt, key} + s[name] = data{info, key} return nil } // Get returns the key stored under the name, or returns an error if not present -func (s MemStore) Get(name string) (salt, key []byte, info keys.Info, err error) { +func (s MemStore) Get(name string) ([]byte, keys.Info, error) { + var err error d, ok := s[name] if !ok { err = errors.Errorf("Key named '%s' doesn't exist", name) } - - return d.salt, d.key, d.info.Format(), err + return d.key, d.info.Format(), err } // List returns the public info of all keys in the MemStore in unsorted order diff --git a/keys/storage/memstorage/main_test.go b/keys/storage/memstorage/main_test.go index 01975df58..feccb387f 100644 --- a/keys/storage/memstorage/main_test.go +++ b/keys/storage/memstorage/main_test.go @@ -14,7 +14,6 @@ func TestBasicCRUD(t *testing.T) { name := "foo" key := []byte("secret-key-here") - salt := []byte("salt-here") pubkey := crypto.GenPrivKeyEd25519().PubKey() info := keys.Info{ Name: name, @@ -22,7 +21,7 @@ func TestBasicCRUD(t *testing.T) { } // No data: Get and Delete return nothing - _, _, _, err := store.Get(name) + _, _, err := store.Get(name) assert.NotNil(err) err = store.Delete(name) assert.NotNil(err) @@ -32,14 +31,14 @@ func TestBasicCRUD(t *testing.T) { assert.Empty(l) // Putting the key in the store must work - err = store.Put(name, salt, key, info) + err = store.Put(name, key, info) assert.Nil(err) // But a second time is a failure - err = store.Put(name, salt, key, info) + err = store.Put(name, key, info) assert.NotNil(err) // Now, we can get and list properly - _, k, i, err := store.Get(name) + k, i, err := store.Get(name) assert.Nil(err) assert.Equal(key, k) assert.Equal(info.Name, i.Name) @@ -51,7 +50,7 @@ func TestBasicCRUD(t *testing.T) { assert.Equal(i, l[0]) // querying a non-existent key fails - _, _, _, err = store.Get("badname") + _, _, err = store.Get("badname") assert.NotNil(err) // We can only delete once @@ -61,7 +60,7 @@ func TestBasicCRUD(t *testing.T) { assert.NotNil(err) // and then Get and List don't work - _, _, _, err = store.Get(name) + _, _, err = store.Get(name) assert.NotNil(err) // List returns empty list l, err = store.List() From 377d3c7e1122a882a760d005aca8be498ba628aa Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 22:04:22 -0400 Subject: [PATCH 167/273] fix from revert --- keys/types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keys/types.go b/keys/types.go index 008a6f7ae..b3d3a374a 100644 --- a/keys/types.go +++ b/keys/types.go @@ -12,8 +12,8 @@ import ( // Storage has many implementation, based on security and sharing requirements // like disk-backed, mem-backed, vault, db, etc. type Storage interface { - Put(name string, salt []byte, key []byte, info Info) error - Get(name string) (salt []byte, key []byte, info Info, err error) + Put(name string, key []byte, info Info) error + Get(name string) (key []byte, info Info, err error) List() (Infos, error) Delete(name string) error } From d2b1a7096e72bbac6ef0256d7e92edd3c00f61b7 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 27 Oct 2017 22:05:44 -0400 Subject: [PATCH 168/273] changelog --- CHANGELOG.md | 10 ++++++++++ version.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64dc9998b..af0539300 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.4.1 (October 27, 2017) + +This release removes support for bcrypt as it was merged too soon without an upgrade plan +for existing keys. + +REVERTS THE FOLLOWING COMMITS: + +- Parameterize and lower bcrypt cost - dfc4cdd2d71513e4a9922d679c74f36357c4c862 +- Upgrade keys to use bcrypt with salts (#38) - 8e7f0e7701f92206679ad093d013b9b162427631 + ## 0.4.0 (October 27, 2017) BREAKING CHANGES: diff --git a/version.go b/version.go index 585d7e0d7..c39dd627c 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.4.0" +const Version = "0.4.1" From b0cf4b47571c93faa4eb67f2f17afbdf783f48ef Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Sat, 28 Oct 2017 14:11:17 -0700 Subject: [PATCH 169/273] PubKeyFromBytes: return zero value PubKey on error Fixes https://github.com/tendermint/go-crypto/issues/48. This previously skewed up my fuzzing tests so ensure that on error we return the zero value PubKey. --- pub_key.go | 6 ++++-- pub_key_test.go | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/pub_key.go b/pub_key.go index 4d5c31b21..dfa012969 100644 --- a/pub_key.go +++ b/pub_key.go @@ -14,8 +14,10 @@ import ( ) func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { - err = wire.ReadBinaryBytes(pubKeyBytes, &pubKey) - return + if err := wire.ReadBinaryBytes(pubKeyBytes, &pubKey); err != nil { + return PubKey{}, err + } + return pubKey, nil } //---------------------------------------- diff --git a/pub_key_test.go b/pub_key_test.go index 31642233c..097c5ea3b 100644 --- a/pub_key_test.go +++ b/pub_key_test.go @@ -6,6 +6,7 @@ import ( "github.com/btcsuite/btcutil/base58" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type keyData struct { @@ -39,3 +40,9 @@ func TestPubKeySecp256k1Address(t *testing.T) { assert.Equal(t, addr, addrB, "Expected addresses to match") } } + +func TestPubKeyInvalidDataProperReturnsEmpty(t *testing.T) { + pk, err := PubKeyFromBytes([]byte("foo")) + require.NotNil(t, err, "expecting a non-nil error") + require.True(t, pk.Empty(), "expecting an empty public key on error") +} From a2583e278334c35b170352e467a741166474b6da Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 1 Nov 2017 16:38:11 -0500 Subject: [PATCH 170/273] Draft of suggested changes --- keys/cryptostore/docs.go | 25 --- keys/cryptostore/enc_storage.go | 49 ----- keys/cryptostore/encoder.go | 60 ------ keys/cryptostore/encoder_test.go | 105 ----------- keys/cryptostore/generator.go | 88 --------- keys/cryptostore/storage_test.go | 48 ----- keys/{cryptostore/holder.go => keybase.go} | 84 +++++---- .../holder_test.go => keybase_test.go} | 0 keys/storage/filestorage/main.go | 177 ------------------ keys/storage/filestorage/main_test.go | 106 ----------- keys/storage/memstorage/main.go | 68 ------- keys/storage/memstorage/main_test.go | 69 ------- keys/types.go | 124 +----------- 13 files changed, 52 insertions(+), 951 deletions(-) delete mode 100644 keys/cryptostore/docs.go delete mode 100644 keys/cryptostore/enc_storage.go delete mode 100644 keys/cryptostore/encoder.go delete mode 100644 keys/cryptostore/encoder_test.go delete mode 100644 keys/cryptostore/generator.go delete mode 100644 keys/cryptostore/storage_test.go rename keys/{cryptostore/holder.go => keybase.go} (61%) rename keys/{cryptostore/holder_test.go => keybase_test.go} (100%) delete mode 100644 keys/storage/filestorage/main.go delete mode 100644 keys/storage/filestorage/main_test.go delete mode 100644 keys/storage/memstorage/main.go delete mode 100644 keys/storage/memstorage/main_test.go diff --git a/keys/cryptostore/docs.go b/keys/cryptostore/docs.go deleted file mode 100644 index 5c66fba2d..000000000 --- a/keys/cryptostore/docs.go +++ /dev/null @@ -1,25 +0,0 @@ -/* -package cryptostore maintains everything needed for doing public-key signing and -key management in software, based on the go-crypto library from tendermint. - -It is flexible, and allows the user to provide a key generation algorithm -(currently Ed25519 or Secp256k1), an encoder to passphrase-encrypt our keys -when storing them (currently SecretBox from NaCl), and a method to persist -the keys (currently FileStorage like ssh, or MemStorage for tests). -It should be relatively simple to write your own implementation of these -interfaces to match your specific security requirements. - -Note that the private keys are never exposed outside the package, and the -interface of Manager could be implemented by an HSM in the future for -enhanced security. It would require a completely different implementation -however. - -This Manager aims to implement Signer and KeyManager interfaces, along -with some extensions to allow importing/exporting keys and updating the -passphrase. - -Encoder and Generator implementations are currently in this package, -keys.Storage implementations exist as subpackages of -keys/storage -*/ -package cryptostore diff --git a/keys/cryptostore/enc_storage.go b/keys/cryptostore/enc_storage.go deleted file mode 100644 index daeb220b5..000000000 --- a/keys/cryptostore/enc_storage.go +++ /dev/null @@ -1,49 +0,0 @@ -package cryptostore - -import ( - crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-crypto/keys" -) - -// encryptedStorage needs passphrase to get private keys -type encryptedStorage struct { - coder Encoder - store keys.Storage -} - -func (es encryptedStorage) Put(name, pass string, key crypto.PrivKey) error { - secret, err := es.coder.Encrypt(key, pass) - if err != nil { - return err - } - - ki := info(name, key) - return es.store.Put(name, secret, ki) -} - -func (es encryptedStorage) Get(name, pass string) (crypto.PrivKey, keys.Info, error) { - secret, info, err := es.store.Get(name) - if err != nil { - return crypto.PrivKey{}, info, err - } - key, err := es.coder.Decrypt(secret, pass) - return key, info, err -} - -func (es encryptedStorage) List() (keys.Infos, error) { - return es.store.List() -} - -func (es encryptedStorage) Delete(name string) error { - return es.store.Delete(name) -} - -// info hardcodes the encoding of keys -func info(name string, key crypto.PrivKey) keys.Info { - pub := key.PubKey() - return keys.Info{ - Name: name, - Address: pub.Address(), - PubKey: pub, - } -} diff --git a/keys/cryptostore/encoder.go b/keys/cryptostore/encoder.go deleted file mode 100644 index 31cbc2e54..000000000 --- a/keys/cryptostore/encoder.go +++ /dev/null @@ -1,60 +0,0 @@ -package cryptostore - -import ( - "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" -) - -var ( - // SecretBox uses the algorithm from NaCL to store secrets securely - SecretBox Encoder = secretbox{} - // Noop doesn't do any encryption, should only be used in test code - Noop Encoder = noop{} -) - -// Encoder is used to encrypt any key with a passphrase for storage. -// -// This should use a well-designed symetric encryption algorithm -type Encoder interface { - Encrypt(key crypto.PrivKey, pass string) ([]byte, error) - Decrypt(data []byte, pass string) (crypto.PrivKey, error) -} - -func secret(passphrase string) []byte { - // TODO: Sha256(Bcrypt(passphrase)) - return crypto.Sha256([]byte(passphrase)) -} - -type secretbox struct{} - -func (e secretbox) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { - if pass == "" { - return key.Bytes(), nil - } - s := secret(pass) - cipher := crypto.EncryptSymmetric(key.Bytes(), s) - return cipher, nil -} - -func (e secretbox) Decrypt(data []byte, pass string) (key crypto.PrivKey, err error) { - private := data - if pass != "" { - s := secret(pass) - private, err = crypto.DecryptSymmetric(data, s) - if err != nil { - return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") - } - } - key, err = crypto.PrivKeyFromBytes(private) - return key, errors.Wrap(err, "Invalid Passphrase") -} - -type noop struct{} - -func (n noop) Encrypt(key crypto.PrivKey, pass string) ([]byte, error) { - return key.Bytes(), nil -} - -func (n noop) Decrypt(data []byte, pass string) (crypto.PrivKey, error) { - return crypto.PrivKeyFromBytes(data) -} diff --git a/keys/cryptostore/encoder_test.go b/keys/cryptostore/encoder_test.go deleted file mode 100644 index 9a0757b73..000000000 --- a/keys/cryptostore/encoder_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package cryptostore_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - cmn "github.com/tendermint/tmlibs/common" - - "github.com/tendermint/go-crypto/keys/cryptostore" -) - -func TestNoopEncoder(t *testing.T) { - assert, require := assert.New(t), require.New(t) - noop := cryptostore.Noop - - key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) - require.NoError(err) - key2, err := cryptostore.GenSecp256k1.Generate(cmn.RandBytes(16)) - require.NoError(err) - - b, err := noop.Encrypt(key, "encode") - require.Nil(err) - assert.NotEmpty(b) - - b2, err := noop.Encrypt(key2, "encode") - require.Nil(err) - assert.NotEmpty(b2) - assert.NotEqual(b, b2) - - // note the decode with a different password works - not secure! - pk, err := noop.Decrypt(b, "decode") - require.Nil(err) - require.NotNil(pk) - assert.Equal(key, pk) - - pk2, err := noop.Decrypt(b2, "kggugougp") - require.Nil(err) - require.NotNil(pk2) - assert.Equal(key2, pk2) -} - -func TestSecretBox(t *testing.T) { - assert, require := assert.New(t), require.New(t) - enc := cryptostore.SecretBox - - key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) - require.NoError(err) - pass := "some-special-secret" - - b, err := enc.Encrypt(key, pass) - require.Nil(err) - assert.NotEmpty(b) - - // decoding with a different pass is an error - pk, err := enc.Decrypt(b, "decode") - require.NotNil(err) - require.True(pk.Empty()) - - // but decoding with the same passphrase gets us our key - pk, err = enc.Decrypt(b, pass) - require.Nil(err) - assert.Equal(key, pk) -} - -func TestSecretBoxNoPass(t *testing.T) { - assert, require := assert.New(t), require.New(t) - enc := cryptostore.SecretBox - - key, rerr := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) - require.NoError(rerr) - - cases := []struct { - encode string - decode string - valid bool - }{ - {"foo", "foo", true}, - {"foo", "food", false}, - {"", "", true}, - {"", "a", false}, - {"a", "", false}, - } - - for i, tc := range cases { - b, err := enc.Encrypt(key, tc.encode) - require.Nil(err, "%d: %+v", i, err) - assert.NotEmpty(b, "%d", i) - - pk, err := enc.Decrypt(b, tc.decode) - if tc.valid { - require.Nil(err, "%d: %+v", i, err) - assert.Equal(key, pk, "%d", i) - } else { - require.NotNil(err, "%d", i) - } - } - - // now let's make sure raw bytes also work... - b := key.Bytes() - pk, err := enc.Decrypt(b, "") - require.Nil(err, "%+v", err) - assert.Equal(key, pk) -} diff --git a/keys/cryptostore/generator.go b/keys/cryptostore/generator.go deleted file mode 100644 index 81277eda9..000000000 --- a/keys/cryptostore/generator.go +++ /dev/null @@ -1,88 +0,0 @@ -package cryptostore - -import ( - "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/nano" -) - -var ( - // GenEd25519 produces Ed25519 private keys - GenEd25519 Generator = GenFunc(genEd25519) - // GenSecp256k1 produces Secp256k1 private keys - GenSecp256k1 Generator = GenFunc(genSecp256) - // GenLedgerEd25519 used Ed25519 keys stored on nano ledger s with cosmos app - GenLedgerEd25519 Generator = GenFunc(genLedgerEd25519) -) - -// Generator determines the type of private key the keystore creates -type Generator interface { - Generate(secret []byte) (crypto.PrivKey, error) -} - -// GenFunc is a helper to transform a function into a Generator -type GenFunc func(secret []byte) (crypto.PrivKey, error) - -func (f GenFunc) Generate(secret []byte) (crypto.PrivKey, error) { - return f(secret) -} - -func genEd25519(secret []byte) (crypto.PrivKey, error) { - key := crypto.GenPrivKeyEd25519FromSecret(secret).Wrap() - return key, nil -} - -func genSecp256(secret []byte) (crypto.PrivKey, error) { - key := crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap() - return key, nil -} - -// secret is completely ignored for the ledger... -// just for interface compatibility -func genLedgerEd25519(secret []byte) (crypto.PrivKey, error) { - return nano.NewPrivKeyLedgerEd25519Ed25519() -} - -type genInvalidByte struct { - typ byte -} - -func (g genInvalidByte) Generate(secret []byte) (crypto.PrivKey, error) { - err := errors.Errorf("Cannot generate keys for algorithm: %X", g.typ) - return crypto.PrivKey{}, err -} - -type genInvalidAlgo struct { - algo string -} - -func (g genInvalidAlgo) Generate(secret []byte) (crypto.PrivKey, error) { - err := errors.Errorf("Cannot generate keys for algorithm: %s", g.algo) - return crypto.PrivKey{}, err -} - -func getGenerator(algo string) Generator { - switch algo { - case crypto.NameEd25519: - return GenEd25519 - case crypto.NameSecp256k1: - return GenSecp256k1 - case nano.NameLedgerEd25519: - return GenLedgerEd25519 - default: - return genInvalidAlgo{algo} - } -} - -func getGeneratorByType(typ byte) Generator { - switch typ { - case crypto.TypeEd25519: - return GenEd25519 - case crypto.TypeSecp256k1: - return GenSecp256k1 - case nano.TypeLedgerEd25519: - return GenLedgerEd25519 - default: - return genInvalidByte{typ} - } -} diff --git a/keys/cryptostore/storage_test.go b/keys/cryptostore/storage_test.go deleted file mode 100644 index 6d475fdc9..000000000 --- a/keys/cryptostore/storage_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package cryptostore - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - crypto "github.com/tendermint/go-crypto" - cmn "github.com/tendermint/tmlibs/common" - - keys "github.com/tendermint/go-crypto/keys" -) - -func TestSortKeys(t *testing.T) { - assert := assert.New(t) - - gen := func() crypto.PrivKey { - key, _ := GenEd25519.Generate(cmn.RandBytes(16)) - return key - } - assert.NotEqual(gen(), gen()) - - // alphabetical order is n3, n1, n2 - n1, n2, n3 := "john", "mike", "alice" - infos := keys.Infos{ - info(n1, gen()), - info(n2, gen()), - info(n3, gen()), - } - - // make sure they are initialized unsorted - assert.Equal(n1, infos[0].Name) - assert.Equal(n2, infos[1].Name) - assert.Equal(n3, infos[2].Name) - - // now they are sorted - infos.Sort() - assert.Equal(n3, infos[0].Name) - assert.Equal(n1, infos[1].Name) - assert.Equal(n2, infos[2].Name) - - // make sure info put some real data there... - assert.NotEmpty(infos[0].PubKey) - assert.NotEmpty(infos[0].PubKey.Address()) - assert.NotEmpty(infos[1].PubKey) - assert.NotEmpty(infos[1].PubKey.Address()) - assert.NotEqual(infos[0].PubKey, infos[1].PubKey) -} diff --git a/keys/cryptostore/holder.go b/keys/keybase.go similarity index 61% rename from keys/cryptostore/holder.go rename to keys/keybase.go index 7e89dda38..df75b08b7 100644 --- a/keys/cryptostore/holder.go +++ b/keys/keybase.go @@ -4,47 +4,49 @@ import ( "strings" crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-crypto/keys" + dbm "github.com/tendermint/tmlibs/db" ) -// Manager combines encyption and storage implementation to provide +// XXX Lets use go-crypto/bcrypt and ascii encoding directly in here without +// further wrappers around a store or DB. +// Copy functions from: https://github.com/tendermint/mintkey/blob/master/cmd/mintkey/common.go +// +// dbKeybase combines encyption and storage implementation to provide // a full-featured key manager -type Manager struct { - es encryptedStorage - codec keys.Codec +type dbKeybase struct { + db dbm.DB + codec Codec } -func New(coder Encoder, store keys.Storage, codec keys.Codec) Manager { - return Manager{ +func New(db dbm.DB, codec Codec) dbKeybase { + return dbKeybase{ es: encryptedStorage{ + db: db, coder: coder, - store: store, }, codec: codec, } } -// assert Manager satisfies keys.Signer and keys.Manager interfaces -var _ keys.Signer = Manager{} -var _ keys.Manager = Manager{} +var _ Keybase = dbKeybase{} // Create adds a new key to the storage engine, returning error if // another key already stored under this name // // algo must be a supported go-crypto algorithm: ed25519, secp256k1 -func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error) { +func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error) { // 128-bits are the all the randomness we can make use of secret := crypto.CRandBytes(16) gen := getGenerator(algo) key, err := gen.Generate(secret) if err != nil { - return keys.Info{}, "", err + return Info{}, "", err } - err = s.es.Put(name, passphrase, key) + err = kb.es.Put(name, passphrase, key) if err != nil { - return keys.Info{}, "", err + return Info{}, "", err } // we append the type byte to the serialized secret to help with recovery @@ -52,7 +54,7 @@ func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error typ := key.Bytes()[0] secret = append(secret, typ) - seed, err := s.codec.BytesToWords(secret) + seed, err := kb.codec.BytesToWords(secret) phrase := strings.Join(seed, " ") return info(name, key), phrase, err } @@ -63,11 +65,11 @@ func (s Manager) Create(name, passphrase, algo string) (keys.Info, string, error // it under name, protected by passphrase. // // Result similar to New(), except it doesn't return the seed again... -func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) { +func (s dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { words := strings.Split(strings.TrimSpace(seedphrase), " ") - secret, err := s.codec.WordsToBytes(words) + secret, err := kb.codec.WordsToBytes(words) if err != nil { - return keys.Info{}, err + return Info{}, err } // secret is comprised of the actual secret with the type appended @@ -78,24 +80,24 @@ func (s Manager) Recover(name, passphrase, seedphrase string) (keys.Info, error) gen := getGeneratorByType(typ) key, err := gen.Generate(secret) if err != nil { - return keys.Info{}, err + return Info{}, err } // d00d, it worked! create the bugger.... - err = s.es.Put(name, passphrase, key) + err = kb.es.Put(name, passphrase, key) return info(name, key), err } // List loads the keys from the storage and enforces alphabetical order -func (s Manager) List() (keys.Infos, error) { - res, err := s.es.List() +func (s dbKeybase) List() (Infos, error) { + res, err := kb.es.List() res.Sort() return res, err } // Get returns the public information about one key -func (s Manager) Get(name string) (keys.Info, error) { - _, info, err := s.es.store.Get(name) +func (s dbKeybase) Get(name string) (Info, error) { + _, info, err := kb.es.store.Get(name) return info, err } @@ -103,8 +105,8 @@ func (s Manager) Get(name string) (keys.Info, error) { // this public key // // If no key for this name, or the passphrase doesn't match, returns an error -func (s Manager) Sign(name, passphrase string, tx keys.Signable) error { - key, _, err := s.es.Get(name, passphrase) +func (s dbKeybase) Sign(name, passphrase string, msg []byte) error { + key, _, err := kb.es.Get(name, passphrase) if err != nil { return err } @@ -115,55 +117,55 @@ func (s Manager) Sign(name, passphrase string, tx keys.Signable) error { // Export decodes the private key with the current password, encodes // it with a secure one-time password and generates a sequence that can be -// Imported by another Manager +// Imported by another dbKeybase // // This is designed to copy from one device to another, or provide backups // during version updates. -func (s Manager) Export(name, oldpass, transferpass string) ([]byte, error) { - key, _, err := s.es.Get(name, oldpass) +func (s dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { + key, _, err := kb.es.Get(name, oldpass) if err != nil { return nil, err } - res, err := s.es.coder.Encrypt(key, transferpass) + res, err := kb.es.coder.Encrypt(key, transferpass) return res, err } // Import accepts bytes generated by Export along with the same transferpass // If they are valid, it stores the password under the given name with the // new passphrase. -func (s Manager) Import(name, newpass, transferpass string, data []byte) error { - key, err := s.es.coder.Decrypt(data, transferpass) +func (s dbKeybase) Import(name, newpass, transferpass string, data []byte) error { + key, err := kb.es.coder.Decrypt(data, transferpass) if err != nil { return err } - return s.es.Put(name, newpass, key) + return kb.es.Put(name, newpass, key) } // Delete removes key forever, but we must present the // proper passphrase before deleting it (for security) -func (s Manager) Delete(name, passphrase string) error { +func (s dbKeybase) Delete(name, passphrase string) error { // verify we have the proper password before deleting - _, _, err := s.es.Get(name, passphrase) + _, _, err := kb.es.Get(name, passphrase) if err != nil { return err } - return s.es.Delete(name) + return kb.es.Delete(name) } // Update changes the passphrase with which a already stored key is encoded. // // oldpass must be the current passphrase used for encoding, newpass will be // the only valid passphrase from this time forward -func (s Manager) Update(name, oldpass, newpass string) error { - key, _, err := s.es.Get(name, oldpass) +func (s dbKeybase) Update(name, oldpass, newpass string) error { + key, _, err := kb.es.Get(name, oldpass) if err != nil { return err } // we must delete first, as Putting over an existing name returns an error - s.Delete(name, oldpass) + kb.Delete(name, oldpass) - return s.es.Put(name, newpass, key) + return kb.es.Put(name, newpass, key) } diff --git a/keys/cryptostore/holder_test.go b/keys/keybase_test.go similarity index 100% rename from keys/cryptostore/holder_test.go rename to keys/keybase_test.go diff --git a/keys/storage/filestorage/main.go b/keys/storage/filestorage/main.go deleted file mode 100644 index 1f9702995..000000000 --- a/keys/storage/filestorage/main.go +++ /dev/null @@ -1,177 +0,0 @@ -/* -package filestorage provides a secure on-disk storage of private keys and -metadata. Security is enforced by file and directory permissions, much -like standard ssh key storage. -*/ -package filestorage - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "strings" - - "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-crypto/keys" -) - -const ( - BlockType = "Tendermint Light Client" - - // PrivExt is the extension for private keys. - PrivExt = "tlc" - // PubExt is the extensions for public keys. - PubExt = "pub" - - keyPerm = os.FileMode(0600) - // pubPerm = os.FileMode(0644) - dirPerm = os.FileMode(0700) -) - -type FileStore struct { - keyDir string -} - -// New creates an instance of file-based key storage with tight permissions -// -// dir should be an absolute path of a directory owner by this user. It will -// be created if it doesn't exist already. -func New(dir string) FileStore { - err := os.MkdirAll(dir, dirPerm) - if err != nil { - panic(err) - } - return FileStore{dir} -} - -// assert FileStore satisfies keys.Storage -var _ keys.Storage = FileStore{} - -// Put creates two files, one with the public info as json, the other -// with the (encoded) private key as gpg ascii-armor style -func (s FileStore) Put(name string, key []byte, info keys.Info) error { - pub, priv := s.nameToPaths(name) - - // write public info - err := writeInfo(pub, info) - if err != nil { - return err - } - - // write private info - return write(priv, name, key) -} - -// Get loads the info and (encoded) private key from the directory -// It uses `name` to generate the filename, and returns an error if the -// files don't exist or are in the incorrect format -func (s FileStore) Get(name string) ([]byte, keys.Info, error) { - pub, priv := s.nameToPaths(name) - - info, err := readInfo(pub) - if err != nil { - return nil, info, err - } - - key, _, err := read(priv) - return key, info.Format(), err -} - -// List parses the key directory for public info and returns a list of -// Info for all keys located in this directory. -func (s FileStore) List() (keys.Infos, error) { - dir, err := os.Open(s.keyDir) - if err != nil { - return nil, errors.Wrap(err, "List Keys") - } - defer dir.Close() - - names, err := dir.Readdirnames(0) - if err != nil { - return nil, errors.Wrap(err, "List Keys") - } - - // filter names for .pub ending and load them one by one - // half the files is a good guess for pre-allocating the slice - infos := make([]keys.Info, 0, len(names)/2) - for _, name := range names { - if strings.HasSuffix(name, PubExt) { - p := path.Join(s.keyDir, name) - info, err := readInfo(p) - if err != nil { - return nil, err - } - infos = append(infos, info.Format()) - } - } - - return infos, nil -} - -// Delete permanently removes the public and private info for the named key -// The calling function should provide some security checks first. -func (s FileStore) Delete(name string) error { - pub, priv := s.nameToPaths(name) - err := os.Remove(priv) - if err != nil { - return errors.Wrap(err, "Deleting Private Key") - } - err = os.Remove(pub) - return errors.Wrap(err, "Deleting Public Key") -} - -func (s FileStore) nameToPaths(name string) (pub, priv string) { - privName := fmt.Sprintf("%s.%s", name, PrivExt) - pubName := fmt.Sprintf("%s.%s", name, PubExt) - return path.Join(s.keyDir, pubName), path.Join(s.keyDir, privName) -} - -func writeInfo(path string, info keys.Info) error { - return write(path, info.Name, info.PubKey.Bytes()) -} - -func readInfo(path string) (info keys.Info, err error) { - var data []byte - data, info.Name, err = read(path) - if err != nil { - return - } - pk, err := crypto.PubKeyFromBytes(data) - info.PubKey = pk - return -} - -func read(path string) ([]byte, string, error) { - f, err := os.Open(path) - if err != nil { - return nil, "", errors.Wrap(err, "Reading data") - } - defer f.Close() - - d, err := ioutil.ReadAll(f) - if err != nil { - return nil, "", errors.Wrap(err, "Reading data") - } - block, headers, key, err := crypto.DecodeArmor(string(d)) - if err != nil { - return nil, "", errors.Wrap(err, "Invalid Armor") - } - if block != BlockType { - return nil, "", errors.Errorf("Unknown key type: %s", block) - } - return key, headers["name"], nil -} - -func write(path, name string, key []byte) error { - f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, keyPerm) - if err != nil { - return errors.Wrap(err, "Writing data") - } - defer f.Close() - headers := map[string]string{"name": name} - text := crypto.EncodeArmor(BlockType, headers, key) - _, err = f.WriteString(text) - return errors.Wrap(err, "Writing data") -} diff --git a/keys/storage/filestorage/main_test.go b/keys/storage/filestorage/main_test.go deleted file mode 100644 index 28c950c2c..000000000 --- a/keys/storage/filestorage/main_test.go +++ /dev/null @@ -1,106 +0,0 @@ -package filestorage - -import ( - "io/ioutil" - "os" - "path" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-crypto/keys" -) - -func TestBasicCRUD(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - dir, err := ioutil.TempDir("", "filestorage-test") - assert.Nil(err) - defer os.RemoveAll(dir) - store := New(dir) - - name := "bar" - key := []byte("secret-key-here") - pubkey := crypto.GenPrivKeyEd25519().PubKey() - info := keys.Info{ - Name: name, - PubKey: pubkey.Wrap(), - } - - // No data: Get and Delete return nothing - _, _, err = store.Get(name) - assert.NotNil(err) - err = store.Delete(name) - assert.NotNil(err) - // List returns empty list - l, err := store.List() - assert.Nil(err) - assert.Empty(l) - - // Putting the key in the store must work - err = store.Put(name, key, info) - assert.Nil(err) - // But a second time is a failure - err = store.Put(name, key, info) - assert.NotNil(err) - - // Now, we can get and list properly - k, i, err := store.Get(name) - require.Nil(err, "%+v", err) - assert.Equal(key, k) - assert.Equal(info.Name, i.Name) - assert.Equal(info.PubKey, i.PubKey) - assert.NotEmpty(i.Address) - l, err = store.List() - require.Nil(err, "%+v", err) - assert.Equal(1, len(l)) - assert.Equal(i, l[0]) - - // querying a non-existent key fails - _, _, err = store.Get("badname") - assert.NotNil(err) - - // We can only delete once - err = store.Delete(name) - assert.Nil(err) - err = store.Delete(name) - assert.NotNil(err) - - // and then Get and List don't work - _, _, err = store.Get(name) - assert.NotNil(err) - // List returns empty list - l, err = store.List() - assert.Nil(err) - assert.Empty(l) -} - -func TestDirectoryHandling(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - // prepare a temp dir and make sure it is not there - newDir := path.Join(os.TempDir(), "file-test-dir") - _, err := os.Open(newDir) - assert.True(os.IsNotExist(err)) - defer os.RemoveAll(newDir) - - // now, check with two levels deep.... - parentDir := path.Join(os.TempDir(), "missing-dir") - nestedDir := path.Join(parentDir, "lots", "of", "levels", "here") - _, err = os.Open(parentDir) - assert.True(os.IsNotExist(err)) - defer os.RemoveAll(parentDir) - - // create a new storage, and verify it creates the directory with good permissions - for _, dir := range []string{newDir, nestedDir, newDir} { - New(dir) - d, err := os.Open(dir) - require.Nil(err) - defer d.Close() - - stat, err := d.Stat() - require.Nil(err) - assert.Equal(dirPerm, stat.Mode()&os.ModePerm) - } -} diff --git a/keys/storage/memstorage/main.go b/keys/storage/memstorage/main.go deleted file mode 100644 index a988fe0ff..000000000 --- a/keys/storage/memstorage/main.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -package memstorage provides a simple in-memory key store designed for -use in test cases, particularly to isolate them from the filesystem, -concurrency, and cleanup issues. -*/ -package memstorage - -import ( - "github.com/pkg/errors" - keys "github.com/tendermint/go-crypto/keys" -) - -type data struct { - info keys.Info - key []byte -} - -type MemStore map[string]data - -// New creates an instance of file-based key storage with tight permissions -func New() MemStore { - return MemStore{} -} - -// assert MemStore satisfies keys.Storage -var _ keys.Storage = MemStore{} - -// Put adds the given key, returns an error if it another key -// is already stored under this name -func (s MemStore) Put(name string, key []byte, info keys.Info) error { - if _, ok := s[name]; ok { - return errors.Errorf("Key named '%s' already exists", name) - } - s[name] = data{info, key} - return nil -} - -// Get returns the key stored under the name, or returns an error if not present -func (s MemStore) Get(name string) ([]byte, keys.Info, error) { - var err error - d, ok := s[name] - if !ok { - err = errors.Errorf("Key named '%s' doesn't exist", name) - } - return d.key, d.info.Format(), err -} - -// List returns the public info of all keys in the MemStore in unsorted order -func (s MemStore) List() (keys.Infos, error) { - res := make([]keys.Info, len(s)) - i := 0 - for _, d := range s { - res[i] = d.info.Format() - i++ - } - return res, nil -} - -// Delete removes the named key from the MemStore, raising an error if it -// wasn't present yet. -func (s MemStore) Delete(name string) error { - _, ok := s[name] - if !ok { - return errors.Errorf("Key named '%s' doesn't exist", name) - } - delete(s, name) - return nil -} diff --git a/keys/storage/memstorage/main_test.go b/keys/storage/memstorage/main_test.go deleted file mode 100644 index feccb387f..000000000 --- a/keys/storage/memstorage/main_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package memstorage - -import ( - "testing" - - "github.com/stretchr/testify/assert" - crypto "github.com/tendermint/go-crypto" - keys "github.com/tendermint/go-crypto/keys" -) - -func TestBasicCRUD(t *testing.T) { - assert := assert.New(t) - store := New() - - name := "foo" - key := []byte("secret-key-here") - pubkey := crypto.GenPrivKeyEd25519().PubKey() - info := keys.Info{ - Name: name, - PubKey: pubkey, - } - - // No data: Get and Delete return nothing - _, _, err := store.Get(name) - assert.NotNil(err) - err = store.Delete(name) - assert.NotNil(err) - // List returns empty list - l, err := store.List() - assert.Nil(err) - assert.Empty(l) - - // Putting the key in the store must work - err = store.Put(name, key, info) - assert.Nil(err) - // But a second time is a failure - err = store.Put(name, key, info) - assert.NotNil(err) - - // Now, we can get and list properly - k, i, err := store.Get(name) - assert.Nil(err) - assert.Equal(key, k) - assert.Equal(info.Name, i.Name) - assert.Equal(info.PubKey, i.PubKey) - assert.NotEmpty(i.Address) - l, err = store.List() - assert.Nil(err) - assert.Equal(1, len(l)) - assert.Equal(i, l[0]) - - // querying a non-existent key fails - _, _, err = store.Get("badname") - assert.NotNil(err) - - // We can only delete once - err = store.Delete(name) - assert.Nil(err) - err = store.Delete(name) - assert.NotNil(err) - - // and then Get and List don't work - _, _, err = store.Get(name) - assert.NotNil(err) - // List returns empty list - l, err = store.List() - assert.Nil(err) - assert.Empty(l) -} diff --git a/keys/types.go b/keys/types.go index b3d3a374a..534da0720 100644 --- a/keys/types.go +++ b/keys/types.go @@ -1,134 +1,28 @@ package keys import ( - "fmt" "sort" crypto "github.com/tendermint/go-crypto" - wire "github.com/tendermint/go-wire" data "github.com/tendermint/go-wire/data" ) -// Storage has many implementation, based on security and sharing requirements -// like disk-backed, mem-backed, vault, db, etc. -type Storage interface { - Put(name string, key []byte, info Info) error - Get(name string) (key []byte, info Info, err error) - List() (Infos, error) - Delete(name string) error -} - // Info is the public information about a key type Info struct { - Name string `json:"name"` - Address data.Bytes `json:"address"` - PubKey crypto.PubKey `json:"pubkey"` -} - -func (i *Info) Format() Info { - if !i.PubKey.Empty() { - i.Address = i.PubKey.Address() - } - return *i -} - -// Infos is a wrapper to allows alphabetical sorting of the keys -type Infos []Info - -func (k Infos) Len() int { return len(k) } -func (k Infos) Less(i, j int) bool { return k[i].Name < k[j].Name } -func (k Infos) Swap(i, j int) { k[i], k[j] = k[j], k[i] } -func (k Infos) Sort() { - if k != nil { - sort.Sort(k) - } -} - -// Signable represents any transaction we wish to send to tendermint core -// These methods allow us to sign arbitrary Tx with the KeyStore -type Signable interface { - // SignBytes is the immutable data, which needs to be signed - SignBytes() []byte - - // Sign will add a signature and pubkey. - // - // Depending on the Signable, one may be able to call this multiple times for multisig - // Returns error if called with invalid data or too many times - Sign(pubkey crypto.PubKey, sig crypto.Signature) error - - // Signers will return the public key(s) that signed if the signature - // is valid, or an error if there is any issue with the signature, - // including if there are no signatures - Signers() ([]crypto.PubKey, error) - - // TxBytes returns the transaction data as well as all signatures - // It should return an error if Sign was never called - TxBytes() ([]byte, error) -} - -// Signer allows one to use a keystore to sign transactions -type Signer interface { - Sign(name, passphrase string, tx Signable) error + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` } -// Manager allows simple CRUD on a keystore, as an aid to signing -type Manager interface { - Signer - // Create also returns a seed phrase for cold-storage - Create(name, passphrase, algo string) (Info, string, error) - // Recover takes a seedphrase and loads in the private key +// Keybase allows simple CRUD on a keystore, as an aid to signing +type Keybase interface { + // Sign some bytes + Sign(name, passphrase string, msg []byte) (crypto.Signature, error) + // Create a new keypair + Create(name, passphrase, algo string) (_ Info, seedphrase string, _ error) + // Recover takes a seedphrase and loads in the key Recover(name, passphrase, seedphrase string) (Info, error) List() (Infos, error) Get(name string) (Info, error) Update(name, oldpass, newpass string) error Delete(name, passphrase string) error } - -/**** MockSignable allows us to view data ***/ - -// MockSignable lets us wrap arbitrary data with a go-crypto signature -type MockSignable struct { - Data []byte - PubKey crypto.PubKey - Signature crypto.Signature -} - -var _ Signable = &MockSignable{} - -// NewMockSignable sets the data to sign -func NewMockSignable(data []byte) *MockSignable { - return &MockSignable{Data: data} -} - -// TxBytes returns the full data with signatures -func (s *MockSignable) TxBytes() ([]byte, error) { - return wire.BinaryBytes(s), nil -} - -// SignBytes returns the original data passed into `NewSig` -func (s *MockSignable) SignBytes() []byte { - return s.Data -} - -// Sign will add a signature and pubkey. -// -// Depending on the Signable, one may be able to call this multiple times for multisig -// Returns error if called with invalid data or too many times -func (s *MockSignable) Sign(pubkey crypto.PubKey, sig crypto.Signature) error { - s.PubKey = pubkey - s.Signature = sig - return nil -} - -// Signers will return the public key(s) that signed if the signature -// is valid, or an error if there is any issue with the signature, -// including if there are no signatures -func (s *MockSignable) Signers() ([]crypto.PubKey, error) { - if s.PubKey.Empty() { - return nil, fmt.Errorf("no signers") - } - if !s.PubKey.VerifyBytes(s.SignBytes(), s.Signature) { - return nil, fmt.Errorf("invalid signature") - } - return []crypto.PubKey{s.PubKey}, nil -} From ac841a6124a65cdb4d51e857f2fa7e6bfe7e3cae Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 2 Nov 2017 14:09:59 -0500 Subject: [PATCH 171/273] Fixed imports --- glide.lock | 30 ++++++++++++++++++++++++----- glide.yaml | 7 +++++++ keys/keybase.go | 2 +- keys/keybase_test.go | 45 ++++++++++++++++++-------------------------- 4 files changed, 51 insertions(+), 33 deletions(-) diff --git a/glide.lock b/glide.lock index 096ec5c15..c1400b3f9 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 6e06a42eafe0aeff112cee86aef6b2cab0e2f62c2e6bfccfb629aa22f6b62773 -updated: 2017-10-27T18:45:18.350198941+02:00 +hash: 86d02329c537ccb46ccb062918f0cb9e839f2cf894dfd57223c3ea4de14266db +updated: 2017-11-02T14:09:11.208038182-05:00 imports: - name: github.com/btcsuite/btcd version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e @@ -29,29 +29,49 @@ imports: version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf +- name: github.com/golang/snappy + version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/howeyc/crc16 version: 96a97a1abb579c7ff1a8ffa77f2e72d1c314b57f +- name: github.com/jmhodges/levigo + version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d +- name: github.com/syndtr/goleveldb + version: b89cc31ef7977104127d34c1bd31ebd1a9db2199 + subpackages: + - leveldb + - leveldb/cache + - leveldb/comparer + - leveldb/errors + - leveldb/filter + - leveldb/iterator + - leveldb/journal + - leveldb/memdb + - leveldb/opt + - leveldb/storage + - leveldb/table + - leveldb/util - name: github.com/tendermint/ed25519 version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 8ee84b5b2581530168daf66fc89c548d27403c57 + version: 2baffcb6b690057568bc90ef1d457efb150b979a subpackages: - data - data/base58 - name: github.com/tendermint/tmlibs - version: 092eb701c7276907cdbed258750e22ce895b6735 + version: d9525c0fb671204450b160807480e1263053fb20 subpackages: - common + - db - log - name: golang.org/x/crypto - version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 + version: bd6f299fb381e4c3393d1c4b1f0b94f5e77650c8 subpackages: - bcrypt - blowfish diff --git a/glide.yaml b/glide.yaml index 2f3e72471..a0b6650fa 100644 --- a/glide.yaml +++ b/glide.yaml @@ -6,6 +6,13 @@ import: - package: github.com/btcsuite/btcutil subpackages: - base58 +- package: github.com/syndtr/goleveldb + subpackages: + - leveldb + - leveldb/errors + - leveldb/iterator + - leveldb/opt + - leveldb/util - package: github.com/tendermint/ed25519 subpackages: - extra25519 diff --git a/keys/keybase.go b/keys/keybase.go index df75b08b7..54827d3a9 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -1,4 +1,4 @@ -package cryptostore +package keys import ( "strings" diff --git a/keys/keybase_test.go b/keys/keybase_test.go index a9056f0de..a57284e9c 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -1,4 +1,4 @@ -package cryptostore_test +package keys_test import ( "bytes" @@ -10,11 +10,10 @@ import ( "github.com/stretchr/testify/require" cmn "github.com/tendermint/tmlibs/common" + dbm "github.com/tendermint/tmlibs/db" crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/cryptostore" - "github.com/tendermint/go-crypto/keys/storage/memstorage" "github.com/tendermint/go-crypto/nano" ) @@ -23,9 +22,8 @@ func TestKeyManagement(t *testing.T) { assert, require := assert.New(t), require.New(t) // make the storage with reasonable defaults - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), + cstore := keys.New( + dbm.NewMemDB(), keys.MustLoadCodec("english"), ) @@ -92,9 +90,8 @@ func TestSignVerify(t *testing.T) { assert, require := assert.New(t), require.New(t) // make the storage with reasonable defaults - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), + cstore := keys.New( + dbm.NewMemDB(), keys.MustLoadCodec("english"), ) algo := crypto.NameSecp256k1 @@ -164,9 +161,8 @@ func TestSignWithLedger(t *testing.T) { } // make the storage with reasonable defaults - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), + cstore := keys.New( + dbm.NewMemDB(), keys.MustLoadCodec("english"), ) n := "nano-s" @@ -206,7 +202,7 @@ func TestSignWithLedger(t *testing.T) { assert.False(key.VerifyBytes(d1, s2.Signature)) } -func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, pass, badpass string) { +func assertPassword(assert *assert.Assertions, cstore keys.KeyBase, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) assert.NotNil(err) err = cstore.Update(name, pass, pass) @@ -218,13 +214,12 @@ func TestImportUnencrypted(t *testing.T) { require := require.New(t) // make the storage with reasonable defaults - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), + cstore := keys.New( + dbm.NewMemDB(), keys.MustLoadCodec("english"), ) - key, err := cryptostore.GenEd25519.Generate(cmn.RandBytes(16)) + key, err := keys.GenEd25519.Generate(cmn.RandBytes(16)) require.NoError(err) addr := key.PubKey().Address() @@ -246,9 +241,8 @@ func TestAdvancedKeyManagement(t *testing.T) { assert, require := assert.New(t), require.New(t) // make the storage with reasonable defaults - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), + cstore := keys.New( + dbm.NewMemDB(), keys.MustLoadCodec("english"), ) @@ -290,9 +284,8 @@ func TestSeedPhrase(t *testing.T) { assert, require := assert.New(t), require.New(t) // make the storage with reasonable defaults - cstore := cryptostore.New( - cryptostore.SecretBox, - memstorage.New(), + cstore := keys.New( + dbm.NewMemDB(), keys.MustLoadCodec("english"), ) @@ -322,10 +315,8 @@ func TestSeedPhrase(t *testing.T) { func ExampleNew() { // Select the encryption and storage for your cryptostore - cstore := cryptostore.New( - cryptostore.SecretBox, - // Note: use filestorage.New(dir) for real data - memstorage.New(), + cstore := keys.New( + dbm.NewMemDB(), keys.MustLoadCodec("english"), ) ed := crypto.NameEd25519 From 946c9c573e3615fec3473288832a84c4c85946e4 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 2 Nov 2017 16:31:29 -0500 Subject: [PATCH 172/273] Handle generating keys --- keys/keybase.go | 46 +++++++++++++++++++++++++++++++++++++--------- keys/types.go | 7 ++----- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/keys/keybase.go b/keys/keybase.go index 54827d3a9..bdffb9dce 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -3,8 +3,11 @@ package keys import ( "strings" + "github.com/pkg/errors" crypto "github.com/tendermint/go-crypto" dbm "github.com/tendermint/tmlibs/db" + + "github.com/tendermint/go-crypto/nano" ) // XXX Lets use go-crypto/bcrypt and ascii encoding directly in here without @@ -37,9 +40,7 @@ var _ Keybase = dbKeybase{} func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error) { // 128-bits are the all the randomness we can make use of secret := crypto.CRandBytes(16) - gen := getGenerator(algo) - - key, err := gen.Generate(secret) + key, err := generate(algo, secret) if err != nil { return Info{}, "", err } @@ -77,8 +78,7 @@ func (s dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { l := len(secret) secret, typ := secret[:l-1], secret[l-1] - gen := getGeneratorByType(typ) - key, err := gen.Generate(secret) + key, err := generateByType(typ, secret) if err != nil { return Info{}, err } @@ -89,9 +89,9 @@ func (s dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { } // List loads the keys from the storage and enforces alphabetical order -func (s dbKeybase) List() (Infos, error) { - res, err := kb.es.List() - res.Sort() +func (s dbKeybase) List() ([]Info, error) { + res, err := s.es.List() + sort.SortSlice(res) return res, err } @@ -105,7 +105,7 @@ func (s dbKeybase) Get(name string) (Info, error) { // this public key // // If no key for this name, or the passphrase doesn't match, returns an error -func (s dbKeybase) Sign(name, passphrase string, msg []byte) error { +func (s dbKeybase) Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) { key, _, err := kb.es.Get(name, passphrase) if err != nil { return err @@ -169,3 +169,31 @@ func (s dbKeybase) Update(name, oldpass, newpass string) error { return kb.es.Put(name, newpass, key) } + +func generate(algo string, secret []byte) (crypto.PrivKey, error) { + switch algo { + case crypto.NameEd25519: + return crypto.GenPrivKeyEd25519FromSecret(secret).Wrap(), nil + case crypto.NameSecp256k1: + return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap(), nil + case nano.NameLedgerEd25519: + return nano.NewPrivKeyLedgerEd25519Ed25519() + default: + err := errors.Errorf("Cannot generate keys for algorithm: %s", algo) + return crypto.PrivKey{}, err + } +} + +func generateByType(typ byte, secret []byte) (crypto.PrivKey, error) { + switch typ { + case crypto.TypeEd25519: + return generate(crypto.NameEd25519, secret) + case crypto.TypeSecp256k1: + return generate(crypto.NameSecp256k1, secret) + case nano.TypeLedgerEd25519: + return generate(nano.NameLedgerEd25519, secret) + default: + err := errors.Errorf("Cannot generate keys for algorithm: %X", typ) + return crypto.PrivKey{}, err + } +} diff --git a/keys/types.go b/keys/types.go index 534da0720..110cd3ded 100644 --- a/keys/types.go +++ b/keys/types.go @@ -1,10 +1,7 @@ package keys import ( - "sort" - crypto "github.com/tendermint/go-crypto" - data "github.com/tendermint/go-wire/data" ) // Info is the public information about a key @@ -16,12 +13,12 @@ type Info struct { // Keybase allows simple CRUD on a keystore, as an aid to signing type Keybase interface { // Sign some bytes - Sign(name, passphrase string, msg []byte) (crypto.Signature, error) + Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) // Create a new keypair Create(name, passphrase, algo string) (_ Info, seedphrase string, _ error) // Recover takes a seedphrase and loads in the key Recover(name, passphrase, seedphrase string) (Info, error) - List() (Infos, error) + List() ([]Info, error) Get(name string) (Info, error) Update(name, oldpass, newpass string) error Delete(name, passphrase string) error From 9ef978c5ecb32c22db58a91c46f78239c7a8c588 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 2 Nov 2017 16:46:10 -0500 Subject: [PATCH 173/273] Fix errors except for es missing --- keys/keybase.go | 59 +++++++++++++++++++++++++++++++++---------------- keys/types.go | 7 ++++++ 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/keys/keybase.go b/keys/keybase.go index bdffb9dce..5fa32635e 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -1,6 +1,7 @@ package keys import ( + "sort" "strings" "github.com/pkg/errors" @@ -23,10 +24,7 @@ type dbKeybase struct { func New(db dbm.DB, codec Codec) dbKeybase { return dbKeybase{ - es: encryptedStorage{ - db: db, - coder: coder, - }, + db: db, codec: codec, } } @@ -66,7 +64,7 @@ func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error) // it under name, protected by passphrase. // // Result similar to New(), except it doesn't return the seed again... -func (s dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { +func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { words := strings.Split(strings.TrimSpace(seedphrase), " ") secret, err := kb.codec.WordsToBytes(words) if err != nil { @@ -89,14 +87,14 @@ func (s dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { } // List loads the keys from the storage and enforces alphabetical order -func (s dbKeybase) List() ([]Info, error) { - res, err := s.es.List() - sort.SortSlice(res) +func (kb dbKeybase) List() ([]Info, error) { + res, err := kb.es.List() + sort.Slice(res, func(a, b int) bool { return res[a].Name < res[b].Name }) return res, err } // Get returns the public information about one key -func (s dbKeybase) Get(name string) (Info, error) { +func (kb dbKeybase) Get(name string) (Info, error) { _, info, err := kb.es.store.Get(name) return info, err } @@ -105,14 +103,15 @@ func (s dbKeybase) Get(name string) (Info, error) { // this public key // // If no key for this name, or the passphrase doesn't match, returns an error -func (s dbKeybase) Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) { - key, _, err := kb.es.Get(name, passphrase) +func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pk crypto.PubKey, err error) { + var key crypto.PrivKey + key, _, err = kb.es.Get(name, passphrase) if err != nil { - return err + return } - sig := key.Sign(tx.SignBytes()) - pubkey := key.PubKey() - return tx.Sign(pubkey, sig) + sig = key.Sign(msg) + pk = key.PubKey() + return } // Export decodes the private key with the current password, encodes @@ -121,7 +120,7 @@ func (s dbKeybase) Sign(name, passphrase string, msg []byte) (crypto.Signature, // // This is designed to copy from one device to another, or provide backups // during version updates. -func (s dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { +func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { key, _, err := kb.es.Get(name, oldpass) if err != nil { return nil, err @@ -134,7 +133,7 @@ func (s dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { // Import accepts bytes generated by Export along with the same transferpass // If they are valid, it stores the password under the given name with the // new passphrase. -func (s dbKeybase) Import(name, newpass, transferpass string, data []byte) error { +func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) error { key, err := kb.es.coder.Decrypt(data, transferpass) if err != nil { return err @@ -145,7 +144,7 @@ func (s dbKeybase) Import(name, newpass, transferpass string, data []byte) error // Delete removes key forever, but we must present the // proper passphrase before deleting it (for security) -func (s dbKeybase) Delete(name, passphrase string) error { +func (kb dbKeybase) Delete(name, passphrase string) error { // verify we have the proper password before deleting _, _, err := kb.es.Get(name, passphrase) if err != nil { @@ -158,7 +157,7 @@ func (s dbKeybase) Delete(name, passphrase string) error { // // oldpass must be the current passphrase used for encoding, newpass will be // the only valid passphrase from this time forward -func (s dbKeybase) Update(name, oldpass, newpass string) error { +func (kb dbKeybase) Update(name, oldpass, newpass string) error { key, _, err := kb.es.Get(name, oldpass) if err != nil { return err @@ -197,3 +196,25 @@ func generateByType(typ byte, secret []byte) (crypto.PrivKey, error) { return crypto.PrivKey{}, err } } + +func encrypt(key crypto.PrivKey, pass string) ([]byte, error) { + if pass == "" { + return key.Bytes(), nil + } + s := secret(pass) + cipher := crypto.EncryptSymmetric(key.Bytes(), s) + return cipher, nil +} + +func decrypt(data []byte, pass string) (key crypto.PrivKey, err error) { + private := data + if pass != "" { + s := secret(pass) + private, err = crypto.DecryptSymmetric(data, s) + if err != nil { + return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") + } + } + key, err = crypto.PrivKeyFromBytes(private) + return key, errors.Wrap(err, "Invalid Passphrase") +} diff --git a/keys/types.go b/keys/types.go index 110cd3ded..b126f7267 100644 --- a/keys/types.go +++ b/keys/types.go @@ -10,6 +10,13 @@ type Info struct { PubKey crypto.PubKey `json:"pubkey"` } +func info(name string, privKey crypto.PrivKey) Info { + return Info{ + Name: name, + PubKey: privKey.PubKey(), + } +} + // Keybase allows simple CRUD on a keystore, as an aid to signing type Keybase interface { // Sign some bytes From 4173d1031e6a7361392fb80e46f0cc5469cb4499 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 2 Nov 2017 18:32:12 -0500 Subject: [PATCH 174/273] go build compiles --- keys/keybase.go | 117 +++++++++++++++++++++++++++++------------------- keys/mintkey.go | 73 ++++++++++++++++++++++++++++++ keys/types.go | 11 +++++ 3 files changed, 156 insertions(+), 45 deletions(-) create mode 100644 keys/mintkey.go diff --git a/keys/keybase.go b/keys/keybase.go index 5fa32635e..00de1ad55 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -1,7 +1,7 @@ package keys import ( - "sort" + "fmt" "strings" "github.com/pkg/errors" @@ -43,10 +43,7 @@ func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error) return Info{}, "", err } - err = kb.es.Put(name, passphrase, key) - if err != nil { - return Info{}, "", err - } + public := kb.writeKey(key, name, passphrase) // we append the type byte to the serialized secret to help with recovery // ie [secret] = [secret] + [type] @@ -55,7 +52,7 @@ func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error) seed, err := kb.codec.BytesToWords(secret) phrase := strings.Join(seed, " ") - return info(name, key), phrase, err + return public, phrase, err } // Recover takes a seed phrase and tries to recover the private key. @@ -82,21 +79,31 @@ func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { } // d00d, it worked! create the bugger.... - err = kb.es.Put(name, passphrase, key) - return info(name, key), err + public := kb.writeKey(key, name, passphrase) + return public, err } // List loads the keys from the storage and enforces alphabetical order func (kb dbKeybase) List() ([]Info, error) { - res, err := kb.es.List() - sort.Slice(res, func(a, b int) bool { return res[a].Name < res[b].Name }) - return res, err + var res []Info + var more = true + for iter := kb.db.Iterator(); more; more = iter.Next() { + key := iter.Key() + if isPub(key) { + info, err := readInfo(iter.Value()) + if err != nil { + return nil, err + } + res = append(res, info) + } + } + return res, nil } // Get returns the public information about one key func (kb dbKeybase) Get(name string) (Info, error) { - _, info, err := kb.es.store.Get(name) - return info, err + bs := kb.db.Get(pubName(name)) + return readInfo(bs) } // Sign will modify the Signable in order to attach a valid signature with @@ -105,10 +112,12 @@ func (kb dbKeybase) Get(name string) (Info, error) { // If no key for this name, or the passphrase doesn't match, returns an error func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pk crypto.PubKey, err error) { var key crypto.PrivKey - key, _, err = kb.es.Get(name, passphrase) + bs := kb.db.Get(privName(name)) + key, err = unarmorDecryptPrivKey(string(bs), passphrase) if err != nil { return } + sig = key.Sign(msg) pk = key.PubKey() return @@ -121,36 +130,49 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signat // This is designed to copy from one device to another, or provide backups // during version updates. func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { - key, _, err := kb.es.Get(name, oldpass) + bs := kb.db.Get(privName(name)) + key, err := unarmorDecryptPrivKey(string(bs), oldpass) if err != nil { return nil, err } - res, err := kb.es.coder.Encrypt(key, transferpass) - return res, err + if transferpass == "" { + return key.Bytes(), nil + } + res := encryptArmorPrivKey(key, transferpass) + return []byte(res), nil } // Import accepts bytes generated by Export along with the same transferpass // If they are valid, it stores the password under the given name with the // new passphrase. -func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) error { - key, err := kb.es.coder.Decrypt(data, transferpass) +func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err error) { + var key crypto.PrivKey + if transferpass == "" { + key, err = crypto.PrivKeyFromBytes(data) + } else { + key, err = unarmorDecryptPrivKey(string(data), transferpass) + } if err != nil { return err } - return kb.es.Put(name, newpass, key) + kb.writeKey(key, name, newpass) + return nil } // Delete removes key forever, but we must present the // proper passphrase before deleting it (for security) func (kb dbKeybase) Delete(name, passphrase string) error { // verify we have the proper password before deleting - _, _, err := kb.es.Get(name, passphrase) + bs := kb.db.Get(privName(name)) + _, err := unarmorDecryptPrivKey(string(bs), passphrase) if err != nil { return err } - return kb.es.Delete(name) + kb.db.DeleteSync(pubName(name)) + kb.db.DeleteSync(privName(name)) + return nil } // Update changes the passphrase with which a already stored key is encoded. @@ -158,15 +180,30 @@ func (kb dbKeybase) Delete(name, passphrase string) error { // oldpass must be the current passphrase used for encoding, newpass will be // the only valid passphrase from this time forward func (kb dbKeybase) Update(name, oldpass, newpass string) error { - key, _, err := kb.es.Get(name, oldpass) + bs := kb.db.Get(privName(name)) + key, err := unarmorDecryptPrivKey(string(bs), oldpass) if err != nil { return err } // we must delete first, as Putting over an existing name returns an error - kb.Delete(name, oldpass) + kb.db.DeleteSync(pubName(name)) + kb.db.DeleteSync(privName(name)) + kb.writeKey(key, name, newpass) + return nil +} - return kb.es.Put(name, newpass, key) +func (kb dbKeybase) writeKey(priv crypto.PrivKey, name, passphrase string) Info { + // generate the public bytes + public := info(name, priv) + // generate the encrypted privkey + private := encryptArmorPrivKey(priv, passphrase) + + // write them both + kb.db.SetSync(pubName(name), public.bytes()) + kb.db.SetSync(privName(name), []byte(private)) + + return public } func generate(algo string, secret []byte) (crypto.PrivKey, error) { @@ -197,24 +234,14 @@ func generateByType(typ byte, secret []byte) (crypto.PrivKey, error) { } } -func encrypt(key crypto.PrivKey, pass string) ([]byte, error) { - if pass == "" { - return key.Bytes(), nil - } - s := secret(pass) - cipher := crypto.EncryptSymmetric(key.Bytes(), s) - return cipher, nil -} - -func decrypt(data []byte, pass string) (key crypto.PrivKey, err error) { - private := data - if pass != "" { - s := secret(pass) - private, err = crypto.DecryptSymmetric(data, s) - if err != nil { - return crypto.PrivKey{}, errors.Wrap(err, "Invalid Passphrase") - } - } - key, err = crypto.PrivKeyFromBytes(private) - return key, errors.Wrap(err, "Invalid Passphrase") +func pubName(name string) []byte { + return []byte(fmt.Sprintf("%s.pub", name)) +} + +func privName(name string) []byte { + return []byte(fmt.Sprintf("%s.priv", name)) +} + +func isPub(name []byte) bool { + return strings.HasSuffix(string(name), ".pub") } diff --git a/keys/mintkey.go b/keys/mintkey.go new file mode 100644 index 000000000..c948848be --- /dev/null +++ b/keys/mintkey.go @@ -0,0 +1,73 @@ +package keys + +import ( + "encoding/hex" + "fmt" + + cmn "github.com/tendermint/tmlibs/common" + + "github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto/bcrypt" +) + +const ( + blockTypePrivKey = "TENDERMINT PRIVATE KEY" +) + +func encryptArmorPrivKey(privKey crypto.PrivKey, passphrase string) string { + saltBytes, encBytes := encryptPrivKey(privKey, passphrase) + header := map[string]string{ + "kdf": "bcrypt", + "salt": fmt.Sprintf("%X", saltBytes), + } + armorStr := crypto.EncodeArmor(blockTypePrivKey, header, encBytes) + return armorStr +} + +func unarmorDecryptPrivKey(armorStr string, passphrase string) (crypto.PrivKey, error) { + var privKey crypto.PrivKey + blockType, header, encBytes, err := crypto.DecodeArmor(armorStr) + if err != nil { + return privKey, err + } + if blockType != blockTypePrivKey { + return privKey, fmt.Errorf("Unrecognized armor type: %v", blockType) + } + if header["kdf"] != "bcrypt" { + return privKey, fmt.Errorf("Unrecognized KDF type: %v", header["KDF"]) + } + if header["salt"] == "" { + return privKey, fmt.Errorf("Missing salt bytes") + } + saltBytes, err := hex.DecodeString(header["salt"]) + if err != nil { + return privKey, fmt.Errorf("Error decoding salt: %v", err.Error()) + } + privKey, err = decryptPrivKey(saltBytes, encBytes, passphrase) + return privKey, err +} + +func encryptPrivKey(privKey crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte) { + saltBytes = crypto.CRandBytes(16) + key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 12) // TODO parameterize. 12 is good today (2016) + if err != nil { + cmn.Exit("Error generating bcrypt key from passphrase: " + err.Error()) + } + key = crypto.Sha256(key) // Get 32 bytes + privKeyBytes := privKey.Bytes() + return saltBytes, crypto.EncryptSymmetric(privKeyBytes, key) +} + +func decryptPrivKey(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { + key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 12) // TODO parameterize. 12 is good today (2016) + if err != nil { + cmn.Exit("Error generating bcrypt key from passphrase: " + err.Error()) + } + key = crypto.Sha256(key) // Get 32 bytes + privKeyBytes, err := crypto.DecryptSymmetric(encBytes, key) + if err != nil { + return privKey, err + } + privKey, err = crypto.PrivKeyFromBytes(privKeyBytes) + return privKey, err +} diff --git a/keys/types.go b/keys/types.go index b126f7267..4c546cca7 100644 --- a/keys/types.go +++ b/keys/types.go @@ -1,6 +1,8 @@ package keys import ( + wire "github.com/tendermint/go-wire" + crypto "github.com/tendermint/go-crypto" ) @@ -10,6 +12,15 @@ type Info struct { PubKey crypto.PubKey `json:"pubkey"` } +func (i Info) bytes() []byte { + return wire.BinaryBytes(i) +} + +func readInfo(bs []byte) (info Info, err error) { + err = wire.ReadBinaryBytes(bs, &info) + return +} + func info(name string, privKey crypto.PrivKey) Info { return Info{ Name: name, From 2d4544d6ce40d3a26e4f9ca3edb19ffae21889db Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 2 Nov 2017 18:45:37 -0500 Subject: [PATCH 175/273] Tests compile --- keys/keybase_test.go | 74 ++++++++++++++++++++++---------------------- keys/types.go | 5 +++ 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/keys/keybase_test.go b/keys/keybase_test.go index a57284e9c..bb6602b48 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -1,7 +1,6 @@ package keys_test import ( - "bytes" "fmt" "os" "testing" @@ -111,18 +110,21 @@ func TestSignVerify(t *testing.T) { d2 := []byte("some other important info!") // try signing both data with both keys... - s11 := keys.NewMockSignable(d1) - err = cstore.Sign(n1, p1, s11) + s11, pub1, err := cstore.Sign(n1, p1, d1) require.Nil(err) - s12 := keys.NewMockSignable(d2) - err = cstore.Sign(n1, p1, s12) + require.Equal(i1.PubKey, pub1) + + s12, pub1, err := cstore.Sign(n1, p1, d2) require.Nil(err) - s21 := keys.NewMockSignable(d1) - err = cstore.Sign(n2, p2, s21) + require.Equal(i1.PubKey, pub1) + + s21, pub2, err := cstore.Sign(n2, p2, d1) require.Nil(err) - s22 := keys.NewMockSignable(d2) - err = cstore.Sign(n2, p2, s22) + require.Equal(i2.PubKey, pub2) + + s22, pub2, err := cstore.Sign(n2, p2, d2) require.Nil(err) + require.Equal(i2.PubKey, pub2) // let's try to validate and make sure it only works when everything is proper cases := []struct { @@ -132,15 +134,15 @@ func TestSignVerify(t *testing.T) { valid bool }{ // proper matches - {i1.PubKey, d1, s11.Signature, true}, + {i1.PubKey, d1, s11, true}, // change data, pubkey, or signature leads to fail - {i1.PubKey, d2, s11.Signature, false}, - {i2.PubKey, d1, s11.Signature, false}, - {i1.PubKey, d1, s21.Signature, false}, + {i1.PubKey, d2, s11, false}, + {i2.PubKey, d1, s11, false}, + {i1.PubKey, d1, s21, false}, // make sure other successes - {i1.PubKey, d2, s12.Signature, true}, - {i2.PubKey, d1, s21.Signature, true}, - {i2.PubKey, d2, s22.Signature, true}, + {i1.PubKey, d2, s12, true}, + {i2.PubKey, d1, s21, true}, + {i2.PubKey, d2, s22, true}, } for i, tc := range cases { @@ -188,21 +190,22 @@ func TestSignWithLedger(t *testing.T) { d2 := []byte("please turn on the app") // try signing both data with the ledger... - s1 := keys.NewMockSignable(d1) - err = cstore.Sign(n, p, s1) + s1, pub, err := cstore.Sign(n, p, d1) require.Nil(err) - s2 := keys.NewMockSignable(d2) - err = cstore.Sign(n, p, s2) + require.Equal(info.PubKey, pub) + + s2, pub, err := cstore.Sign(n, p, d2) require.Nil(err) + require.Equal(info.PubKey, pub) // now, let's check those signatures work - assert.True(key.VerifyBytes(d1, s1.Signature)) - assert.True(key.VerifyBytes(d2, s2.Signature)) + assert.True(key.VerifyBytes(d1, s1)) + assert.True(key.VerifyBytes(d2, s2)) // and mismatched signatures don't - assert.False(key.VerifyBytes(d1, s2.Signature)) + assert.False(key.VerifyBytes(d1, s2)) } -func assertPassword(assert *assert.Assertions, cstore keys.KeyBase, name, pass, badpass string) { +func assertPassword(assert *assert.Assertions, cstore keys.Keybase, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) assert.NotNil(err) err = cstore.Update(name, pass, pass) @@ -219,21 +222,20 @@ func TestImportUnencrypted(t *testing.T) { keys.MustLoadCodec("english"), ) - key, err := keys.GenEd25519.Generate(cmn.RandBytes(16)) - require.NoError(err) + key := crypto.GenPrivKeyEd25519FromSecret(cmn.RandBytes(16)).Wrap() addr := key.PubKey().Address() name := "john" pass := "top-secret" // import raw bytes - err = cstore.Import(name, pass, "", key.Bytes()) + err := cstore.Import(name, pass, "", key.Bytes()) require.Nil(err, "%+v", err) // make sure the address matches info, err := cstore.Get(name) require.Nil(err, "%+v", err) - require.EqualValues(addr, info.Address) + require.EqualValues(addr, info.Address()) } // TestAdvancedKeyManagement verifies update, import, export functionality @@ -309,7 +311,7 @@ func TestSeedPhrase(t *testing.T) { newInfo, err := cstore.Recover(n2, p2, seed) require.Nil(err, "%+v", err) assert.Equal(n2, newInfo.Name) - assert.Equal(info.Address, newInfo.Address) + assert.Equal(info.Address(), newInfo.Address()) assert.Equal(info.PubKey, newInfo.PubKey) } @@ -339,8 +341,8 @@ func ExampleNew() { } // We need to use passphrase to generate a signature - tx := keys.NewMockSignable([]byte("deadbeef")) - err = cstore.Sign("Bob", "friend", tx) + tx := []byte("deadbeef") + sig, pub, err := cstore.Sign("Bob", "friend", tx) if err != nil { fmt.Println("don't accept real passphrase") } @@ -351,13 +353,11 @@ func ExampleNew() { fmt.Println("Get and Create return different keys") } - sigs, err := tx.Signers() - if err != nil { - fmt.Println("badly signed") - } else if bytes.Equal(sigs[0].Bytes(), binfo.PubKey.Bytes()) { + if pub.Equals(binfo.PubKey) { fmt.Println("signed by Bob") - } else { - fmt.Println("signed by someone else") + } + if !pub.VerifyBytes(tx, sig) { + fmt.Println("invalid signature") } // Output: diff --git a/keys/types.go b/keys/types.go index 4c546cca7..541234b37 100644 --- a/keys/types.go +++ b/keys/types.go @@ -12,6 +12,11 @@ type Info struct { PubKey crypto.PubKey `json:"pubkey"` } +// Address is a helper function to calculate the address from the pubkey +func (i Info) Address() []byte { + return i.PubKey.Address() +} + func (i Info) bytes() []byte { return wire.BinaryBytes(i) } From 9d78be41b5826cc5e8d52f214856c7bd55d900fe Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 13 Nov 2017 14:41:00 +0100 Subject: [PATCH 176/273] Update tmlibs to sdk-develop, fix broken test --- glide.lock | 12 ++++++------ glide.yaml | 2 +- keys/keybase.go | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/glide.lock b/glide.lock index c1400b3f9..c8c922c6a 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 86d02329c537ccb46ccb062918f0cb9e839f2cf894dfd57223c3ea4de14266db -updated: 2017-11-02T14:09:11.208038182-05:00 +hash: 765599cf3dcac232d3d2ece65c3b016d0abe55d0536adfe93d11e0dd29287de4 +updated: 2017-11-13T14:37:54.127163059+01:00 imports: - name: github.com/btcsuite/btcd version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e @@ -10,7 +10,7 @@ imports: subpackages: - base58 - name: github.com/ethanfrey/hid - version: 660bb717bd4e7cbcdf0f7cd5cadf1cb2e4be452a + version: ea8f4c923d3bc8c9c312b7d38724a294f184258a - name: github.com/ethanfrey/ledger version: 23a7bb9d74bc83a862fcb4bddde24215b2295ad9 - name: github.com/go-kit/kit @@ -60,18 +60,18 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 2baffcb6b690057568bc90ef1d457efb150b979a + version: 1c96861c03231361546944d883d99593b2e6b408 subpackages: - data - data/base58 - name: github.com/tendermint/tmlibs - version: d9525c0fb671204450b160807480e1263053fb20 + version: 56e51bc1133bd54a331e0314d5f80fb547460362 subpackages: - common - db - log - name: golang.org/x/crypto - version: bd6f299fb381e4c3393d1c4b1f0b94f5e77650c8 + version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 subpackages: - bcrypt - blowfish diff --git a/glide.yaml b/glide.yaml index a0b6650fa..64b275f10 100644 --- a/glide.yaml +++ b/glide.yaml @@ -17,7 +17,7 @@ import: subpackages: - extra25519 - package: github.com/tendermint/tmlibs - version: develop + version: sdk-develop - package: github.com/tendermint/go-wire version: develop subpackages: diff --git a/keys/keybase.go b/keys/keybase.go index 00de1ad55..14775060a 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -86,8 +86,7 @@ func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { // List loads the keys from the storage and enforces alphabetical order func (kb dbKeybase) List() ([]Info, error) { var res []Info - var more = true - for iter := kb.db.Iterator(); more; more = iter.Next() { + for iter := kb.db.Iterator(); iter.Valid(); iter.Next() { key := iter.Key() if isPub(key) { info, err := readInfo(iter.Value()) From 2649c056cd37716ab7f9dcea759874d97c22870a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 13 Nov 2017 14:54:14 +0100 Subject: [PATCH 177/273] Minor cleanup --- Makefile | 3 ++- keys/keybase.go | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index c1974c410..31ea0214a 100644 --- a/Makefile +++ b/Makefile @@ -56,11 +56,12 @@ metalinter_test: ensure_tools --enable=structcheck \ --enable=unconvert \ --enable=unused \ - --enable=vetshadow \ --enable=vet \ --enable=varcheck \ ./... + # --enable=vetshadow \ <= doesn't like assert := assert.New(t) + #--enable=dupl \ #--enable=errcheck \ #--enable=goimports \ diff --git a/keys/keybase.go b/keys/keybase.go index 14775060a..7f53b2979 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -222,11 +222,11 @@ func generate(algo string, secret []byte) (crypto.PrivKey, error) { func generateByType(typ byte, secret []byte) (crypto.PrivKey, error) { switch typ { case crypto.TypeEd25519: - return generate(crypto.NameEd25519, secret) + return crypto.GenPrivKeyEd25519FromSecret(secret).Wrap(), nil case crypto.TypeSecp256k1: - return generate(crypto.NameSecp256k1, secret) + return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap(), nil case nano.TypeLedgerEd25519: - return generate(nano.NameLedgerEd25519, secret) + return nano.NewPrivKeyLedgerEd25519Ed25519() default: err := errors.Errorf("Cannot generate keys for algorithm: %X", typ) return crypto.PrivKey{}, err From 086e1f6508e6b32159b82ded17f335abd76caaf7 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 15 Nov 2017 13:57:17 +0100 Subject: [PATCH 178/273] Make vetshadow and zach happy --- Makefile | 2 +- encode_test.go | 4 +--- keys/ecc_test.go | 6 +++--- keys/keybase_test.go | 18 +++++++++--------- keys/wordcodec_test.go | 12 ++++++------ nano/keys_test.go | 10 +++++----- nano/sign_test.go | 9 +++++---- signature_test.go | 6 ++---- 8 files changed, 32 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 31ea0214a..9e2530a94 100644 --- a/Makefile +++ b/Makefile @@ -58,9 +58,9 @@ metalinter_test: ensure_tools --enable=unused \ --enable=vet \ --enable=varcheck \ + --enable=vetshadow \ ./... - # --enable=vetshadow \ <= doesn't like assert := assert.New(t) #--enable=dupl \ #--enable=errcheck \ diff --git a/encode_test.go b/encode_test.go index 1b70d88ec..947d91901 100644 --- a/encode_test.go +++ b/encode_test.go @@ -145,8 +145,6 @@ func (s SigMessage) Bytes() []byte { } func TestEmbededWireEncodings(t *testing.T) { - assert := assert.New(t) - cases := []struct { privKey PrivKey keyType byte @@ -171,7 +169,7 @@ func TestEmbededWireEncodings(t *testing.T) { for i, tc := range cases { pubKey := tc.privKey.PubKey() sig := tc.privKey.Sign(payload) - assert.True(pubKey.VerifyBytes(payload, sig), "%d", i) + assert.True(t, pubKey.VerifyBytes(payload, sig), "%d", i) msg := SigMessage{ Key: pubKey, diff --git a/keys/ecc_test.go b/keys/ecc_test.go index d6b536aaa..6d3e3bec8 100644 --- a/keys/ecc_test.go +++ b/keys/ecc_test.go @@ -3,7 +3,7 @@ package keys import ( "testing" - "github.com/stretchr/testify/assert" + asrt "github.com/stretchr/testify/assert" cmn "github.com/tendermint/tmlibs/common" ) @@ -21,7 +21,7 @@ var codecs = []ECC{ // TestECCPasses makes sure that the AddECC/CheckECC methods are symetric func TestECCPasses(t *testing.T) { - assert := assert.New(t) + assert := asrt.New(t) checks := append(codecs, NoECC{}) @@ -41,7 +41,7 @@ func TestECCPasses(t *testing.T) { // TestECCFails makes sure random data will (usually) fail the checksum func TestECCFails(t *testing.T) { - assert := assert.New(t) + assert := asrt.New(t) checks := codecs attempts := 2000 diff --git a/keys/keybase_test.go b/keys/keybase_test.go index bb6602b48..72476a02e 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -5,8 +5,8 @@ import ( "os" "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + asrt "github.com/stretchr/testify/assert" + rqr "github.com/stretchr/testify/require" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" @@ -18,7 +18,7 @@ import ( // TestKeyManagement makes sure we can manipulate these keys well func TestKeyManagement(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -86,7 +86,7 @@ func TestKeyManagement(t *testing.T) { // TestSignVerify does some detailed checks on how we sign and validate // signatures func TestSignVerify(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -157,7 +157,7 @@ func TestSignVerify(t *testing.T) { // This test will only succeed with a ledger attached to the computer // and the cosmos app open func TestSignWithLedger(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) if os.Getenv("WITH_LEDGER") == "" { t.Skip("Set WITH_LEDGER to run code on real ledger") } @@ -205,7 +205,7 @@ func TestSignWithLedger(t *testing.T) { assert.False(key.VerifyBytes(d1, s2)) } -func assertPassword(assert *assert.Assertions, cstore keys.Keybase, name, pass, badpass string) { +func assertPassword(assert *asrt.Assertions, cstore keys.Keybase, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) assert.NotNil(err) err = cstore.Update(name, pass, pass) @@ -214,7 +214,7 @@ func assertPassword(assert *assert.Assertions, cstore keys.Keybase, name, pass, // TestImportUnencrypted tests accepting raw priv keys bytes as input func TestImportUnencrypted(t *testing.T) { - require := require.New(t) + require := rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -240,7 +240,7 @@ func TestImportUnencrypted(t *testing.T) { // TestAdvancedKeyManagement verifies update, import, export functionality func TestAdvancedKeyManagement(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -283,7 +283,7 @@ func TestAdvancedKeyManagement(t *testing.T) { // TestSeedPhrase verifies restoring from a seed phrase func TestSeedPhrase(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( diff --git a/keys/wordcodec_test.go b/keys/wordcodec_test.go index a44607be2..f79ebcad0 100644 --- a/keys/wordcodec_test.go +++ b/keys/wordcodec_test.go @@ -3,14 +3,14 @@ package keys import ( "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + asrt "github.com/stretchr/testify/assert" + rqr "github.com/stretchr/testify/require" cmn "github.com/tendermint/tmlibs/common" ) func TestLengthCalc(t *testing.T) { - assert := assert.New(t) + assert := asrt.New(t) cases := []struct { bytes, words int @@ -50,7 +50,7 @@ func TestLengthCalc(t *testing.T) { } func TestEncodeDecode(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) codec, err := LoadCodec("english") require.Nil(err, "%+v", err) @@ -82,7 +82,7 @@ func TestEncodeDecode(t *testing.T) { } func TestCheckInvalidLists(t *testing.T) { - assert := assert.New(t) + assert := asrt.New(t) trivial := []string{"abc", "def"} short := make([]string, 1234) @@ -144,7 +144,7 @@ func getDiffWord(c *WordCodec, not string) string { } func TestCheckTypoDetection(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) banks := []string{"english", "spanish", "japanese", "chinese_simplified"} diff --git a/nano/keys_test.go b/nano/keys_test.go index 15aa0d545..2e5142e30 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -5,14 +5,14 @@ import ( "os" "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + asrt "github.com/stretchr/testify/assert" + rqr "github.com/stretchr/testify/require" crypto "github.com/tendermint/go-crypto" ) func TestLedgerKeys(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) cases := []struct { msg, pubkey, sig string @@ -76,7 +76,7 @@ func TestLedgerKeys(t *testing.T) { } func TestRealLedger(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) if os.Getenv("WITH_LEDGER") == "" { t.Skip("Set WITH_LEDGER to run code on real ledger") @@ -115,7 +115,7 @@ func TestRealLedger(t *testing.T) { // TestRealLedgerErrorHandling calls. These tests assume // the ledger is not plugged in.... func TestRealLedgerErrorHandling(t *testing.T) { - require := require.New(t) + require := rqr.New(t) if os.Getenv("WITH_LEDGER") != "" { t.Skip("Skipping on WITH_LEDGER as it tests unplugged cases") diff --git a/nano/sign_test.go b/nano/sign_test.go index 04a6d0be7..18e4e0d0b 100644 --- a/nano/sign_test.go +++ b/nano/sign_test.go @@ -5,8 +5,9 @@ import ( "testing" "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + asrt "github.com/stretchr/testify/assert" + rqr "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" ) @@ -29,7 +30,7 @@ func parseSig(data []byte) (key crypto.Signature, err error) { } func TestParseDigest(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) cases := []struct { output string @@ -91,7 +92,7 @@ func toBytes(c cryptoCase) (msg, key, sig []byte, err error) { } func TestCryptoConvert(t *testing.T) { - assert, require := assert.New(t), require.New(t) + assert, require := asrt.New(t), rqr.New(t) cases := []cryptoCase{ 0: { diff --git a/signature_test.go b/signature_test.go index 5e9f06723..6659c5b9d 100644 --- a/signature_test.go +++ b/signature_test.go @@ -109,8 +109,6 @@ func TestSignatureEncodings(t *testing.T) { } func TestWrapping(t *testing.T) { - assert := assert.New(t) - // construct some basic constructs msg := CRandBytes(128) priv := GenPrivKeyEd25519() @@ -126,7 +124,7 @@ func TestWrapping(t *testing.T) { } for _, p := range pubs { _, ok := p.PubKeyInner.(PubKey) - assert.False(ok) + assert.False(t, ok) } sigs := []Signature{ @@ -137,7 +135,7 @@ func TestWrapping(t *testing.T) { } for _, s := range sigs { _, ok := s.SignatureInner.(Signature) - assert.False(ok) + assert.False(t, ok) } } From eaf4b8c79500e7be9b227c5dca8b9813bb75842d Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 21 Dec 2017 19:51:57 -0500 Subject: [PATCH 179/273] fix Equals --- priv_key.go | 16 ++++++---------- signature.go | 16 ++++------------ signature_test.go | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/priv_key.go b/priv_key.go index 456985615..613d94593 100644 --- a/priv_key.go +++ b/priv_key.go @@ -55,13 +55,11 @@ func (privKey PrivKeyEd25519) PubKey() PubKey { return PubKeyEd25519(pubBytes).Wrap() } +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the keys. func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { if otherEd, ok := other.Unwrap().(PrivKeyEd25519); ok { - // It is essential that we constant time compare - // private keys and signatures instead of bytes.Equal, - // to avoid susceptibility to timing/side channel attacks. - // See Issue https://github.com/tendermint/go-crypto/issues/43 - return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 0 + return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 } else { return false } @@ -146,13 +144,11 @@ func (privKey PrivKeySecp256k1) PubKey() PubKey { return pub.Wrap() } +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the keys. func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { if otherSecp, ok := other.Unwrap().(PrivKeySecp256k1); ok { - // It is essential that we constant time compare - // private keys and signatures instead of bytes.Equal, - // to avoid susceptibility to timing/side channel attacks. - // See Issue https://github.com/tendermint/go-crypto/issues/43 - return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 0 + return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 1 } else { return false } diff --git a/signature.go b/signature.go index fb07aba96..be1f24905 100644 --- a/signature.go +++ b/signature.go @@ -1,7 +1,7 @@ package crypto import ( - "crypto/subtle" + "bytes" "fmt" "github.com/tendermint/go-wire" @@ -46,11 +46,7 @@ func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fing func (sig SignatureEd25519) Equals(other Signature) bool { if otherEd, ok := other.Unwrap().(SignatureEd25519); ok { - // It is essential that we constant time compare - // private keys and signatures instead of bytes.Equal, - // to avoid susceptibility to timing/side channel attacks. - // See Issue https://github.com/tendermint/go-crypto/issues/43 - return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 0 + return bytes.Equal(sig[:], otherEd[:]) } else { return false } @@ -85,12 +81,8 @@ func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } func (sig SignatureSecp256k1) Equals(other Signature) bool { - if otherEd, ok := other.Unwrap().(SignatureSecp256k1); ok { - // It is essential that we constant time compare - // private keys and signatures instead of bytes.Equal, - // to avoid susceptibility to timing/side channel attacks. - // See Issue https://github.com/tendermint/go-crypto/issues/43 - return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 0 + if otherSecp, ok := other.Unwrap().(SignatureSecp256k1); ok { + return bytes.Equal(sig[:], otherSecp[:]) } else { return false } diff --git a/signature_test.go b/signature_test.go index 5e9f06723..4801e5fef 100644 --- a/signature_test.go +++ b/signature_test.go @@ -141,3 +141,27 @@ func TestWrapping(t *testing.T) { } } + +func TestPrivKeyEquality(t *testing.T) { + { + privKey := GenPrivKeySecp256k1().Wrap() + privKey2 := GenPrivKeySecp256k1().Wrap() + assert.False(t, privKey.Equals(privKey2)) + assert.False(t, privKey2.Equals(privKey)) + + privKeyCopy := privKey // copy + assert.True(t, privKey.Equals(privKeyCopy)) + assert.True(t, privKeyCopy.Equals(privKey)) + } + + { + privKey := GenPrivKeyEd25519().Wrap() + privKey2 := GenPrivKeyEd25519().Wrap() + assert.False(t, privKey.Equals(privKey2)) + assert.False(t, privKey2.Equals(privKey)) + + privKeyCopy := privKey // copy + assert.True(t, privKey.Equals(privKeyCopy)) + assert.True(t, privKeyCopy.Equals(privKey)) + } +} From 62115b55ef895f154ea70e999532d3d682c1ab20 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Fri, 22 Dec 2017 23:16:31 -0700 Subject: [PATCH 180/273] CRandHex: fix up doc to mention length of digits The previous doc seemed misleading and was out of date i.e. RandHex(24) not CRandHex. Anyways provide a doc of what the function does in relation to the length of digits of the hex value returned i.e. floor(numDigits / 2) * 2 so the even lowest number e.g: * len(CRandHex(5)) = 4 * len(CRandHex(4)) = 4 --- random.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/random.go b/random.go index 40cbcf8fa..46754219d 100644 --- a/random.go +++ b/random.go @@ -44,7 +44,10 @@ func CRandBytes(numBytes int) []byte { return b } -// RandHex(24) gives 96 bits of randomness, strong enough for most purposes. +// CRandHex returns a hex encoded string that's floor(numDigits/2) * 2 long. +// +// Note: CRandHex(24) gives 96 bits of randomness that +// are usually strong enough for most purposes. func CRandHex(numDigits int) string { return hex.EncodeToString(CRandBytes(numDigits / 2)) } From 9472476a8b5814d42b96881e28a01536acfdabb3 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 26 Dec 2017 00:28:07 -0800 Subject: [PATCH 181/273] Update Makefile --- Makefile | 107 ++++++++++++++++++++++++-------------- keys/wordlist/wordlist.go | 30 +++++------ 2 files changed, 83 insertions(+), 54 deletions(-) diff --git a/Makefile b/Makefile index 9e2530a94..6f23f8ef7 100644 --- a/Makefile +++ b/Makefile @@ -1,70 +1,99 @@ -.PHONEY: all test install get_vendor_deps ensure_tools codegen wordlist - GOTOOLS = \ github.com/Masterminds/glide \ github.com/jteeuwen/go-bindata/go-bindata \ - github.com/alecthomas/gometalinter + gopkg.in/alecthomas/gometalinter.v2 \ +GOTOOLS_CHECK = glide go-bindata gometalinter.v2 -REPO:=github.com/tendermint/go-crypto +all: check get_vendor_deps build test install metalinter -all: get_vendor_deps metalinter_test test +check: check_tools -test: - go test -p 1 `glide novendor` -get_vendor_deps: ensure_tools +######################################## +### Build + +wordlist: + # Generating wordlist.go... + go-bindata -ignore ".*\.go" -o keys/wordlist/wordlist.go -pkg "wordlist" keys/wordlist/... + +build: wordlist + # Nothing else to build! + +install: + # Nothing to install! + + +######################################## +### Tools & dependencies + +check_tools: + @# https://stackoverflow.com/a/25668869 + @echo "Found tools: $(foreach tool,$(GOTOOLS_CHECK),\ + $(if $(shell which $(tool)),$(tool),$(error "No $(tool) in PATH")))" + +get_tools: + @echo "--> Installing tools" + go get -u -v $(GOTOOLS) + @gometalinter.v2 --install + +update_tools: + @echo "--> Updating tools" + @go get -u $(GOTOOLS) + +get_vendor_deps: @rm -rf vendor/ @echo "--> Running glide install" @glide install -ensure_tools: - go get $(GOTOOLS) -wordlist: - go-bindata -ignore ".*\.go" -o keys/wordlist/wordlist.go -pkg "wordlist" keys/wordlist/... +######################################## +### Testing -prepgen: install - go install ./vendor/github.com/btcsuite/btcutil/base58 - go install ./vendor/github.com/stretchr/testify/assert - go install ./vendor/github.com/stretchr/testify/require - go install ./vendor/golang.org/x/crypto/bcrypt +test: + go test -p 1 `glide novendor` -codegen: - @echo "--> regenerating all interface wrappers" - @gen - @echo "Done!" -metalinter: ensure_tools - @gometalinter --install - gometalinter --vendor --deadline=600s --enable-all --disable=lll ./... +######################################## +### Formatting, linting, and vetting -metalinter_test: ensure_tools - @gometalinter --install - gometalinter --vendor --deadline=600s --disable-all \ +fmt: + @go fmt ./... + +metalinter: + @echo "==> Running linter" + gometalinter.v2 --vendor --deadline=600s --disable-all \ + --enable=maligned \ --enable=deadcode \ - --enable=gas \ --enable=goconst \ - --enable=gocyclo \ + --enable=goimports \ --enable=gosimple \ - --enable=ineffassign \ - --enable=interfacer \ - --enable=maligned \ + --enable=ineffassign \ --enable=megacheck \ - --enable=misspell \ - --enable=safesql \ + --enable=misspell \ --enable=staticcheck \ + --enable=safesql \ --enable=structcheck \ - --enable=unconvert \ + --enable=unconvert \ --enable=unused \ - --enable=vet \ --enable=varcheck \ --enable=vetshadow \ ./... - - + #--enable=gas \ #--enable=dupl \ #--enable=errcheck \ - #--enable=goimports \ + #--enable=gocyclo \ #--enable=golint \ <== comments on anything exported #--enable=gotype \ + #--enable=interfacer \ #--enable=unparam \ + #--enable=vet \ + +metalinter_all: + protoc $(INCLUDE) --lint_out=. types/*.proto + gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... + + +# To avoid unintended conflicts with file names, always add to .PHONY +# unless there is a reason not to. +# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html +.PHONEY: check wordlist build install check_tools get_tools update_tools get_vendor_deps test fmt metalinter metalinter_all diff --git a/keys/wordlist/wordlist.go b/keys/wordlist/wordlist.go index 58ff41181..dd531b6dd 100644 --- a/keys/wordlist/wordlist.go +++ b/keys/wordlist/wordlist.go @@ -71,7 +71,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _keysWordlistChinese_simplifiedTxt = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x1c\x97\x55\x76\xeb\x30\x14\x45\xff\xf7\xa8\xc3\xcc\x49\xc3\x69\x98\xda\x86\xd9\x0e\x4c\xc6\xf7\x4a\x9a\xc5\x5b\x7e\x7f\x5d\x5d\x6d\x6c\x45\x07\xf6\x31\xdd\x04\xc1\x3d\x82\xb6\x77\x48\x7f\x45\x70\x2f\x12\x78\x29\xb4\x9f\x45\x6a\x05\x02\xcf\xc3\x7e\x3a\x04\xf7\x0d\x32\x5b\x12\xdc\x3d\x82\x7b\x8e\xe0\xfe\x83\xf4\x5e\x68\xa6\x4a\xe0\xcf\xb1\x8b\x28\x81\xdf\x44\x5b\x57\x74\x30\xc7\x34\x56\x04\xfe\x1f\xa6\x31\x44\x32\x7b\x82\x57\x1f\xe9\xef\x09\xbc\x12\x92\xf6\x90\xfd\x01\xc9\xa4\x90\xdd\x03\xcd\x54\x08\x9e\x5d\xa4\xbc\x23\xb8\xfb\x48\xb9\x8a\x3c\xce\x48\x6e\x85\x54\x0a\xc8\x6d\x4e\xf0\x18\x62\xe3\x2f\x82\x7b\x1e\xfb\x49\x23\x9b\x0a\x76\x77\x26\xf0\x96\x98\x65\x11\x37\x98\x60\x23\x05\xb4\xf9\x40\x2a\x25\x64\xd6\x45\xb6\x5d\xec\xb8\x80\x6c\x16\xe8\xe9\x0b\xcd\x46\xd0\x7d\x15\x79\xb7\x30\x7e\x19\x29\x46\x09\xee\x59\x82\x47\xf8\x99\x3d\xcc\x20\x82\xd9\x64\x71\xf1\x15\xe2\x2d\x90\xed\x15\xd3\xb8\x20\xb9\x1e\x2e\x5d\x40\x16\x31\x74\x7f\x46\x0a\x4d\xdc\x6f\x1b\x9b\xfe\x21\xf0\x0a\x98\x4a\x0a\x7b\xb9\x21\xfb\x32\x26\xbb\xc6\x94\xf6\xc8\xf6\x1b\xc9\x8d\x70\xe9\x32\xee\xff\x7b\xcf\x08\x5e\x75\x24\x73\x45\xfb\x1e\xf2\xaa\x13\xbc\x3e\x98\xd8\x83\xc0\x2f\x11\xdc\xbb\x68\xff\x0f\x29\xf9\x68\x2e\x87\x46\x96\xc8\xfc\x85\x78\x0d\xe4\x19\x41\xb6\x71\xa4\x92\xc1\x7e\xda\x48\x6f\x84\x69\x1c\x90\xe4\x95\xc0\xeb\x61\x12\x57\x24\x5b\x44\x66\x4d\x64\xb6\x46\x1b\x1f\xa4\xd7\x43\x5b\x73\x5c\x6c\x8a\x99\xbd\x09\x1e\x59\x02\x2f\x8f\x3c\x4e\xc8\x6b\x82\xe9\xdd\x91\xe4\x0a\x3b\x5e\xe1\x5a\x67\x74\x74\x23\xb8\x97\x90\xe4\x09\xa9\x24\x70\xe9\x22\xda\xdc\x63\xbc\x0f\x92\x4a\xa2\x5f\x7b\x74\x33\x45\x3e\x71\xa4\x5c\x24\x78\x8d\xd0\x76\x09\xd3\xcf\x23\xa5\x21\x52\xce\x10\x3c\x32\x48\x66\x8d\xee\x1a\x68\xa6\x49\xf0\x4a\x61\xcf\x2b\x74\xdf\xc0\xfc\xfd\x21\x95\x2a\x2e\x5a\x47\xaa\x2f\x74\x33\x43\xca\x6d\x74\x30\x46\xca\x3f\xe8\x71\x8c\xf1\xeb\xd8\xe5\x14\xd7\xda\xa2\x89\x32\xe2\x7b\x68\x3f\x83\x24\xff\xd0\xd6\x08\x73\xf2\x91\x54\x0f\x79\x67\xd0\x78\x12\x1b\x49\xa2\xfd\x08\xe6\x37\x4f\xe0\x4f\xd1\xf8\x09\xb9\x1d\x71\x91\x2e\xf2\xb8\xa2\xe5\x0a\xa6\x77\xc6\x4d\xda\x48\xb2\x8b\x59\xe5\x91\xc3\x17\x81\xd7\x40\xbf\xfb\x68\xb3\x83\x3d\x8c\x91\x6a\x1b\x37\x58\x13\xbc\x8a\x48\x72\x8e\xdc\xef\x68\x33\x8d\x46\x7c\xf4\x6f\x8c\xd4\xa3\xc8\xb3\x8c\x9e\x7d\xec\xf6\x8d\x94\x73\x98\xed\x18\x93\x0d\xef\xee\x8a\xfb\xfa\xa0\x87\x18\x36\x12\x45\x66\x67\x64\xe8\x61\x2f\x09\xec\xfb\x81\x5e\xa2\xd8\xdb\x0e\xe3\x2d\x91\x50\x7b\xbd\x37\x72\x38\x60\xfc\x21\x5a\x9a\x63\x86\x73\xec\x3b\x8e\xec\x53\x18\x3f\x81\x5d\x46\xb1\xdb\x31\x92\xf9\x45\xe6\x0f\x34\x9b\xc7\x2e\x6b\x68\x7f\x88\x8e\x1e\xd8\x6d\xe8\xc7\x0a\x92\xea\xa3\x85\x34\x92\x1e\x11\x3c\x06\x48\xc1\x43\x9e\x1e\xda\x78\x23\xa9\x13\x76\xfe\xc1\x4e\x7e\x91\xc7\x11\x89\x76\x91\x4f\x12\xcd\x84\xdf\x43\x06\xe9\x7d\x23\x99\x0e\x81\x1f\x7a\xad\x89\x16\xb7\xc8\x2c\x81\x6b\x0f\x91\x62\xe8\x8d\x0e\x36\x7b\x44\x92\x59\x5c\x6b\x85\x14\x4f\x04\x9f\x01\x7a\xf4\x91\x42\x0b\x17\x19\x61\x3a\x6f\xec\x32\x81\x89\x6f\x70\x93\x14\xc1\x3d\x8e\x86\x1e\x28\x4f\x09\xee\x7d\x64\xf7\x44\x3a\x2b\xa4\x94\x47\x3e\x2d\x82\x7b\x13\x97\xae\x22\x93\x6f\x02\x2f\x8b\x5e\x4a\xb8\xf6\x15\x3d\x3e\xd0\xc8\x00\xed\xef\xd0\xef\x28\x81\x17\xea\xa2\x85\x8d\x36\x08\xfc\x08\x76\x3b\x43\x92\x1b\x24\x79\x40\x07\x71\xb4\x71\xc5\xee\xa2\x68\xe3\x81\xde\x93\x98\x77\x09\x49\x15\x71\xe9\x34\xf6\xf5\x87\xf6\xce\x48\xf1\x0b\x37\x2d\x21\x99\x34\x9a\xad\x63\x3a\x2f\xf4\xab\x83\x8b\x0c\xb1\xb9\x03\x72\x0f\xbd\x9d\x45\xfa\x1e\xd6\xfb\xc5\xbe\x16\x04\xef\x3c\xa6\x3f\x44\x72\x63\x24\x19\x7a\x21\x8d\xee\xca\x98\xde\x16\x9b\x3e\x61\xdf\x6f\xec\x65\x8f\x59\xee\x30\x33\x0f\xbb\xdd\x22\xd3\x3d\x9a\x9b\xa3\xcd\x16\xb2\x2d\x60\x0e\x3e\x92\xfc\xc5\x2c\x7c\xa4\x58\x42\x2a\x45\xcc\x78\x8b\x66\x8b\x98\x65\x15\x79\x8e\x08\x3e\x63\xdc\xfa\x0f\x9b\x8b\x61\x77\x03\xcc\xe1\x84\x7e\x9d\x31\x6b\x0f\x49\xc6\x91\xd4\x85\xc0\xcf\xe1\x7a\x29\xf4\xbe\x26\x78\x8e\x90\xfe\x10\xbb\xbd\xa3\x9b\x39\xe6\x3d\x43\x1e\x1f\xcc\xf0\x84\xdd\xee\x71\xfd\x08\xba\xbd\x60\x46\x0d\xcc\x57\x01\xcd\x67\xd1\xef\x16\xf2\xce\x23\xe5\x5f\x82\x7b\x03\xb3\xbe\x62\x97\x31\xec\x35\x87\xf1\xd3\xd8\x69\x12\x79\x1d\x30\xdb\x16\xc1\xab\x84\x16\xa2\xb8\xe1\x89\xe0\xd9\x22\x78\x2c\x90\x7b\x1c\x99\x15\x91\xed\x03\x49\x7c\x70\x63\x1f\xd7\x49\x22\x5f\x29\xdc\xe0\x1b\xf7\x53\xc0\x7e\xbe\xd1\xe6\x06\xbd\x1d\x70\xdd\x37\xf6\x53\xc5\x0c\x3f\x48\x31\x8e\x54\x57\xc8\xb2\x81\x39\x8f\xd0\x5c\x04\x99\xa5\x91\x62\x0e\xc9\x7d\xe3\x06\x35\x4c\x3f\x8a\x64\xc2\x67\x8d\x90\x7a\x11\xe3\x2d\xd0\xc6\x0e\x9b\xf9\x43\xca\x47\x34\x11\xde\xc3\x89\xe0\x1d\xe6\xd8\x04\x79\x47\x70\xc9\x3b\x52\x4a\x21\xf7\x18\x92\xcc\x13\xbc\xbe\x70\x9d\x19\x7a\xcd\xa0\xdf\x09\xc4\xeb\x63\x96\x7b\x64\xf6\x83\xa4\x53\x98\xe3\x1b\x89\x3c\x91\xf2\x0d\x53\x4a\xa3\xad\x32\xc6\x3f\x23\x99\x1a\x2e\x92\x45\x47\x69\x24\xd5\x41\x36\x6d\x24\xd2\x41\x77\x3d\x02\xef\x88\x7c\x7e\xd1\xaf\x0c\xda\xdc\xe1\x3a\x13\x74\x38\x47\x0f\x43\xe4\x3b\xd4\xc7\x13\x53\xca\xa3\x85\xf0\xff\x9f\x48\xd2\x47\xdb\x75\xcc\x6b\x8b\x9e\x43\x5f\xc7\x30\xd9\x34\xb2\xcc\x23\xc5\x33\xc1\xbd\x8e\xc9\x5d\xb1\xb1\x23\x52\x8a\x11\x78\x7f\xd8\x5d\x0a\x17\x89\x21\x87\x6f\xa4\x9f\x42\x0a\x49\x4c\xf4\x97\xe0\x55\xc6\xee\xe3\xa8\x3f\x46\x4a\x1f\xe4\x10\xc1\x24\x97\x48\x39\x86\xf1\x26\x18\x3f\x85\x3c\xbf\x90\x4a\xf8\x19\x73\x5c\x3d\xec\xdb\x50\xa7\x73\xdc\xa2\x89\x78\x5f\xe8\xf5\x88\x6c\xdb\xc8\xfb\x86\xeb\x96\x31\xad\x24\x36\x5f\x46\x66\x07\x64\xdf\x40\x37\x61\x7e\x1d\x71\xc9\x22\x32\x3f\xe1\xfc\x04\x5a\x5a\xa1\xed\x37\x76\x9f\xc1\xbc\x7e\x30\xf3\x6f\x6c\xd6\x43\xaa\x13\x24\xec\xfc\xca\x2f\xc1\x33\x8a\xf6\x7b\xc8\x2e\x85\x66\x1f\xd8\xca\x1c\x37\x7e\xe0\xda\x47\x82\xfb\x1b\x53\x89\x63\xf3\x07\x74\xbf\x44\x72\x1f\xa4\x9a\x43\x07\x25\xa4\xbc\xc7\x56\x5e\x68\x7f\x85\xdc\xb7\xd8\xd7\x16\x33\x0a\x3b\xbb\x8b\xdc\xc3\x1c\x3a\xa3\xa7\x15\xf6\xd3\x47\x36\x2d\x74\x50\x41\x4b\x35\x82\x77\x0f\x3d\x9e\xd0\x30\x4f\xf7\x51\xa4\xbc\x40\x9b\x2f\x24\x5d\x46\x47\x55\xd4\xbb\xa2\x91\x12\xba\x99\xa0\xe3\x0c\x76\x15\x41\xa6\xbf\xc8\x20\x8d\x6e\x16\x48\xcf\x43\xca\x57\xdc\xe1\x89\x9e\x26\xd8\x65\x8a\xc0\x4f\x62\xcf\x0f\xcc\x79\x89\xc9\x1c\x90\xdb\x02\xf3\x3b\x42\x5b\x6b\xb4\x3f\x40\xb6\x27\x8c\xbf\xc1\xbe\x7c\xb4\x5f\xc4\xee\xc2\x0c\x19\x22\xc9\x24\x92\xbc\xa0\x5e\x05\xc9\xcc\xd0\x5c\x98\x4f\x77\xec\xf5\x84\x0e\x2b\x18\x3f\x8e\xdc\xc2\x8c\x38\xa3\x83\x0f\xa6\xb1\xc7\x75\x8a\x38\xbf\x8a\xc9\xed\xb0\xe7\x21\x92\xf6\xb1\x85\x38\xc6\x5f\x22\xc9\x33\xc1\xf3\x49\xf0\xea\x20\x83\x2e\xda\x3b\x62\xdf\x75\x82\xcf\x16\xfd\x4a\x22\xc3\x90\x5d\x7e\x91\xd9\x10\x17\x89\x62\xfe\x1a\xd8\xcc\x03\x29\x8e\x90\xf2\x09\x7b\x9e\x20\x95\x38\xb2\x2b\xa0\xed\x39\x36\x5a\xc0\x2e\xb3\xe8\x21\x8b\x69\xf8\x48\x6e\x88\xdc\xce\xd8\xdb\x10\x1b\xe6\xde\x20\x86\x9b\x7e\xa3\xd3\x08\x52\xb9\x23\xb9\x35\x52\x4c\xe3\xda\x27\x02\xaf\x86\x64\x06\x48\xa6\x87\xe6\x5a\xd8\x48\x1c\xcd\x7d\x21\x83\x32\x66\xd3\x44\xca\x33\xe4\x9d\x40\x8b\x13\xb4\xff\x83\xbd\x55\x31\x61\x8e\xd6\x26\x68\xef\x8d\xf9\x0d\xcf\x37\xc5\xfc\x76\x30\xdb\x08\xf6\xb3\xc7\xd5\x0e\x48\x76\x87\xec\x5f\xc8\x7d\x80\xec\x13\xd8\x62\x16\x49\x1d\xd1\xec\x07\x93\xff\x23\xf0\x67\xb8\x4e\x05\xd7\xfe\x20\xdb\x29\xa6\xb4\x43\xca\x05\xec\xee\x86\xbd\x26\x91\xf7\x16\xbb\x5d\xa3\xa5\x25\x72\x0b\xf5\xb8\xc3\xbe\xce\x68\xf6\x8d\x54\x16\x18\xef\x07\xd3\xcb\x11\xbc\x07\x04\xcf\x36\x6e\x7c\xc5\x8c\x23\xd8\xd7\x0b\x89\xd4\xd0\xcc\x07\xf3\x13\x45\x06\x15\xcc\x31\x8b\x7e\x15\x30\x5f\x73\x64\x3b\xc1\x4e\xa2\x48\xea\x86\x8d\xf7\x31\xfe\x00\xfd\xae\x20\x83\x16\x92\x8d\xa1\x97\x3c\x41\xf8\xce\xc5\x32\x76\x97\x45\x3e\x17\x5c\x27\x43\xe0\x17\x31\xaf\x16\xa6\x57\x41\xca\x79\xf4\x9c\xc7\x35\x3a\xd8\xfc\x02\x99\xf5\x91\x4c\x15\xb3\xf4\x71\x93\x2a\x2e\x52\xc1\x0d\x46\xe8\xed\x86\xee\x8a\x98\xe1\x06\xd3\xdd\x62\xfc\x0c\x36\xda\x45\x0f\xe1\x9d\x54\x09\xbc\x2a\x52\xff\x41\x5b\x13\xec\x2d\x7c\xe6\x2f\x12\xed\x63\xe2\x19\x64\xb6\x45\x76\x43\x4c\x7c\x89\xfd\x24\x91\x49\xe8\xaf\x39\x52\xdc\xa3\xe7\x23\x92\xf1\xd1\xfc\x1f\xfa\x89\x20\x9b\x06\x5a\xf9\xc6\x34\x42\xde\x0d\xef\x2b\x89\x8e\xee\xe8\x68\x8c\x7e\x4d\x09\xde\x17\xa4\xb2\xc4\x34\x8e\xe8\xfd\x4e\xf0\x48\x62\xcb\x7d\xa4\x7a\x42\x5b\x4b\x74\x35\x46\x1f\x4d\xec\x79\x89\x16\x87\xb8\x49\xc8\x01\x3e\xba\xfb\x45\x3b\x5b\xcc\xea\x44\xf0\xe8\x20\x8b\x0c\x3a\x2b\xa2\xd1\x1d\x9a\x5d\xe3\xea\x61\x0f\x6f\xd0\xc2\x1c\x97\xac\x21\xdb\x0c\x9a\xff\x20\x5e\x19\xe3\xdd\x91\x82\x8f\x79\x7a\xb8\x5e\xc8\xf0\x2d\x5c\x2d\x64\xc3\x36\xf2\x15\xb2\xed\x1c\x69\x1c\xb0\xbb\x1d\x76\xbb\x41\x13\xa1\x0e\xc6\xb8\x4e\x02\x5b\xba\x61\x0b\x57\xdc\xb1\x8f\x39\x6e\xd1\xe6\x0c\xd9\xac\xb1\x89\x03\x66\xfc\x8b\x8d\xcd\x91\x66\x02\xf7\xee\xa0\xcf\x06\x26\xe4\xe9\x7b\x05\x3b\x8e\xa0\x7f\x13\x74\xb2\x47\x4b\x05\x74\x53\x40\x8f\x1d\x24\xd3\x45\x1b\x3e\x76\x5f\xc7\xf4\xde\xd8\xed\x0a\xed\x74\x31\xc7\x1a\xc1\xe3\x80\x49\xc7\x31\xc3\x1e\xc1\xa3\x84\x0e\x22\xd8\xe2\x0e\xd9\x46\x71\xc7\x28\xf6\x7c\xc1\xd5\x86\x98\xe4\x0c\xbb\xf3\x31\xe5\x0d\xc1\x73\x87\x5b\x84\xec\x14\x6e\x86\x5f\xa4\x3c\x27\xb8\xef\x91\xe1\x03\x2d\x87\xec\xb0\x47\xf3\x49\xe4\xb9\xc0\xf6\xf2\xe8\x31\x8b\x44\xd3\x98\xf5\x07\xcd\x2e\x31\x9b\x06\xc1\xa3\x82\xdd\x47\x71\x63\x0f\x13\x1f\x62\x9e\x6b\xe4\x1d\xc5\x26\xee\x48\xb3\x8f\x0e\xde\xd8\x44\x17\xe9\xed\x91\x67\xd8\x77\x45\x6c\x3c\xf4\xfb\x10\xb3\x28\x13\x3c\xf6\xe8\xb0\x4e\x10\x66\x7e\xb8\x49\x92\x13\x34\xf2\x85\x99\x46\x91\x48\x11\x33\x6f\x62\xba\x69\x82\x4f\x1c\x37\xe8\x60\xc7\x73\xec\x2e\x81\xf9\xf8\xd8\x58\x16\x7b\xbb\x20\xfb\x27\x76\x3c\x45\xb6\x2f\x34\xfb\x87\x4e\xb3\xc8\xbd\x40\xf0\x9c\xa1\xf5\x22\xf2\x1d\xc3\x84\x3d\xb6\xed\xa3\xfb\x09\x32\x6f\x61\x06\x53\xb4\x10\x72\x5a\xb8\x3b\xb6\x68\xff\x17\xd9\xfe\x20\x5e\x0a\xf3\x6c\x62\xb2\x3d\xec\x72\x81\xb6\x47\xb8\xde\x0d\xd7\x88\x60\x77\x2d\x24\x64\xdf\x43\x12\xcd\xd5\xb1\xd3\x18\x36\xfe\x8d\x54\x9f\xc8\xaa\x8d\x76\x76\xc8\x2a\x8a\xf1\x3f\x68\xe7\x8a\x94\xba\x98\xde\x10\x3b\x1e\xe3\xee\x63\x64\xd3\x41\xfc\x2b\x52\x3c\x60\xe3\x57\xe4\x90\x27\x78\x8c\x09\xee\x67\x5c\x27\x85\x1b\xbf\xd1\x52\x16\xa9\x46\x30\xd1\x1d\x72\x8c\xa2\xa5\x1f\x74\x30\xc4\x46\x2a\x48\xf8\x9d\x97\xb2\xd8\xcb\x05\x7b\x3b\x21\xf5\x39\xb2\x99\x62\x77\x6f\x24\xbd\xc3\xc6\xc7\xb8\xc9\x00\xfd\x7b\x63\xfc\x22\x52\xbc\xe1\x5e\xe1\x1e\x1d\x62\x6b\x77\x74\xdb\x44\xf7\x77\x64\xdb\xc2\xe6\x5b\xc8\x6d\x80\x89\x65\x91\xe3\x1a\x79\x1e\x70\xbd\x70\xef\xae\x90\x79\x19\x3d\x7e\x70\xfd\x23\x3a\x48\xa1\xa5\x09\xea\x57\x71\x5f\x69\xdc\x7c\x83\x5e\xea\xd8\xcc\x0f\x1a\x89\x60\x2f\x57\xc4\xab\x23\x33\x8f\xe0\x99\xc3\x44\x2f\x98\x55\x09\x17\x69\x60\xa2\x1b\xec\xa5\x87\xbc\x6a\x48\xf9\x0f\xf7\xac\xa3\xb5\x0d\xa6\xd7\xc6\x4e\xa3\xb8\xce\x1a\xf1\x6e\x48\x63\x87\xbc\xbe\xb0\xe5\x02\xc6\xdb\x21\x91\x21\xe6\xd4\xc4\xf4\x9a\xe8\xea\x07\xf3\xb7\xc0\x2c\xa3\x48\xee\x07\x19\xc5\x90\xe1\x10\xfd\xfe\x41\xaf\x0b\xe4\x91\x44\xea\x19\xcc\xef\x10\x93\x0a\x7b\xe2\x17\x3d\xbd\xb0\x89\x2a\x32\x9d\x61\x26\x27\xf4\x6f\x89\x8b\x16\x09\xde\x4b\x64\xb7\x42\xbf\x26\xc8\xcb\xc7\x76\xaa\x68\xb3\x8f\x6d\x86\xcc\xb5\xc1\x78\x27\xe4\xf9\xc0\xcd\x8f\x04\xcf\x3b\x9a\x6b\xe3\x42\x9e\x7b\x7c\xd0\x6e\x0b\x5b\xbc\x61\xea\x0b\x64\xfc\x8d\x78\x39\xcc\xa6\x8a\x46\xaf\x68\xe6\x86\xdd\x7e\x90\x71\x03\x99\xa7\x71\x91\x32\x1a\x66\x73\x26\x82\xb6\x42\x6f\x85\x9d\x37\x46\xf7\x3b\x5c\x34\x4d\xe0\xbf\xd0\x5d\x0d\x3d\xcd\x71\x91\x08\x7a\x6e\xa1\xd5\x14\x26\xba\x47\x5e\x61\xa7\x35\xb1\x91\x16\x32\x2b\xa3\xf9\x35\xf2\xe9\xe0\xea\x7d\x4c\x61\x8b\x19\xff\x11\x78\x19\xcc\x23\x8a\xf4\x33\xb8\x5e\xc8\x88\x2f\x82\xf0\x3d\x73\x2f\xcc\x2e\xec\xc3\x0b\xae\x1d\x32\x5b\xc8\x1c\xe1\xc6\x7a\x21\xa3\x14\xae\x97\xc0\x7e\x4a\xe8\xa9\x87\xc9\xdc\xd1\xf9\x13\x17\xfd\x60\xf7\x79\xa4\xb2\xc2\xa5\x4b\x98\x42\x98\xe3\x2d\xcc\x79\x87\x44\xcb\x48\xf2\x8e\x5b\xa4\x30\xe7\x09\x66\xb9\xc0\x26\x62\x68\xc8\x3e\xe1\x99\x0f\x29\xe4\x13\x7a\xae\x8d\xc6\x73\xc8\x38\xdc\xc4\x2d\x34\x91\x41\xfb\x07\xb4\xf7\xc1\x78\x33\xcc\xb1\x85\x44\xde\xc8\xbe\x8b\x69\xf5\xd0\x79\x17\xfb\xdf\x87\x79\xec\x79\x83\x99\x86\xb9\xda\x43\x0f\x21\xc3\x44\x31\x93\x12\xee\x67\x85\xe9\x55\xd1\xe2\x17\xf2\x1c\xa2\xdd\x33\x92\x3d\x62\xcf\x3b\x74\x9b\xc3\xa5\x73\xd8\x5d\x91\xc0\x1b\x23\xa1\x96\xc6\x61\xee\x86\xdd\x93\x41\xf6\x6d\x5c\xcb\x47\xcb\x1b\x4c\x6c\x8b\x6e\xf3\x48\xea\x0f\x1d\xcf\x91\x45\x1a\xbb\x59\x60\xfc\x27\x9a\xef\x21\x95\x33\x81\xdf\x46\x2f\x5b\x5c\x74\x83\xbc\x2b\x68\x6c\x85\x56\xd3\xd8\xfd\x0d\x7b\xf9\xc6\x6c\xc3\x5d\xd0\xc0\x6e\x27\x98\xc6\x0d\xa9\x3c\x90\x5e\xa8\x97\x50\xbb\x15\xec\x39\xec\xe3\x3c\xa6\xe4\x23\xb7\x15\x36\x12\x72\xc7\x02\x5b\x0c\xf7\xff\x06\x7d\xbc\x71\x8d\x2d\x92\x0e\xf7\x92\x8f\x6b\x24\xd1\xaf\x50\x3b\x6b\x24\x3b\x47\xd2\x03\xcc\xe4\x80\x7b\x7d\xd0\xcc\x0f\x26\xf6\xc4\x79\x3e\xc6\xf3\x30\x8b\x28\xe2\x0d\x31\xbd\x1e\x26\x9b\xc1\x3c\xeb\x48\x3a\x82\x19\xf4\xd0\x76\x01\x59\x77\xd1\x6b\x16\xb3\xa9\x21\xed\x33\x5a\xae\x21\xc7\x3b\xda\x0f\xb3\x2a\x81\x1d\xb7\xb0\xad\x32\xb2\xac\x62\xcf\x77\x6c\xb2\x82\xcc\xcf\xc8\xd7\x02\x8d\xef\x08\x1e\x6d\x82\x67\x07\x8d\x4e\x90\x42\x04\xe3\x1d\xd0\x6c\x09\xfb\x5e\x63\x23\x27\xe4\xf5\x83\x4d\x4f\x09\xbc\x0f\xa6\x16\x32\xd5\x05\x9b\xc8\x62\x96\x11\x6c\x65\x45\xf0\x49\x60\x5e\x55\x6c\x26\xf4\x44\x0b\x69\xde\x30\xde\x05\xd9\xdd\xd1\x43\x0b\x2d\xc4\xd0\xf3\x0f\xf6\xec\xe1\x5a\x3f\xe8\xf0\x0f\x93\x49\x61\xe2\x3b\xf4\x3c\xc7\xac\x7c\x64\xd2\xc1\xbe\x76\x48\x3e\x8d\xc4\xcb\xa8\xdf\x45\x4a\x6d\x6c\xad\x83\xcd\x9d\xb0\xb1\x1d\x32\x18\xa3\xc3\x03\xb6\x38\xc6\x26\x3f\x04\x7e\xa8\xd3\x24\xb2\x7f\x63\x5f\x4b\x24\xb5\xc7\x9e\xc7\x98\x8e\x8f\xf3\x4b\x48\x36\x87\xab\xf9\x48\x3e\xdc\x48\x71\x5c\x37\xcc\xfe\x15\x2e\xbe\x41\x4e\x7b\xe4\x1e\x45\xef\x3b\x82\x67\x19\xfb\x5a\x11\x78\x6b\x74\xf7\x85\xd6\x17\xd8\xd2\x2f\x92\xf1\xd0\xcb\x0f\x66\xd9\x46\xcb\x67\x74\xf4\x83\x44\xc3\xae\xdf\x62\x63\x63\xe4\xd8\xc3\x34\xda\xe8\x69\x8c\x19\x8c\x31\xbf\xe1\x8e\x09\xcf\x3c\xc3\xb5\x23\x04\xcf\x2a\x7a\x48\x63\x33\x45\x4c\x98\xdb\xfe\x17\x26\x76\x47\xea\x47\xcc\xf4\x86\xf1\x43\x56\xcf\xa3\xb7\x31\xb2\x6f\x22\x95\x70\xa3\xdd\xd0\xe1\x19\xa9\x66\x90\x77\x0d\x37\xe9\xa3\xa7\x1f\xcc\xaa\x88\x7c\xc2\x67\x5d\xb0\xf5\x01\x9a\x6f\xa2\xe7\x6f\xb4\x94\xc1\x7d\xf5\xb1\xef\x1e\x32\xdd\xe2\x1a\xa1\x9f\x7e\xb1\x9d\x2e\xf2\xdc\xa1\xd5\x35\x1a\x9e\xf5\xf1\x44\xfc\x1b\xb2\xcf\x61\x7e\x5a\x98\x70\x1b\x3e\x13\xb8\xee\x15\xd3\xac\xa2\xfb\x32\xb2\xfd\x45\x96\x15\x5c\x3f\x8d\xa9\x7e\xa3\x91\x1f\x64\x3f\xc3\x54\xce\xc8\xfb\x07\x2d\x97\xb1\xa9\x3e\xf6\x33\x40\x66\x0f\x6c\x72\x8f\x79\xb6\x31\xe5\x11\x66\x7d\x43\xa7\x5b\xf4\x7b\x80\xf9\x7d\xa0\xc7\x21\x12\xfb\xc3\xf8\x27\xe4\x93\xc2\xc5\x16\x48\x76\x8d\x3c\xee\xe8\x25\x85\x8e\xc2\x5c\x9b\x63\xb2\x1d\xec\x79\x8b\x99\x3d\xd1\x90\xa3\x6b\x23\x8c\xf7\xc0\xbc\x26\x68\xbe\x88\x84\xfc\xdd\xcc\x61\x27\x4d\x64\x18\x47\xf2\x33\xcc\xab\x8b\x49\x2c\xd0\x57\x9f\xe0\x59\x44\x26\x2b\xf4\xef\x88\x79\x0e\x90\x65\x1d\xc9\xe4\x70\xf3\x03\x81\xff\x41\xe6\x4d\x5c\x7d\x80\xfb\x7b\x12\xdc\x5f\xd8\xdb\x0a\x17\x7a\xbd\x10\xfe\xfe\x8d\x66\x7f\x91\xe6\x00\x3b\xc9\x63\x62\x1b\xf4\x30\x46\x1e\x5f\xd8\xdd\x1d\x79\x86\xfb\xef\x80\x4e\x92\xc8\xfc\x8a\x9e\xa3\x98\xe8\x1b\x9b\x19\xe2\xb2\x67\x6c\x3e\xe4\xbd\x27\x1a\xfe\xcd\x2e\x8a\xa6\x63\x48\x98\xe9\x1d\x0f\x19\x36\x90\x5d\x02\x39\xe4\xb0\xb7\x38\x7a\x1f\xa3\x85\x2a\xc1\xfd\x81\xcd\x86\x3a\x0d\xfd\x1e\xb2\x55\xc8\x7c\x0f\x34\x73\xc6\x8c\xa2\xe8\x64\x81\x0d\x33\x3c\xd5\xc0\x5e\x66\xe8\xbd\x81\xd4\x37\xe8\xd7\x1f\x6e\xd2\x42\xe6\x0d\x5c\x3d\x49\xe0\x1f\xb1\x9d\x12\x26\xdc\x8a\x8b\x07\xc1\xa3\x8c\x29\x17\x31\x8d\x13\x3a\x2e\xe0\xa2\x17\x24\x19\xc5\x75\x53\xd8\x6f\x8f\xc0\xaf\xe3\x36\x65\x5c\xa3\x82\x76\xea\xe8\x7e\x8b\x24\x9f\xb8\x6e\x05\x33\x29\x62\x2f\xbf\x68\x7e\x85\x7c\x46\xd8\x58\x1c\xf3\xbc\x63\xb2\x17\x34\x37\x41\x8a\x5d\xe4\xb6\x44\xa6\x27\x24\x99\x40\x07\x7d\xec\x76\x87\xdd\x75\x31\x93\x25\x66\x3e\x47\x87\x3b\xdc\xf8\x82\xdc\xc6\x98\xe1\x1a\x8d\x1d\x31\xd1\x02\xee\x9d\x20\x78\x2e\x30\xf3\x15\xb2\xf3\xd1\x71\x0c\x57\xf7\x90\xfe\x14\x8d\x56\xd0\xe8\x1e\x17\xaf\x62\xaf\x53\x34\xf7\x87\x2d\xd6\xb0\xc9\x37\xf6\x7c\x46\x87\x0d\xd4\x3f\x63\x0a\x3d\x5c\xbb\x81\x7d\xa7\x90\x85\x8f\x8c\x7f\xd1\xda\x0c\x89\xad\x30\x9b\x37\xae\xf5\x40\xb3\x7b\xcc\xf9\x17\x33\x8a\xe1\xfe\x6f\xa6\x32\x52\xc9\xe1\x3a\x57\x82\x67\x05\x69\xc6\x30\xcd\x16\xa6\x7e\x45\xd6\x29\x34\xd7\xc5\xa6\x63\x68\xf5\x8e\x7c\x8a\xd8\xce\x1b\xdb\x1f\xe3\x62\x3e\x36\x7e\x47\x6e\x6b\xb4\x30\x43\xa2\x57\xe4\x19\x47\x97\x2f\x24\x77\x24\x78\x9c\x70\xb1\x3a\x52\xc9\x12\xf8\x51\x4c\x3c\x86\x19\x35\x31\xcb\x21\xc1\xa3\x80\xcd\xec\x09\x9e\x67\x4c\xbd\x8f\x5e\x92\x04\xf7\x0e\xda\x8d\x61\xd2\x73\x74\x1d\xe6\xd7\x09\xfb\xb9\xa1\xdd\x90\x2f\x0b\x98\xe5\x12\x1b\x4f\x61\x77\x0b\xcc\x7e\x89\xbd\x97\x31\xf5\x1b\x76\x7f\x40\xaa\x29\x64\xfb\xc6\x9c\x72\xe8\xb9\x87\x7d\x67\xd1\xc4\x0c\xf3\xfb\x8d\xeb\x76\xd0\x48\x0d\x73\x6c\x13\x3c\xc2\x2d\xfe\x83\x8d\xad\x31\x87\x22\xfa\x55\x46\xaf\x31\x4c\xaa\x83\xe9\xa6\x08\xde\x0b\x34\xf6\x87\x96\xda\x04\xde\x2f\xc6\x1b\xe1\x52\x35\x4c\x3e\x86\x6b\x44\xd1\x5b\x04\x8d\xae\x30\xd9\x23\xae\x7f\xc7\x64\xfe\xb0\x97\x32\x2e\x92\xc2\x94\xd6\xb8\xce\x05\x33\x1f\x60\x96\x35\xf4\xd2\xc1\x1e\x0b\xc8\xeb\x81\xbc\x9e\x68\x2c\x8b\xbb\x6f\xb0\xd7\x3c\x92\x9e\xa1\x9d\x15\xe6\x7f\x1e\x65\x30\xcb\x90\x63\x2e\x98\xd7\x11\x9d\xec\x30\xb1\x12\x1a\x66\xde\x34\x8f\x5b\x1f\x30\x9b\x1e\x72\x1a\x23\xa9\x1a\x12\xee\xd9\xdd\x07\xbb\xab\xa2\x97\x3b\x7a\x0a\xf9\xfd\x85\xfd\x0c\x31\xe3\x24\xa6\x99\xc2\x9e\x6f\xe8\xb3\x8c\x59\x7d\x90\xd4\x08\xf9\x5d\x63\xe3\x51\x6c\x6e\x87\xc9\x4e\x90\x72\x0f\xdb\x8d\x20\xf3\x39\xee\x3e\x45\x8e\x1b\xcc\x3b\x87\xa4\x37\x04\xf7\x23\x32\x6e\x63\xfc\x36\x2e\x79\xc1\x7e\x17\x31\xbd\x14\xae\x31\x46\xbc\x0e\x66\xf3\x40\x52\x3e\x36\xdc\x9b\xd5\x04\x76\xb2\xc1\x6c\xf2\x68\xbe\x86\xc4\xbb\x68\xeb\x80\xab\xbd\x71\xf7\x21\xfa\x4c\xa1\xc7\x0c\xa6\x9f\xc5\x34\xcb\xe8\xcd\x47\xa7\x35\xcc\xba\x85\x19\x0f\x70\xc3\x35\x2e\xf2\x44\xb3\x1b\x82\xf7\x0a\x49\x67\xd1\x82\x87\x99\xb4\xd0\xd1\x0b\x13\xab\xa1\x83\x1d\x1a\x9b\xe2\x16\x65\x24\x37\xc0\x1e\x7e\xb0\xef\x17\x92\x8f\xe3\xee\x1f\xb4\xb5\x40\x2a\x61\x46\xf6\x31\x21\xa7\x0f\xf3\xd8\x77\x0e\x0d\xef\x63\xbe\x45\x2b\x7f\xb8\x9f\x18\xf6\xfd\x8d\xe4\xc3\x1c\x9b\x12\x3c\xf7\xd8\x5a\x1e\xe3\xd7\x70\xbd\x37\xc1\x3d\x64\xb0\x0b\xb2\x4c\xa1\xf9\x21\xb2\x4d\x63\xdf\x55\x5c\xe7\x0b\xd7\xfb\x42\x42\xee\xab\x27\x90\x73\x1a\xc9\xfe\x20\x91\x31\x52\x4a\x22\xb5\x3f\xdc\xfa\x8a\x6d\xee\x90\xcc\x0d\x6d\xce\x31\x5f\x3f\xd8\x4b\x1e\x99\x67\x09\x5e\x3d\xf4\x92\x46\x9f\xbf\x68\x2f\x3c\x67\x1a\x57\xeb\xa0\xe3\x38\x9a\xbd\x12\xf8\x0d\xec\xa7\x41\xf0\x69\x11\x78\x65\x6c\xb2\x81\xfb\xce\xa3\xd3\x03\x76\x91\x42\xc7\x29\x34\x96\x40\xca\x0d\xb4\xf6\x8d\xfb\x69\x21\xf9\x36\xda\xf2\xd0\xe3\x1d\xd9\xcc\x90\x4a\x05\xd9\x0c\xd1\xfb\x08\x39\x64\x30\xcd\x37\xb2\xe8\xa0\xf1\x3e\x81\xbf\xc7\xe4\x47\xd8\x78\x04\xbb\xaf\xa0\xb9\x1e\xae\x9f\x45\xc7\x55\x24\xe4\xcc\x76\x0f\x3b\xde\x63\x7a\x2d\xf4\xde\xc2\x26\xca\xd8\x4b\x13\xbd\x16\x30\x8d\x3e\xda\x7b\xe0\xda\x49\x6c\xac\x80\xd4\xd7\x48\x29\x8b\x89\xc7\x31\xde\x1f\xba\x4b\xa2\xed\x15\xc1\xf3\x07\xd3\x4a\x63\x92\x5b\xa4\xfc\xc0\xd5\xb2\x68\x65\x83\x2d\x94\x30\x7f\x4f\x5c\xf2\x86\x44\x6f\xc8\xb3\x8e\x6b\xcc\xd1\x68\x78\xa7\x7b\x64\x50\xc5\x3d\x7d\xcc\xe7\x89\xf1\xae\x48\xb9\x83\xc9\x1f\x70\x91\x2d\xe6\x55\xc1\xf8\x7d\x74\xda\x45\x73\x55\x6c\x6a\x85\x6d\xfc\x21\x3b\x0f\xf7\x33\xc3\xac\x53\x48\xea\x8a\x7e\xef\x90\x54\x01\x09\x77\x5a\xfa\x8e\xf1\x93\xc8\x20\xd4\xb8\x87\x49\xec\xb1\xaf\x3d\xfa\x37\x45\x3b\x79\x4c\x7b\x81\xbc\xc7\xb8\xc6\x06\xd7\x58\x10\xdc\x97\x68\xeb\x0f\xd7\xf0\x91\xef\x04\x5a\xe9\xa3\xd9\x2a\x2e\x16\x21\xf0\x36\xb8\xe4\x0e\xfb\xc9\x60\x33\x35\x6c\x22\x85\x4b\x5e\x71\xad\x23\xf2\x59\xe2\x92\x5d\xdc\xf8\x85\x79\xbf\xd0\xeb\x0a\x29\xde\x09\xfc\x16\xae\x13\x6a\x73\x88\xc6\xd7\xe8\x60\x83\x2c\xbb\xd8\x58\x17\x2d\x66\x71\xd3\x36\xfa\x8c\xa1\xed\x14\xfa\xe7\x21\x95\x37\x2e\x5e\xc2\xc4\x6f\xe8\x21\x8a\x54\x2f\xb8\xf9\x1e\x5b\x59\xe2\x7a\x49\x5c\x6c\x8b\xfd\x44\x31\xe9\x2f\xb4\x56\x43\x96\x3e\xf6\x72\x46\xb6\x67\x4c\x7c\x81\x44\x3c\xe4\x5e\x41\x9b\x55\x5c\x3d\x8e\xb6\x56\xb8\x54\x1a\x5b\x9d\xe2\xc2\xad\xd2\x0b\x39\xf6\x83\xe6\x0b\x48\x2c\x89\x4d\x3e\x90\xc5\x1c\x2d\x67\xb1\xe7\x19\x9a\x4f\xa1\x9b\x1f\x6c\x75\x8c\x8d\x7b\x04\xf7\x09\x7a\x59\x23\xe1\x99\xda\x31\xe4\xfb\x17\x2d\x8c\xb1\xcb\x0c\xf6\xfc\x83\xfe\x67\x98\x33\x7a\x08\x7f\x2e\x20\xa9\xb0\xd7\x3c\x64\xd9\xc7\xee\xc3\xec\xb8\x22\xb9\x70\x5f\xff\x61\xc3\x9d\xd6\x2e\x63\x43\x26\xef\x65\x70\x3f\x55\x82\x47\x03\xf5\x7e\x08\xee\x3d\xa4\x38\x41\x73\x0f\x5c\xeb\x86\xd4\x56\x48\x66\x8b\x5b\xbf\x31\x61\x5e\xc4\x86\x68\xb5\x8d\xab\xd7\xd0\xd2\x0d\x37\x49\x23\x0f\x1f\x1d\x26\xd0\xf8\x08\x8d\xaf\x08\x5e\x27\x02\x3f\x8d\x4d\x86\x8c\x36\x40\xaf\x33\x24\x5b\xc5\x7c\x2f\x91\xd1\x18\x3d\x3d\xb1\xd5\x03\xe6\xb5\xc6\xf5\x8b\x68\xf1\x1b\x1b\x2f\x61\xf3\x45\xd4\x0f\x39\x7c\x8d\x16\x93\xe8\xa3\x8d\x19\x15\x71\xfd\x6f\x5c\xec\x82\xad\x24\x30\xcd\x1d\x7a\x0b\xf7\x4d\xd8\x0b\x39\xcc\xf1\x07\x13\x6f\x23\xdb\x0f\x3a\x9e\xa2\x99\x0c\x6e\x7d\x42\x7e\x63\xd8\xe9\x17\xf2\xee\x60\xb6\x1b\xb4\x58\xc1\xc6\x46\x68\xad\x8a\x76\x6a\xd8\xf7\x0a\xdd\x7e\xb0\xa5\x23\x5a\xcd\xa1\x95\x24\x2e\x79\x40\x0e\x65\x4c\xf3\x17\xa9\x47\xb0\x61\xa6\x8e\x2e\xe8\xf1\x17\xd3\x3d\x60\xbe\x92\x48\x79\x84\x6b\x47\xb1\xa5\x03\xfa\x75\xc4\xbe\x9b\xb8\xda\x1a\xd3\x0a\x77\xd2\x00\xb9\xdd\x70\xf3\x0f\x66\x7e\x27\xb8\xb7\x31\xa5\x04\xea\x85\x5e\xdd\xe3\x22\x3e\xf2\xda\x20\xfb\x70\xdb\x7d\x90\xc5\x0a\x9b\x4d\x23\x95\x6f\xdc\x70\x81\x46\x56\x98\xe1\x16\xdd\xa4\xf9\x17\x00\x00\xff\xff\xbf\x1b\x72\xe3\x00\x20\x00\x00") +var _keysWordlistChinese_simplifiedTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x1c\x97\x55\x76\xeb\x30\x14\x45\xff\xf7\xa8\xc3\xcc\x49\xc3\x69\x98\xda\x86\xd9\x0e\x4c\xc6\xf7\x4a\x9a\xc5\x5b\x7e\x7f\x5d\x5d\x6d\x6c\x45\x07\xf6\x31\xdd\x04\xc1\x3d\x82\xb6\x77\x48\x7f\x45\x70\x2f\x12\x78\x29\xb4\x9f\x45\x6a\x05\x02\xcf\xc3\x7e\x3a\x04\xf7\x0d\x32\x5b\x12\xdc\x3d\x82\x7b\x8e\xe0\xfe\x83\xf4\x5e\x68\xa6\x4a\xe0\xcf\xb1\x8b\x28\x81\xdf\x44\x5b\x57\x74\x30\xc7\x34\x56\x04\xfe\x1f\xa6\x31\x44\x32\x7b\x82\x57\x1f\xe9\xef\x09\xbc\x12\x92\xf6\x90\xfd\x01\xc9\xa4\x90\xdd\x03\xcd\x54\x08\x9e\x5d\xa4\xbc\x23\xb8\xfb\x48\xb9\x8a\x3c\xce\x48\x6e\x85\x54\x0a\xc8\x6d\x4e\xf0\x18\x62\xe3\x2f\x82\x7b\x1e\xfb\x49\x23\x9b\x0a\x76\x77\x26\xf0\x96\x98\x65\x11\x37\x98\x60\x23\x05\xb4\xf9\x40\x2a\x25\x64\xd6\x45\xb6\x5d\xec\xb8\x80\x6c\x16\xe8\xe9\x0b\xcd\x46\xd0\x7d\x15\x79\xb7\x30\x7e\x19\x29\x46\x09\xee\x59\x82\x47\xf8\x99\x3d\xcc\x20\x82\xd9\x64\x71\xf1\x15\xe2\x2d\x90\xed\x15\xd3\xb8\x20\xb9\x1e\x2e\x5d\x40\x16\x31\x74\x7f\x46\x0a\x4d\xdc\x6f\x1b\x9b\xfe\x21\xf0\x0a\x98\x4a\x0a\x7b\xb9\x21\xfb\x32\x26\xbb\xc6\x94\xf6\xc8\xf6\x1b\xc9\x8d\x70\xe9\x32\xee\xff\x7b\xcf\x08\x5e\x75\x24\x73\x45\xfb\x1e\xf2\xaa\x13\xbc\x3e\x98\xd8\x83\xc0\x2f\x11\xdc\xbb\x68\xff\x0f\x29\xf9\x68\x2e\x87\x46\x96\xc8\xfc\x85\x78\x0d\xe4\x19\x41\xb6\x71\xa4\x92\xc1\x7e\xda\x48\x6f\x84\x69\x1c\x90\xe4\x95\xc0\xeb\x61\x12\x57\x24\x5b\x44\x66\x4d\x64\xb6\x46\x1b\x1f\xa4\xd7\x43\x5b\x73\x5c\x6c\x8a\x99\xbd\x09\x1e\x59\x02\x2f\x8f\x3c\x4e\xc8\x6b\x82\xe9\xdd\x91\xe4\x0a\x3b\x5e\xe1\x5a\x67\x74\x74\x23\xb8\x97\x90\xe4\x09\xa9\x24\x70\xe9\x22\xda\xdc\x63\xbc\x0f\x92\x4a\xa2\x5f\x7b\x74\x33\x45\x3e\x71\xa4\x5c\x24\x78\x8d\xd0\x76\x09\xd3\xcf\x23\xa5\x21\x52\xce\x10\x3c\x32\x48\x66\x8d\xee\x1a\x68\xa6\x49\xf0\x4a\x61\xcf\x2b\x74\xdf\xc0\xfc\xfd\x21\x95\x2a\x2e\x5a\x47\xaa\x2f\x74\x33\x43\xca\x6d\x74\x30\x46\xca\x3f\xe8\x71\x8c\xf1\xeb\xd8\xe5\x14\xd7\xda\xa2\x89\x32\xe2\x7b\x68\x3f\x83\x24\xff\xd0\xd6\x08\x73\xf2\x91\x54\x0f\x79\x67\xd0\x78\x12\x1b\x49\xa2\xfd\x08\xe6\x37\x4f\xe0\x4f\xd1\xf8\x09\xb9\x1d\x71\x91\x2e\xf2\xb8\xa2\xe5\x0a\xa6\x77\xc6\x4d\xda\x48\xb2\x8b\x59\xe5\x91\xc3\x17\x81\xd7\x40\xbf\xfb\x68\xb3\x83\x3d\x8c\x91\x6a\x1b\x37\x58\x13\xbc\x8a\x48\x72\x8e\xdc\xef\x68\x33\x8d\x46\x7c\xf4\x6f\x8c\xd4\xa3\xc8\xb3\x8c\x9e\x7d\xec\xf6\x8d\x94\x73\x98\xed\x18\x93\x0d\xef\xee\x8a\xfb\xfa\xa0\x87\x18\x36\x12\x45\x66\x67\x64\xe8\x61\x2f\x09\xec\xfb\x81\x5e\xa2\xd8\xdb\x0e\xe3\x2d\x91\x50\x7b\xbd\x37\x72\x38\x60\xfc\x21\x5a\x9a\x63\x86\x73\xec\x3b\x8e\xec\x53\x18\x3f\x81\x5d\x46\xb1\xdb\x31\x92\xf9\x45\xe6\x0f\x34\x9b\xc7\x2e\x6b\x68\x7f\x88\x8e\x1e\xd8\x6d\xe8\xc7\x0a\x92\xea\xa3\x85\x34\x92\x1e\x11\x3c\x06\x48\xc1\x43\x9e\x1e\xda\x78\x23\xa9\x13\x76\xfe\xc1\x4e\x7e\x91\xc7\x11\x89\x76\x91\x4f\x12\xcd\x84\xdf\x43\x06\xe9\x7d\x23\x99\x0e\x81\x1f\x7a\xad\x89\x16\xb7\xc8\x2c\x81\x6b\x0f\x91\x62\xe8\x8d\x0e\x36\x7b\x44\x92\x59\x5c\x6b\x85\x14\x4f\x04\x9f\x01\x7a\xf4\x91\x42\x0b\x17\x19\x61\x3a\x6f\xec\x32\x81\x89\x6f\x70\x93\x14\xc1\x3d\x8e\x86\x1e\x28\x4f\x09\xee\x7d\x64\xf7\x44\x3a\x2b\xa4\x94\x47\x3e\x2d\x82\x7b\x13\x97\xae\x22\x93\x6f\x02\x2f\x8b\x5e\x4a\xb8\xf6\x15\x3d\x3e\xd0\xc8\x00\xed\xef\xd0\xef\x28\x81\x17\xea\xa2\x85\x8d\x36\x08\xfc\x08\x76\x3b\x43\x92\x1b\x24\x79\x40\x07\x71\xb4\x71\xc5\xee\xa2\x68\xe3\x81\xde\x93\x98\x77\x09\x49\x15\x71\xe9\x34\xf6\xf5\x87\xf6\xce\x48\xf1\x0b\x37\x2d\x21\x99\x34\x9a\xad\x63\x3a\x2f\xf4\xab\x83\x8b\x0c\xb1\xb9\x03\x72\x0f\xbd\x9d\x45\xfa\x1e\xd6\xfb\xc5\xbe\x16\x04\xef\x3c\xa6\x3f\x44\x72\x63\x24\x19\x7a\x21\x8d\xee\xca\x98\xde\x16\x9b\x3e\x61\xdf\x6f\xec\x65\x8f\x59\xee\x30\x33\x0f\xbb\xdd\x22\xd3\x3d\x9a\x9b\xa3\xcd\x16\xb2\x2d\x60\x0e\x3e\x92\xfc\xc5\x2c\x7c\xa4\x58\x42\x2a\x45\xcc\x78\x8b\x66\x8b\x98\x65\x15\x79\x8e\x08\x3e\x63\xdc\xfa\x0f\x9b\x8b\x61\x77\x03\xcc\xe1\x84\x7e\x9d\x31\x6b\x0f\x49\xc6\x91\xd4\x85\xc0\xcf\xe1\x7a\x29\xf4\xbe\x26\x78\x8e\x90\xfe\x10\xbb\xbd\xa3\x9b\x39\xe6\x3d\x43\x1e\x1f\xcc\xf0\x84\xdd\xee\x71\xfd\x08\xba\xbd\x60\x46\x0d\xcc\x57\x01\xcd\x67\xd1\xef\x16\xf2\xce\x23\xe5\x5f\x82\x7b\x03\xb3\xbe\x62\x97\x31\xec\x35\x87\xf1\xd3\xd8\x69\x12\x79\x1d\x30\xdb\x16\xc1\xab\x84\x16\xa2\xb8\xe1\x89\xe0\xd9\x22\x78\x2c\x90\x7b\x1c\x99\x15\x91\xed\x03\x49\x7c\x70\x63\x1f\xd7\x49\x22\x5f\x29\xdc\xe0\x1b\xf7\x53\xc0\x7e\xbe\xd1\xe6\x06\xbd\x1d\x70\xdd\x37\xf6\x53\xc5\x0c\x3f\x48\x31\x8e\x54\x57\xc8\xb2\x81\x39\x8f\xd0\x5c\x04\x99\xa5\x91\x62\x0e\xc9\x7d\xe3\x06\x35\x4c\x3f\x8a\x64\xc2\x67\x8d\x90\x7a\x11\xe3\x2d\xd0\xc6\x0e\x9b\xf9\x43\xca\x47\x34\x11\xde\xc3\x89\xe0\x1d\xe6\xd8\x04\x79\x47\x70\xc9\x3b\x52\x4a\x21\xf7\x18\x92\xcc\x13\xbc\xbe\x70\x9d\x19\x7a\xcd\xa0\xdf\x09\xc4\xeb\x63\x96\x7b\x64\xf6\x83\xa4\x53\x98\xe3\x1b\x89\x3c\x91\xf2\x0d\x53\x4a\xa3\xad\x32\xc6\x3f\x23\x99\x1a\x2e\x92\x45\x47\x69\x24\xd5\x41\x36\x6d\x24\xd2\x41\x77\x3d\x02\xef\x88\x7c\x7e\xd1\xaf\x0c\xda\xdc\xe1\x3a\x13\x74\x38\x47\x0f\x43\xe4\x3b\xd4\xc7\x13\x53\xca\xa3\x85\xf0\xff\x9f\x48\xd2\x47\xdb\x75\xcc\x6b\x8b\x9e\x43\x5f\xc7\x30\xd9\x34\xb2\xcc\x23\xc5\x33\xc1\xbd\x8e\xc9\x5d\xb1\xb1\x23\x52\x8a\x11\x78\x7f\xd8\x5d\x0a\x17\x89\x21\x87\x6f\xa4\x9f\x42\x0a\x49\x4c\xf4\x97\xe0\x55\xc6\xee\xe3\xa8\x3f\x46\x4a\x1f\xe4\x10\xc1\x24\x97\x48\x39\x86\xf1\x26\x18\x3f\x85\x3c\xbf\x90\x4a\xf8\x19\x73\x5c\x3d\xec\xdb\x50\xa7\x73\xdc\xa2\x89\x78\x5f\xe8\xf5\x88\x6c\xdb\xc8\xfb\x86\xeb\x96\x31\xad\x24\x36\x5f\x46\x66\x07\x64\xdf\x40\x37\x61\x7e\x1d\x71\xc9\x22\x32\x3f\xe1\xfc\x04\x5a\x5a\xa1\xed\x37\x76\x9f\xc1\xbc\x7e\x30\xf3\x6f\x6c\xd6\x43\xaa\x13\x24\xec\xfc\xca\x2f\xc1\x33\x8a\xf6\x7b\xc8\x2e\x85\x66\x1f\xd8\xca\x1c\x37\x7e\xe0\xda\x47\x82\xfb\x1b\x53\x89\x63\xf3\x07\x74\xbf\x44\x72\x1f\xa4\x9a\x43\x07\x25\xa4\xbc\xc7\x56\x5e\x68\x7f\x85\xdc\xb7\xd8\xd7\x16\x33\x0a\x3b\xbb\x8b\xdc\xc3\x1c\x3a\xa3\xa7\x15\xf6\xd3\x47\x36\x2d\x74\x50\x41\x4b\x35\x82\x77\x0f\x3d\x9e\xd0\x30\x4f\xf7\x51\xa4\xbc\x40\x9b\x2f\x24\x5d\x46\x47\x55\xd4\xbb\xa2\x91\x12\xba\x99\xa0\xe3\x0c\x76\x15\x41\xa6\xbf\xc8\x20\x8d\x6e\x16\x48\xcf\x43\xca\x57\xdc\xe1\x89\x9e\x26\xd8\x65\x8a\xc0\x4f\x62\xcf\x0f\xcc\x79\x89\xc9\x1c\x90\xdb\x02\xf3\x3b\x42\x5b\x6b\xb4\x3f\x40\xb6\x27\x8c\xbf\xc1\xbe\x7c\xb4\x5f\xc4\xee\xc2\x0c\x19\x22\xc9\x24\x92\xbc\xa0\x5e\x05\xc9\xcc\xd0\x5c\x98\x4f\x77\xec\xf5\x84\x0e\x2b\x18\x3f\x8e\xdc\xc2\x8c\x38\xa3\x83\x0f\xa6\xb1\xc7\x75\x8a\x38\xbf\x8a\xc9\xed\xb0\xe7\x21\x92\xf6\xb1\x85\x38\xc6\x5f\x22\xc9\x33\xc1\xf3\x49\xf0\xea\x20\x83\x2e\xda\x3b\x62\xdf\x75\x82\xcf\x16\xfd\x4a\x22\xc3\x90\x5d\x7e\x91\xd9\x10\x17\x89\x62\xfe\x1a\xd8\xcc\x03\x29\x8e\x90\xf2\x09\x7b\x9e\x20\x95\x38\xb2\x2b\xa0\xed\x39\x36\x5a\xc0\x2e\xb3\xe8\x21\x8b\x69\xf8\x48\x6e\x88\xdc\xce\xd8\xdb\x10\x1b\xe6\xde\x20\x86\x9b\x7e\xa3\xd3\x08\x52\xb9\x23\xb9\x35\x52\x4c\xe3\xda\x27\x02\xaf\x86\x64\x06\x48\xa6\x87\xe6\x5a\xd8\x48\x1c\xcd\x7d\x21\x83\x32\x66\xd3\x44\xca\x33\xe4\x9d\x40\x8b\x13\xb4\xff\x83\xbd\x55\x31\x61\x8e\xd6\x26\x68\xef\x8d\xf9\x0d\xcf\x37\xc5\xfc\x76\x30\xdb\x08\xf6\xb3\xc7\xd5\x0e\x48\x76\x87\xec\x5f\xc8\x7d\x80\xec\x13\xd8\x62\x16\x49\x1d\xd1\xec\x07\x93\xff\x23\xf0\x67\xb8\x4e\x05\xd7\xfe\x20\xdb\x29\xa6\xb4\x43\xca\x05\xec\xee\x86\xbd\x26\x91\xf7\x16\xbb\x5d\xa3\xa5\x25\x72\x0b\xf5\xb8\xc3\xbe\xce\x68\xf6\x8d\x54\x16\x18\xef\x07\xd3\xcb\x11\xbc\x07\x04\xcf\x36\x6e\x7c\xc5\x8c\x23\xd8\xd7\x0b\x89\xd4\xd0\xcc\x07\xf3\x13\x45\x06\x15\xcc\x31\x8b\x7e\x15\x30\x5f\x73\x64\x3b\xc1\x4e\xa2\x48\xea\x86\x8d\xf7\x31\xfe\x00\xfd\xae\x20\x83\x16\x92\x8d\xa1\x97\x3c\x41\xf8\xce\xc5\x32\x76\x97\x45\x3e\x17\x5c\x27\x43\xe0\x17\x31\xaf\x16\xa6\x57\x41\xca\x79\xf4\x9c\xc7\x35\x3a\xd8\xfc\x02\x99\xf5\x91\x4c\x15\xb3\xf4\x71\x93\x2a\x2e\x52\xc1\x0d\x46\xe8\xed\x86\xee\x8a\x98\xe1\x06\xd3\xdd\x62\xfc\x0c\x36\xda\x45\x0f\xe1\x9d\x54\x09\xbc\x2a\x52\xff\x41\x5b\x13\xec\x2d\x7c\xe6\x2f\x12\xed\x63\xe2\x19\x64\xb6\x45\x76\x43\x4c\x7c\x89\xfd\x24\x91\x49\xe8\xaf\x39\x52\xdc\xa3\xe7\x23\x92\xf1\xd1\xfc\x1f\xfa\x89\x20\x9b\x06\x5a\xf9\xc6\x34\x42\xde\x0d\xef\x2b\x89\x8e\xee\xe8\x68\x8c\x7e\x4d\x09\xde\x17\xa4\xb2\xc4\x34\x8e\xe8\xfd\x4e\xf0\x48\x62\xcb\x7d\xa4\x7a\x42\x5b\x4b\x74\x35\x46\x1f\x4d\xec\x79\x89\x16\x87\xb8\x49\xc8\x01\x3e\xba\xfb\x45\x3b\x5b\xcc\xea\x44\xf0\xe8\x20\x8b\x0c\x3a\x2b\xa2\xd1\x1d\x9a\x5d\xe3\xea\x61\x0f\x6f\xd0\xc2\x1c\x97\xac\x21\xdb\x0c\x9a\xff\x20\x5e\x19\xe3\xdd\x91\x82\x8f\x79\x7a\xb8\x5e\xc8\xf0\x2d\x5c\x2d\x64\xc3\x36\xf2\x15\xb2\xed\x1c\x69\x1c\xb0\xbb\x1d\x76\xbb\x41\x13\xa1\x0e\xc6\xb8\x4e\x02\x5b\xba\x61\x0b\x57\xdc\xb1\x8f\x39\x6e\xd1\xe6\x0c\xd9\xac\xb1\x89\x03\x66\xfc\x8b\x8d\xcd\x91\x66\x02\xf7\xee\xa0\xcf\x06\x26\xe4\xe9\x7b\x05\x3b\x8e\xa0\x7f\x13\x74\xb2\x47\x4b\x05\x74\x53\x40\x8f\x1d\x24\xd3\x45\x1b\x3e\x76\x5f\xc7\xf4\xde\xd8\xed\x0a\xed\x74\x31\xc7\x1a\xc1\xe3\x80\x49\xc7\x31\xc3\x1e\xc1\xa3\x84\x0e\x22\xd8\xe2\x0e\xd9\x46\x71\xc7\x28\xf6\x7c\xc1\xd5\x86\x98\xe4\x0c\xbb\xf3\x31\xe5\x0d\xc1\x73\x87\x5b\x84\xec\x14\x6e\x86\x5f\xa4\x3c\x27\xb8\xef\x91\xe1\x03\x2d\x87\xec\xb0\x47\xf3\x49\xe4\xb9\xc0\xf6\xf2\xe8\x31\x8b\x44\xd3\x98\xf5\x07\xcd\x2e\x31\x9b\x06\xc1\xa3\x82\xdd\x47\x71\x63\x0f\x13\x1f\x62\x9e\x6b\xe4\x1d\xc5\x26\xee\x48\xb3\x8f\x0e\xde\xd8\x44\x17\xe9\xed\x91\x67\xd8\x77\x45\x6c\x3c\xf4\xfb\x10\xb3\x28\x13\x3c\xf6\xe8\xb0\x4e\x10\x66\x7e\xb8\x49\x92\x13\x34\xf2\x85\x99\x46\x91\x48\x11\x33\x6f\x62\xba\x69\x82\x4f\x1c\x37\xe8\x60\xc7\x73\xec\x2e\x81\xf9\xf8\xd8\x58\x16\x7b\xbb\x20\xfb\x27\x76\x3c\x45\xb6\x2f\x34\xfb\x87\x4e\xb3\xc8\xbd\x40\xf0\x9c\xa1\xf5\x22\xf2\x1d\xc3\x84\x3d\xb6\xed\xa3\xfb\x09\x32\x6f\x61\x06\x53\xb4\x10\x72\x5a\xb8\x3b\xb6\x68\xff\x17\xd9\xfe\x20\x5e\x0a\xf3\x6c\x62\xb2\x3d\xec\x72\x81\xb6\x47\xb8\xde\x0d\xd7\x88\x60\x77\x2d\x24\x64\xdf\x43\x12\xcd\xd5\xb1\xd3\x18\x36\xfe\x8d\x54\x9f\xc8\xaa\x8d\x76\x76\xc8\x2a\x8a\xf1\x3f\x68\xe7\x8a\x94\xba\x98\xde\x10\x3b\x1e\xe3\xee\x63\x64\xd3\x41\xfc\x2b\x52\x3c\x60\xe3\x57\xe4\x90\x27\x78\x8c\x09\xee\x67\x5c\x27\x85\x1b\xbf\xd1\x52\x16\xa9\x46\x30\xd1\x1d\x72\x8c\xa2\xa5\x1f\x74\x30\xc4\x46\x2a\x48\xf8\x9d\x97\xb2\xd8\xcb\x05\x7b\x3b\x21\xf5\x39\xb2\x99\x62\x77\x6f\x24\xbd\xc3\xc6\xc7\xb8\xc9\x00\xfd\x7b\x63\xfc\x22\x52\xbc\xe1\x5e\xe1\x1e\x1d\x62\x6b\x77\x74\xdb\x44\xf7\x77\x64\xdb\xc2\xe6\x5b\xc8\x6d\x80\x89\x65\x91\xe3\x1a\x79\x1e\x70\xbd\x70\xef\xae\x90\x79\x19\x3d\x7e\x70\xfd\x23\x3a\x48\xa1\xa5\x09\xea\x57\x71\x5f\x69\xdc\x7c\x83\x5e\xea\xd8\xcc\x0f\x1a\x89\x60\x2f\x57\xc4\xab\x23\x33\x8f\xe0\x99\xc3\x44\x2f\x98\x55\x09\x17\x69\x60\xa2\x1b\xec\xa5\x87\xbc\x6a\x48\xf9\x0f\xf7\xac\xa3\xb5\x0d\xa6\xd7\xc6\x4e\xa3\xb8\xce\x1a\xf1\x6e\x48\x63\x87\xbc\xbe\xb0\xe5\x02\xc6\xdb\x21\x91\x21\xe6\xd4\xc4\xf4\x9a\xe8\xea\x07\xf3\xb7\xc0\x2c\xa3\x48\xee\x07\x19\xc5\x90\xe1\x10\xfd\xfe\x41\xaf\x0b\xe4\x91\x44\xea\x19\xcc\xef\x10\x93\x0a\x7b\xe2\x17\x3d\xbd\xb0\x89\x2a\x32\x9d\x61\x26\x27\xf4\x6f\x89\x8b\x16\x09\xde\x4b\x64\xb7\x42\xbf\x26\xc8\xcb\xc7\x76\xaa\x68\xb3\x8f\x6d\x86\xcc\xb5\xc1\x78\x27\xe4\xf9\xc0\xcd\x8f\x04\xcf\x3b\x9a\x6b\xe3\x42\x9e\x7b\x7c\xd0\x6e\x0b\x5b\xbc\x61\xea\x0b\x64\xfc\x8d\x78\x39\xcc\xa6\x8a\x46\xaf\x68\xe6\x86\xdd\x7e\x90\x71\x03\x99\xa7\x71\x91\x32\x1a\x66\x73\x26\x82\xb6\x42\x6f\x85\x9d\x37\x46\xf7\x3b\x5c\x34\x4d\xe0\xbf\xd0\x5d\x0d\x3d\xcd\x71\x91\x08\x7a\x6e\xa1\xd5\x14\x26\xba\x47\x5e\x61\xa7\x35\xb1\x91\x16\x32\x2b\xa3\xf9\x35\xf2\xe9\xe0\xea\x7d\x4c\x61\x8b\x19\xff\x11\x78\x19\xcc\x23\x8a\xf4\x33\xb8\x5e\xc8\x88\x2f\x82\xf0\x3d\x73\x2f\xcc\x2e\xec\xc3\x0b\xae\x1d\x32\x5b\xc8\x1c\xe1\xc6\x7a\x21\xa3\x14\xae\x97\xc0\x7e\x4a\xe8\xa9\x87\xc9\xdc\xd1\xf9\x13\x17\xfd\x60\xf7\x79\xa4\xb2\xc2\xa5\x4b\x98\x42\x98\xe3\x2d\xcc\x79\x87\x44\xcb\x48\xf2\x8e\x5b\xa4\x30\xe7\x09\x66\xb9\xc0\x26\x62\x68\xc8\x3e\xe1\x99\x0f\x29\xe4\x13\x7a\xae\x8d\xc6\x73\xc8\x38\xdc\xc4\x2d\x34\x91\x41\xfb\x07\xb4\xf7\xc1\x78\x33\xcc\xb1\x85\x44\xde\xc8\xbe\x8b\x69\xf5\xd0\x79\x17\xfb\xdf\x87\x79\xec\x79\x83\x99\x86\xb9\xda\x43\x0f\x21\xc3\x44\x31\x93\x12\xee\x67\x85\xe9\x55\xd1\xe2\x17\xf2\x1c\xa2\xdd\x33\x92\x3d\x62\xcf\x3b\x74\x9b\xc3\xa5\x73\xd8\x5d\x91\xc0\x1b\x23\xa1\x96\xc6\x61\xee\x86\xdd\x93\x41\xf6\x6d\x5c\xcb\x47\xcb\x1b\x4c\x6c\x8b\x6e\xf3\x48\xea\x0f\x1d\xcf\x91\x45\x1a\xbb\x59\x60\xfc\x27\x9a\xef\x21\x95\x33\x81\xdf\x46\x2f\x5b\x5c\x74\x83\xbc\x2b\x68\x6c\x85\x56\xd3\xd8\xfd\x0d\x7b\xf9\xc6\x6c\xc3\x5d\xd0\xc0\x6e\x27\x98\xc6\x0d\xa9\x3c\x90\x5e\xa8\x97\x50\xbb\x15\xec\x39\xec\xe3\x3c\xa6\xe4\x23\xb7\x15\x36\x12\x72\xc7\x02\x5b\x0c\xf7\xff\x06\x7d\xbc\x71\x8d\x2d\x92\x0e\xf7\x92\x8f\x6b\x24\xd1\xaf\x50\x3b\x6b\x24\x3b\x47\xd2\x03\xcc\xe4\x80\x7b\x7d\xd0\xcc\x0f\x26\xf6\xc4\x79\x3e\xc6\xf3\x30\x8b\x28\xe2\x0d\x31\xbd\x1e\x26\x9b\xc1\x3c\xeb\x48\x3a\x82\x19\xf4\xd0\x76\x01\x59\x77\xd1\x6b\x16\xb3\xa9\x21\xed\x33\x5a\xae\x21\xc7\x3b\xda\x0f\xb3\x2a\x81\x1d\xb7\xb0\xad\x32\xb2\xac\x62\xcf\x77\x6c\xb2\x82\xcc\xcf\xc8\xd7\x02\x8d\xef\x08\x1e\x6d\x82\x67\x07\x8d\x4e\x90\x42\x04\xe3\x1d\xd0\x6c\x09\xfb\x5e\x63\x23\x27\xe4\xf5\x83\x4d\x4f\x09\xbc\x0f\xa6\x16\x32\xd5\x05\x9b\xc8\x62\x96\x11\x6c\x65\x45\xf0\x49\x60\x5e\x55\x6c\x26\xf4\x44\x0b\x69\xde\x30\xde\x05\xd9\xdd\xd1\x43\x0b\x2d\xc4\xd0\xf3\x0f\xf6\xec\xe1\x5a\x3f\xe8\xf0\x0f\x93\x49\x61\xe2\x3b\xf4\x3c\xc7\xac\x7c\x64\xd2\xc1\xbe\x76\x48\x3e\x8d\xc4\xcb\xa8\xdf\x45\x4a\x6d\x6c\xad\x83\xcd\x9d\xb0\xb1\x1d\x32\x18\xa3\xc3\x03\xb6\x38\xc6\x26\x3f\x04\x7e\xa8\xd3\x24\xb2\x7f\x63\x5f\x4b\x24\xb5\xc7\x9e\xc7\x98\x8e\x8f\xf3\x4b\x48\x36\x87\xab\xf9\x48\x3e\xdc\x48\x71\x5c\x37\xcc\xfe\x15\x2e\xbe\x41\x4e\x7b\xe4\x1e\x45\xef\x3b\x82\x67\x19\xfb\x5a\x11\x78\x6b\x74\xf7\x85\xd6\x17\xd8\xd2\x2f\x92\xf1\xd0\xcb\x0f\x66\xd9\x46\xcb\x67\x74\xf4\x83\x44\xc3\xae\xdf\x62\x63\x63\xe4\xd8\xc3\x34\xda\xe8\x69\x8c\x19\x8c\x31\xbf\xe1\x8e\x09\xcf\x3c\xc3\xb5\x23\x04\xcf\x2a\x7a\x48\x63\x33\x45\x4c\x98\xdb\xfe\x17\x26\x76\x47\xea\x47\xcc\xf4\x86\xf1\x43\x56\xcf\xa3\xb7\x31\xb2\x6f\x22\x95\x70\xa3\xdd\xd0\xe1\x19\xa9\x66\x90\x77\x0d\x37\xe9\xa3\xa7\x1f\xcc\xaa\x88\x7c\xc2\x67\x5d\xb0\xf5\x01\x9a\x6f\xa2\xe7\x6f\xb4\x94\xc1\x7d\xf5\xb1\xef\x1e\x32\xdd\xe2\x1a\xa1\x9f\x7e\xb1\x9d\x2e\xf2\xdc\xa1\xd5\x35\x1a\x9e\xf5\xf1\x44\xfc\x1b\xb2\xcf\x61\x7e\x5a\x98\x70\x1b\x3e\x13\xb8\xee\x15\xd3\xac\xa2\xfb\x32\xb2\xfd\x45\x96\x15\x5c\x3f\x8d\xa9\x7e\xa3\x91\x1f\x64\x3f\xc3\x54\xce\xc8\xfb\x07\x2d\x97\xb1\xa9\x3e\xf6\x33\x40\x66\x0f\x6c\x72\x8f\x79\xb6\x31\xe5\x11\x66\x7d\x43\xa7\x5b\xf4\x7b\x80\xf9\x7d\xa0\xc7\x21\x12\xfb\xc3\xf8\x27\xe4\x93\xc2\xc5\x16\x48\x76\x8d\x3c\xee\xe8\x25\x85\x8e\xc2\x5c\x9b\x63\xb2\x1d\xec\x79\x8b\x99\x3d\xd1\x90\xa3\x6b\x23\x8c\xf7\xc0\xbc\x26\x68\xbe\x88\x84\xfc\xdd\xcc\x61\x27\x4d\x64\x18\x47\xf2\x33\xcc\xab\x8b\x49\x2c\xd0\x57\x9f\xe0\x59\x44\x26\x2b\xf4\xef\x88\x79\x0e\x90\x65\x1d\xc9\xe4\x70\xf3\x03\x81\xff\x41\xe6\x4d\x5c\x7d\x80\xfb\x7b\x12\xdc\x5f\xd8\xdb\x0a\x17\x7a\xbd\x10\xfe\xfe\x8d\x66\x7f\x91\xe6\x00\x3b\xc9\x63\x62\x1b\xf4\x30\x46\x1e\x5f\xd8\xdd\x1d\x79\x86\xfb\xef\x80\x4e\x92\xc8\xfc\x8a\x9e\xa3\x98\xe8\x1b\x9b\x19\xe2\xb2\x67\x6c\x3e\xe4\xbd\x27\x1a\xfe\xcd\x2e\x8a\xa6\x63\x48\x98\xe9\x1d\x0f\x19\x36\x90\x5d\x02\x39\xe4\xb0\xb7\x38\x7a\x1f\xa3\x85\x2a\xc1\xfd\x81\xcd\x86\x3a\x0d\xfd\x1e\xb2\x55\xc8\x7c\x0f\x34\x73\xc6\x8c\xa2\xe8\x64\x81\x0d\x33\x3c\xd5\xc0\x5e\x66\xe8\xbd\x81\xd4\x37\xe8\xd7\x1f\x6e\xd2\x42\xe6\x0d\x5c\x3d\x49\xe0\x1f\xb1\x9d\x12\x26\xdc\x8a\x8b\x07\xc1\xa3\x8c\x29\x17\x31\x8d\x13\x3a\x2e\xe0\xa2\x17\x24\x19\xc5\x75\x53\xd8\x6f\x8f\xc0\xaf\xe3\x36\x65\x5c\xa3\x82\x76\xea\xe8\x7e\x8b\x24\x9f\xb8\x6e\x05\x33\x29\x62\x2f\xbf\x68\x7e\x85\x7c\x46\xd8\x58\x1c\xf3\xbc\x63\xb2\x17\x34\x37\x41\x8a\x5d\xe4\xb6\x44\xa6\x27\x24\x99\x40\x07\x7d\xec\x76\x87\xdd\x75\x31\x93\x25\x66\x3e\x47\x87\x3b\xdc\xf8\x82\xdc\xc6\x98\xe1\x1a\x8d\x1d\x31\xd1\x02\xee\x9d\x20\x78\x2e\x30\xf3\x15\xb2\xf3\xd1\x71\x0c\x57\xf7\x90\xfe\x14\x8d\x56\xd0\xe8\x1e\x17\xaf\x62\xaf\x53\x34\xf7\x87\x2d\xd6\xb0\xc9\x37\xf6\x7c\x46\x87\x0d\xd4\x3f\x63\x0a\x3d\x5c\xbb\x81\x7d\xa7\x90\x85\x8f\x8c\x7f\xd1\xda\x0c\x89\xad\x30\x9b\x37\xae\xf5\x40\xb3\x7b\xcc\xf9\x17\x33\x8a\xe1\xfe\x6f\xa6\x32\x52\xc9\xe1\x3a\x57\x82\x67\x05\x69\xc6\x30\xcd\x16\xa6\x7e\x45\xd6\x29\x34\xd7\xc5\xa6\x63\x68\xf5\x8e\x7c\x8a\xd8\xce\x1b\xdb\x1f\xe3\x62\x3e\x36\x7e\x47\x6e\x6b\xb4\x30\x43\xa2\x57\xe4\x19\x47\x97\x2f\x24\x77\x24\x78\x9c\x70\xb1\x3a\x52\xc9\x12\xf8\x51\x4c\x3c\x86\x19\x35\x31\xcb\x21\xc1\xa3\x80\xcd\xec\x09\x9e\x67\x4c\xbd\x8f\x5e\x92\x04\xf7\x0e\xda\x8d\x61\xd2\x73\x74\x1d\xe6\xd7\x09\xfb\xb9\xa1\xdd\x90\x2f\x0b\x98\xe5\x12\x1b\x4f\x61\x77\x0b\xcc\x7e\x89\xbd\x97\x31\xf5\x1b\x76\x7f\x40\xaa\x29\x64\xfb\xc6\x9c\x72\xe8\xb9\x87\x7d\x67\xd1\xc4\x0c\xf3\xfb\x8d\xeb\x76\xd0\x48\x0d\x73\x6c\x13\x3c\xc2\x2d\xfe\x83\x8d\xad\x31\x87\x22\xfa\x55\x46\xaf\x31\x4c\xaa\x83\xe9\xa6\x08\xde\x0b\x34\xf6\x87\x96\xda\x04\xde\x2f\xc6\x1b\xe1\x52\x35\x4c\x3e\x86\x6b\x44\xd1\x5b\x04\x8d\xae\x30\xd9\x23\xae\x7f\xc7\x64\xfe\xb0\x97\x32\x2e\x92\xc2\x94\xd6\xb8\xce\x05\x33\x1f\x60\x96\x35\xf4\xd2\xc1\x1e\x0b\xc8\xeb\x81\xbc\x9e\x68\x2c\x8b\xbb\x6f\xb0\xd7\x3c\x92\x9e\xa1\x9d\x15\xe6\x7f\x1e\x65\x30\xcb\x90\x63\x2e\x98\xd7\x11\x9d\xec\x30\xb1\x12\x1a\x66\xde\x34\x8f\x5b\x1f\x30\x9b\x1e\x72\x1a\x23\xa9\x1a\x12\xee\xd9\xdd\x07\xbb\xab\xa2\x97\x3b\x7a\x0a\xf9\xfd\x85\xfd\x0c\x31\xe3\x24\xa6\x99\xc2\x9e\x6f\xe8\xb3\x8c\x59\x7d\x90\xd4\x08\xf9\x5d\x63\xe3\x51\x6c\x6e\x87\xc9\x4e\x90\x72\x0f\xdb\x8d\x20\xf3\x39\xee\x3e\x45\x8e\x1b\xcc\x3b\x87\xa4\x37\x04\xf7\x23\x32\x6e\x63\xfc\x36\x2e\x79\xc1\x7e\x17\x31\xbd\x14\xae\x31\x46\xbc\x0e\x66\xf3\x40\x52\x3e\x36\xdc\x9b\xd5\x04\x76\xb2\xc1\x6c\xf2\x68\xbe\x86\xc4\xbb\x68\xeb\x80\xab\xbd\x71\xf7\x21\xfa\x4c\xa1\xc7\x0c\xa6\x9f\xc5\x34\xcb\xe8\xcd\x47\xa7\x35\xcc\xba\x85\x19\x0f\x70\xc3\x35\x2e\xf2\x44\xb3\x1b\x82\xf7\x0a\x49\x67\xd1\x82\x87\x99\xb4\xd0\xd1\x0b\x13\xab\xa1\x83\x1d\x1a\x9b\xe2\x16\x65\x24\x37\xc0\x1e\x7e\xb0\xef\x17\x92\x8f\xe3\xee\x1f\xb4\xb5\x40\x2a\x61\x46\xf6\x31\x21\xa7\x0f\xf3\xd8\x77\x0e\x0d\xef\x63\xbe\x45\x2b\x7f\xb8\x9f\x18\xf6\xfd\x8d\xe4\xc3\x1c\x9b\x12\x3c\xf7\xd8\x5a\x1e\xe3\xd7\x70\xbd\x37\xc1\x3d\x64\xb0\x0b\xb2\x4c\xa1\xf9\x21\xb2\x4d\x63\xdf\x55\x5c\xe7\x0b\xd7\xfb\x42\x42\xee\xab\x27\x90\x73\x1a\xc9\xfe\x20\x91\x31\x52\x4a\x22\xb5\x3f\xdc\xfa\x8a\x6d\xee\x90\xcc\x0d\x6d\xce\x31\x5f\x3f\xd8\x4b\x1e\x99\x67\x09\x5e\x3d\xf4\x92\x46\x9f\xbf\x68\x2f\x3c\x67\x1a\x57\xeb\xa0\xe3\x38\x9a\xbd\x12\xf8\x0d\xec\xa7\x41\xf0\x69\x11\x78\x65\x6c\xb2\x81\xfb\xce\xa3\xd3\x03\x76\x91\x42\xc7\x29\x34\x96\x40\xca\x0d\xb4\xf6\x8d\xfb\x69\x21\xf9\x36\xda\xf2\xd0\xe3\x1d\xd9\xcc\x90\x4a\x05\xd9\x0c\xd1\xfb\x08\x39\x64\x30\xcd\x37\xb2\xe8\xa0\xf1\x3e\x81\xbf\xc7\xe4\x47\xd8\x78\x04\xbb\xaf\xa0\xb9\x1e\xae\x9f\x45\xc7\x55\x24\xe4\xcc\x76\x0f\x3b\xde\x63\x7a\x2d\xf4\xde\xc2\x26\xca\xd8\x4b\x13\xbd\x16\x30\x8d\x3e\xda\x7b\xe0\xda\x49\x6c\xac\x80\xd4\xd7\x48\x29\x8b\x89\xc7\x31\xde\x1f\xba\x4b\xa2\xed\x15\xc1\xf3\x07\xd3\x4a\x63\x92\x5b\xa4\xfc\xc0\xd5\xb2\x68\x65\x83\x2d\x94\x30\x7f\x4f\x5c\xf2\x86\x44\x6f\xc8\xb3\x8e\x6b\xcc\xd1\x68\x78\xa7\x7b\x64\x50\xc5\x3d\x7d\xcc\xe7\x89\xf1\xae\x48\xb9\x83\xc9\x1f\x70\x91\x2d\xe6\x55\xc1\xf8\x7d\x74\xda\x45\x73\x55\x6c\x6a\x85\x6d\xfc\x21\x3b\x0f\xf7\x33\xc3\xac\x53\x48\xea\x8a\x7e\xef\x90\x54\x01\x09\x77\x5a\xfa\x8e\xf1\x93\xc8\x20\xd4\xb8\x87\x49\xec\xb1\xaf\x3d\xfa\x37\x45\x3b\x79\x4c\x7b\x81\xbc\xc7\xb8\xc6\x06\xd7\x58\x10\xdc\x97\x68\xeb\x0f\xd7\xf0\x91\xef\x04\x5a\xe9\xa3\xd9\x2a\x2e\x16\x21\xf0\x36\xb8\xe4\x0e\xfb\xc9\x60\x33\x35\x6c\x22\x85\x4b\x5e\x71\xad\x23\xf2\x59\xe2\x92\x5d\xdc\xf8\x85\x79\xbf\xd0\xeb\x0a\x29\xde\x09\xfc\x16\xae\x13\x6a\x73\x88\xc6\xd7\xe8\x60\x83\x2c\xbb\xd8\x58\x17\x2d\x66\x71\xd3\x36\xfa\x8c\xa1\xed\x14\xfa\xe7\x21\x95\x37\x2e\x5e\xc2\xc4\x6f\xe8\x21\x8a\x54\x2f\xb8\xf9\x1e\x5b\x59\xe2\x7a\x49\x5c\x6c\x8b\xfd\x44\x31\xe9\x2f\xb4\x56\x43\x96\x3e\xf6\x72\x46\xb6\x67\x4c\x7c\x81\x44\x3c\xe4\x5e\x41\x9b\x55\x5c\x3d\x8e\xb6\x56\xb8\x54\x1a\x5b\x9d\xe2\xc2\xad\xd2\x0b\x39\xf6\x83\xe6\x0b\x48\x2c\x89\x4d\x3e\x90\xc5\x1c\x2d\x67\xb1\xe7\x19\x9a\x4f\xa1\x9b\x1f\x6c\x75\x8c\x8d\x7b\x04\xf7\x09\x7a\x59\x23\xe1\x99\xda\x31\xe4\xfb\x17\x2d\x8c\xb1\xcb\x0c\xf6\xfc\x83\xfe\x67\x98\x33\x7a\x08\x7f\x2e\x20\xa9\xb0\xd7\x3c\x64\xd9\xc7\xee\xc3\xec\xb8\x22\xb9\x70\x5f\xff\x61\xc3\x9d\xd6\x2e\x63\x43\x26\xef\x65\x70\x3f\x55\x82\x47\x03\xf5\x7e\x08\xee\x3d\xa4\x38\x41\x73\x0f\x5c\xeb\x86\xd4\x56\x48\x66\x8b\x5b\xbf\x31\x61\x5e\xc4\x86\x68\xb5\x8d\xab\xd7\xd0\xd2\x0d\x37\x49\x23\x0f\x1f\x1d\x26\xd0\xf8\x08\x8d\xaf\x08\x5e\x27\x02\x3f\x8d\x4d\x86\x8c\x36\x40\xaf\x33\x24\x5b\xc5\x7c\x2f\x91\xd1\x18\x3d\x3d\xb1\xd5\x03\xe6\xb5\xc6\xf5\x8b\x68\xf1\x1b\x1b\x2f\x61\xf3\x45\xd4\x0f\x39\x7c\x8d\x16\x93\xe8\xa3\x8d\x19\x15\x71\xfd\x6f\x5c\xec\x82\xad\x24\x30\xcd\x1d\x7a\x0b\xf7\x4d\xd8\x0b\x39\xcc\xf1\x07\x13\x6f\x23\xdb\x0f\x3a\x9e\xa2\x99\x0c\x6e\x7d\x42\x7e\x63\xd8\xe9\x17\xf2\xee\x60\xb6\x1b\xb4\x58\xc1\xc6\x46\x68\xad\x8a\x76\x6a\xd8\xf7\x0a\xdd\x7e\xb0\xa5\x23\x5a\xcd\xa1\x95\x24\x2e\x79\x40\x0e\x65\x4c\xf3\x17\xa9\x47\xb0\x61\xa6\x8e\x2e\xe8\xf1\x17\xd3\x3d\x60\xbe\x92\x48\x79\x84\x6b\x47\xb1\xa5\x03\xfa\x75\xc4\xbe\x9b\xb8\xda\x1a\xd3\x0a\x77\xd2\x00\xb9\xdd\x70\xf3\x0f\x66\x7e\x27\xb8\xb7\x31\xa5\x04\xea\x85\x5e\xdd\xe3\x22\x3e\xf2\xda\x20\xfb\x70\xdb\x7d\x90\xc5\x0a\x9b\x4d\x23\x95\x6f\xdc\x70\x81\x46\x56\x98\xe1\x16\xdd\xa4\xf9\x17\x00\x00\xff\xff\xbf\x1b\x72\xe3\x00\x20\x00\x00") func keysWordlistChinese_simplifiedTxtBytes() ([]byte, error) { return bindataRead( @@ -86,12 +86,12 @@ func keysWordlistChinese_simplifiedTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/wordlist/chinese_simplified.txt", size: 8192, mode: os.FileMode(420), modTime: time.Unix(1497960590, 0)} + info := bindataFileInfo{name: "keys/wordlist/chinese_simplified.txt", size: 8192, mode: os.FileMode(420), modTime: time.Unix(1511602021, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _keysWordlistEnglishTxt = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x2c\x5b\xdd\xbe\xbc\x2a\x08\xbd\xf7\x2d\xc9\xa8\xd8\xa3\xe2\x41\x9d\x76\xfb\xe9\xcf\x6f\xad\xfe\x17\x83\xe5\x07\x2a\x22\x2c\xcc\x91\x4d\xda\xee\x2d\xc9\x66\xc5\xe6\x93\x64\x2b\x9a\x64\xf3\x35\x41\xbf\x78\x1e\xda\xf0\x32\x3c\x36\x24\x33\x24\xf3\x7d\xc5\x9e\x64\x5b\x43\x93\xe4\xac\x63\x20\xb1\x9d\x95\x73\xf6\xf5\xa6\x6f\xf1\x65\x0a\x56\xd9\xf6\x24\xd9\xd7\x98\x96\x93\xe4\xff\x96\x05\x72\xc3\xd9\x18\xf5\xa7\x61\x2c\x79\x7a\x80\xc6\xcb\x75\x2e\x29\x49\x76\xe9\x33\xc9\xbe\xe3\x67\x99\x8f\x6f\xf9\xfe\xb3\x06\x5e\xab\x81\xae\x02\xfa\x95\x96\x15\xa9\x21\xd1\xf0\x0d\x3d\x1e\x87\x58\x20\x71\x0c\xfd\x08\xc1\x78\x4e\xb1\x96\xe4\x54\xfc\x30\xe6\x33\x54\x93\x5c\x2a\x7b\x12\xab\x89\x2d\x2c\xba\xc7\x4c\x62\x03\xd2\x29\x12\x35\x49\xd9\x16\x68\xf6\xcb\x4b\x92\xa2\x28\x2f\xa6\x2d\x49\xc1\x7b\xd1\x07\xd4\xef\x24\xa5\x3a\x06\x58\xbc\xa1\x71\xbf\x24\x49\x09\x95\x1d\x15\x86\x27\x29\x53\x23\x49\xb9\xe5\x19\x49\xaa\x4c\x5d\x81\xf4\xcf\xda\x99\xa4\xfa\x4b\x29\xcf\xba\x86\xee\x49\x9a\x94\x07\x1c\x5b\xbe\x20\xa8\x96\x8d\x23\x6f\x27\xf8\xb4\x13\x63\x6c\x67\x3c\x49\x9a\x55\x88\xae\x7d\x98\xd5\x7c\x51\x2a\xad\x51\xa0\xcd\xe7\xc5\x06\xe3\x66\x32\xb5\x35\x41\x6a\xff\x2d\xd4\xfa\x35\x85\x42\xb4\x27\x49\x17\xcc\xae\x7b\xf1\x13\x6f\x5d\x25\x90\x80\x6b\xef\x41\x35\xe9\x61\x25\x49\xe4\x0b\x84\xeb\x1b\x2a\x20\xe0\x19\x27\x38\x42\x6a\x51\x31\x81\xa8\x18\x77\xd4\x27\x49\xf8\x6a\xc8\x09\x0c\x1f\xa9\x62\x66\x11\xf6\xe5\x1b\xe4\x87\xbe\x63\xea\x41\x15\x89\x69\xac\x30\x6f\x8f\x4f\x92\x81\x5f\x57\x94\x8c\x21\x5c\xfc\x31\x94\x94\xf5\xc6\x58\x55\x93\x8c\x79\x55\x49\x32\xaf\xa2\x53\x93\x4c\xaf\x49\xe6\x94\xfc\x41\xa2\x18\xc0\x9c\x36\xd7\x8e\xb2\x7f\x0a\xbe\xfe\x29\xe3\xda\xa1\x57\xeb\xa4\x92\x71\x15\xd6\xa4\xd8\xd7\x74\x90\x55\x5b\x92\xaf\x06\x55\xe8\xeb\x59\x76\x47\x0a\xd5\xba\xe5\xa3\xa0\x41\xfa\x24\xb9\x75\x38\x86\x73\x1f\xab\x24\xb9\x3f\xb7\x40\x11\x7f\x6d\xa4\x4d\xb6\x27\x6d\x92\x2f\x2d\x1e\x78\xf0\x96\x36\xd9\x4f\x4d\x9b\x9c\x69\x93\x42\x85\xde\xa0\x6f\x0d\x15\x4b\x49\x9b\xd4\xcd\x3d\x6d\xd2\xa4\x09\x92\xa6\x68\xc9\x9f\x16\x54\x0a\xea\xf6\x06\xa1\xa2\xfa\x00\x83\x61\x19\xf4\xa3\x33\x6d\x32\x67\xd1\xb4\xa9\xe4\x0b\xb4\x81\xac\xf9\xa4\x4d\xb3\x60\xe3\x6e\x9a\x31\xdc\x4d\xf5\x48\x9b\x1e\x1e\x78\x3e\xc1\x52\x2f\xf9\xe2\xe5\xb2\xb6\xa7\x4d\x0b\xf7\xf7\xa6\x50\xf7\x4d\xcb\x4c\x9b\x36\xf2\x6c\x7a\x18\xde\x06\xc8\x0c\x01\xef\x09\x75\xdf\x74\xde\xaa\xe0\xf4\x38\x58\x58\x7e\x32\xc6\x62\x78\xfe\xe0\x81\xb9\xaf\xc6\x6d\x16\x78\x89\x79\xa5\xcd\xde\xe6\x05\x6b\xb7\x15\xd9\x15\xb4\x92\x36\x4e\xaa\x08\x3a\x2b\x2a\x28\x87\x81\xd8\x0a\x79\x15\x77\xd2\x31\xbc\x22\xe5\x04\xcb\x22\x01\xc3\x35\xae\xb4\x39\x16\x64\x73\x99\x69\xf3\xfd\x49\x9b\x5b\x49\x9b\xd7\x2d\x6d\xd8\xbc\x9b\xb7\x35\xd2\xe6\xfe\x01\x41\x37\x1e\x3b\x46\xe3\x81\xbd\xba\x39\xf5\x75\x83\x39\xdb\x7c\x42\xc9\xb6\x77\xcb\x6d\xfe\x9b\x36\x7f\xd2\x16\x92\x39\xc8\xe0\xc2\x84\x60\x60\x21\xa8\x1f\x14\x28\xcc\x02\xa8\xfe\xe1\xc5\x30\xc7\x30\x6a\x41\x18\x16\x21\xec\xbc\xd0\x9c\xdd\x85\x0d\x94\x7b\xce\x5e\x0c\x0f\x1f\x08\x34\xbc\xb1\xb1\xa3\xfb\x78\xf7\xf8\x16\x7e\xa3\x88\x73\x5c\x1b\x6c\xfc\xb6\x76\x4c\x70\xed\x27\xc6\xb3\x8e\x43\x8a\xa7\x6d\x59\xd9\xd3\xb6\xca\x06\xf2\x01\x29\x2c\x6e\x3b\x9b\xb4\x0f\x98\xad\xd8\xd1\xd1\x8a\xf3\x7d\x83\x20\x20\x97\x35\xac\x51\xe0\x6b\x80\xf3\xbb\x50\xeb\x21\xfd\xfb\x4b\x59\xb6\x0d\x9b\x24\xcb\x66\x0d\xb4\xe0\x39\xcf\x35\x52\x7e\xf3\x3f\x20\xa5\x80\xd4\x94\xa5\x6a\x08\x92\x9e\xb2\xa0\x41\x13\x14\xb5\xac\x4c\xf6\x07\xb4\x39\x4b\x1c\x2d\xdb\x57\xc0\xaa\x3d\xcc\xeb\xff\x3a\xe8\x36\xd9\xae\x4f\x61\xb7\x81\xdf\xc6\x2a\xb1\x83\x9c\x0e\xda\x75\x22\x09\x70\x0d\x3c\x0e\x34\x1e\x17\x88\x35\x54\x19\x93\xfc\xc6\x22\x3b\x54\x99\x52\xfc\x44\x9a\x51\x6d\xea\xe9\x6c\x3e\xdf\x8a\x0b\x4b\xf5\x6e\xa4\x2c\x8b\xc6\x24\x63\x91\xb3\x5a\xc1\xfa\x65\x2d\x8a\xfa\x5a\x61\xbd\xb3\xb6\x01\x49\x68\x9b\x8b\xb9\xa1\xe8\x47\xe3\x1d\xf6\x05\x3f\x94\x2f\x29\x1f\xd0\xda\xc9\xed\xa2\xcd\xcc\x97\xf8\x00\xed\x10\x78\xbe\x24\xde\xcc\x41\x3a\x53\xbe\x54\x3a\x68\x46\x5b\x55\xe6\xeb\x01\xc2\xe9\x5e\xd8\x9d\xf9\xb2\x0c\xf5\x81\xab\x46\x11\xf4\x20\x5f\x56\x9b\xa2\x86\xc3\x8d\xe6\xcb\x9d\x6d\xc3\x9b\xe5\x94\xaf\x95\xe1\x57\xf2\xb5\x1a\x18\xaf\x68\x29\xdb\x09\xf9\x5a\x6b\xf0\x5b\x29\x5b\x60\x53\x67\x9b\xf6\x07\xde\x00\x18\xd9\xbe\x56\x52\x2e\xf0\xad\xb9\x60\x60\x45\xc2\x8e\x07\xe9\x0d\x82\x27\xd8\xa2\x5c\x34\x3e\xa0\x5f\xcc\xaa\x60\x2f\xe4\x42\x47\x97\x8b\x1d\x07\x68\xdd\x40\x39\x98\x62\xe0\xe4\xac\x84\x35\x29\x1c\x6a\xf1\x79\x81\xae\x1d\xf4\x06\xd3\x85\x36\x0b\x3a\x55\xd6\xa0\xc0\xca\xe2\xfa\xb9\xbc\x14\xc2\xf0\xec\x6d\x21\xdd\x35\x65\x3f\x0e\x45\x82\x61\x3b\xd6\xc2\x4b\x81\xc3\xc9\x0e\x53\x9d\xbd\xc0\x03\x64\xaf\x9b\x35\x54\xab\x24\x07\xf0\x42\xf6\x8a\xb1\x79\xa5\x30\xbc\x76\x38\xd3\xec\x0d\xab\x8a\x74\x5f\x64\xd3\x0e\x8b\x8a\xf4\x24\xa0\xc9\xde\xda\xcb\xbf\x0d\x83\x79\xc9\xde\x66\x38\x7a\x6f\x5f\x83\x39\xc9\xb0\x40\xd9\x99\xd5\x3b\x6b\x74\x30\x0e\x68\x0c\xac\x74\x76\x2c\x86\x47\xbc\x7c\x38\xa5\x39\x39\x88\xc5\x59\xae\x36\xb1\xf4\xbe\xe0\xc3\xb3\xaf\x18\x4c\x06\xa7\x47\x81\xfb\xe3\x53\x53\x86\xc1\x02\xc5\xfe\xcf\x21\xc7\x04\xad\x20\x8d\x19\xd8\x20\x21\x94\x63\xc8\x5d\x40\xff\x9e\x94\x43\x59\x49\xe1\x3b\x73\xa8\x82\x87\xde\x29\xc3\xa4\x61\xa3\x85\x41\x4c\x61\xa3\x83\x02\x2e\xe4\x70\x3c\xc3\x76\xe6\x78\x47\x19\x7e\xef\x29\xc7\xca\x86\x79\xc5\x52\x52\xc3\x50\x63\x55\xee\xee\x58\x8d\x35\x17\xc7\x81\x8e\x9f\xc1\xed\xbe\x36\x4d\x79\x95\xb9\x20\x8d\xd5\xf1\x7b\x8d\x7b\x5e\x61\x8e\x8d\xb6\x22\xa8\x4c\xeb\xdf\x0e\x5b\x81\xbd\xb9\xc6\xc5\xad\xb5\x06\xcc\x77\x5e\x90\x01\x3d\xd3\x2e\x7b\xda\xa5\xc2\x50\xed\x30\x49\x3b\x1d\xf2\xfe\x82\xae\x5d\x68\x91\x77\x88\x63\xe7\xc6\x67\xe6\xdd\xd2\x2e\x4f\xda\xb1\x93\x77\xdd\x64\x2a\x92\xb0\x91\x76\xcd\x70\x5d\xbb\x66\xad\x1b\xea\x2a\xa0\x33\x92\x02\x2d\xda\x15\x8b\xc9\xea\x10\xe5\xc0\x03\x6b\x1d\xda\xf8\x72\xbc\xb5\x0e\x30\x27\x60\xdd\xb5\xb0\xa7\x62\x5f\x56\xac\x70\x2d\xbb\x56\x63\xf5\x66\x1c\x41\x23\x76\xda\xb5\xa1\x26\x31\xdd\xae\x5d\x59\xb1\xfb\x30\xbe\xce\x0b\x14\x28\x60\x57\x82\xb0\x5d\x47\x0e\xdb\xf8\xa0\x6c\x32\xec\x6c\x48\x3e\x20\x1d\x86\x69\xd7\x31\xc3\xd1\x64\x8a\xa1\xa7\x09\xc5\xdb\xf5\xab\xc5\x3b\x52\xd8\x8f\x5d\xbf\x50\xa9\xdd\xe4\x84\x0a\xed\x1c\x93\xc1\x50\xec\x48\xe3\x49\x3b\xab\x99\x0e\x45\x89\xce\xb4\xdb\x71\x60\x3a\x76\xd2\x88\xef\x76\x36\xd8\x90\xdd\x8a\xd6\x2a\x69\x37\x62\x9e\xdd\x9a\x0f\x59\x78\xa0\xc2\xef\x86\x61\xda\x78\xa1\xfc\x6e\xe3\x55\xe9\xdd\xc6\x2b\x4a\xc3\x2a\xd9\xa8\x36\x06\xd2\xd7\x87\xef\x36\x3a\x45\x68\x63\xbe\x4b\x0b\x49\x82\xcf\x97\x2b\x63\x5f\x0f\xe6\xfe\xfd\x3d\x69\x77\x86\x28\xbb\xe7\x45\xe3\xbd\xfb\x99\x76\x2f\x05\xa4\x5f\xd6\xd2\xee\x55\x98\x34\xae\xa2\xb7\x8f\xa2\x55\x63\x23\x12\x0c\xc4\x17\x94\x78\x07\x7e\xde\xb9\xb7\xf6\x90\xd3\x1b\x12\xcc\x2e\x84\x81\xd2\x1e\x72\xa7\x9d\x3b\xea\x8d\x78\xf6\x30\xd6\x35\x74\x18\xd6\x3e\xa0\x1d\x84\x8c\x20\xf1\x58\xa8\xfc\xa4\x7d\xe5\x4f\xda\x57\xdd\xd2\xbe\xa0\x31\xeb\xd5\x53\x60\xd9\x9d\x66\x6f\xe7\x4a\xdf\x12\x47\xda\x9f\x26\xb0\x57\x2a\x50\x69\x15\xc4\x11\x2a\x51\x1e\xd0\x06\x32\xaf\xa4\x32\x8c\x39\x63\x82\x3c\x49\xf3\xe5\x49\xf3\x0b\xd4\x34\x7b\xf3\xfa\x24\x05\x64\xe1\xe6\xd7\x7d\xc1\x33\x26\x3d\x68\x11\xf5\x3c\x93\x12\xc3\xa8\x11\x99\x68\xd9\xfc\x4e\x5a\x76\x3e\x6b\x9e\x81\x11\x14\x3d\xa5\x4d\xa4\x14\xaf\x16\xed\xd7\xbf\x8c\xaf\x40\xf2\x5a\x0c\x4c\xcb\xd0\xa4\x75\x93\xf8\x20\x01\x62\xd3\x0a\x8c\x85\x5c\x85\x1b\xd4\xea\x74\xbc\x5a\x7b\x71\x94\x76\x47\xb0\xa3\xb5\xcf\x27\x69\x23\x44\xd0\x06\xbc\x8f\x6d\xa0\x80\x39\x63\x20\x75\x58\x44\x6d\x8a\xc9\x34\x0d\xcc\xad\x1d\xd4\x00\x6d\x27\x8c\x80\xb6\x13\x7b\x50\xdb\x45\x6d\xd1\xf6\x03\xfe\xad\x60\x87\x69\xf3\x75\x5e\x49\x5b\x58\x66\x02\xd5\x80\x7f\x0f\x54\x84\x6d\xc0\x56\x7c\x5f\x02\xad\xb8\x4f\x34\x69\xb7\x01\x97\xa3\xff\x01\x63\xe8\x7f\xcb\x7a\x02\x06\xd2\x80\xde\x6a\xb0\x2c\x7c\x70\x46\x11\x90\x43\xac\x3e\x93\x8e\x2c\x68\x3e\x86\x3c\xa0\xca\x11\x8d\x49\xc1\x4f\x0d\x00\x27\x9d\x97\xe5\x91\x14\xda\xcc\x62\xb8\x61\xfd\xfa\x07\x8f\x5e\xbe\x9a\xf4\x97\x72\xf8\x95\x0a\xa7\xa0\xbf\x8c\xe9\xf5\xf7\x1f\xca\xd0\xdf\x4c\x91\xff\xe6\x82\x30\x49\x7f\x19\xda\xeb\xaf\xd2\x46\xea\xaf\x46\x36\x66\x5c\x02\xed\xd2\xdf\xcb\x36\xac\xff\xaf\x91\x19\xc5\xf2\xcb\x0c\x87\x52\xeb\x6f\x87\x85\xd2\x5f\xc6\x6e\xfa\xdb\x29\x8e\xdf\x5e\xb0\x6d\xf4\xb7\x3b\x79\xf5\x78\xc7\xc0\x10\x4d\x7f\x27\x64\xf1\x28\x7e\x40\xb4\xe9\x10\x60\xe4\x74\x60\xc1\x0f\x81\xb9\x7f\xd2\x01\xbb\x7a\x88\xb5\x09\x3a\xaf\x74\x00\x51\x1e\x02\x55\x39\x10\x28\x1c\x52\xa1\xc1\x07\x62\xea\x91\x0e\x69\xf8\x65\x64\xb4\x09\x85\x3e\x10\xa7\x1e\xf2\xfa\x81\x43\xc0\x06\xb6\xe7\x10\xea\xeb\x21\xd3\x10\xcc\x1e\x8c\x35\x0f\xf9\x7a\x40\x2c\x87\x0a\x5d\xcd\xa1\x5b\x2c\x98\xb2\x43\x77\x85\x3b\x06\x74\x38\x54\x77\x10\xbc\x55\x29\xc8\xc0\x0a\x1c\x3a\xa6\x7d\x59\x07\x3b\xf1\x20\xd0\x39\xf4\x4e\x87\xc1\x25\x1c\xf6\x06\xa0\x87\x69\xd9\xd3\x61\x27\xf9\x43\x9a\x87\x95\x0a\x32\x59\x0b\x8b\x7b\x20\xc2\xa1\x4f\x38\x8c\x0e\xe9\xb0\x06\x2b\x77\x18\xdb\x60\x42\x06\x98\x7e\xd8\xc8\xac\xce\x32\xbc\x4f\x22\xf6\xc3\x7e\xd3\x51\xe4\x04\x81\x88\x0a\x1c\xd9\x51\x30\xf9\x82\x29\xa6\xa3\x60\x1e\x85\x3b\xf7\x00\xd6\x3a\x8a\xb3\x14\x88\xeb\x28\xce\x2a\xdc\x5a\x47\x59\xb6\x83\x92\xc3\x93\x0e\x97\x9a\x0e\xcf\x90\xb5\x9f\xe9\x00\x8c\x3a\x1c\x33\x72\x9e\x8e\x1c\x08\xcb\x0e\xf7\x99\xde\xed\x85\x28\x73\xf0\x05\x81\xc9\x81\x20\x1f\x96\x03\xd6\xeb\x70\x98\xb5\xc3\x83\x61\xf3\xe1\x63\x90\x17\x51\xdc\xc1\x63\x84\xc3\x7f\xd3\x11\x72\x52\x4a\xc1\xa9\x84\xfe\xb7\x60\x43\x8e\x50\x8c\x28\x0c\xaa\x74\xc0\x0c\xa2\x10\x23\x0a\x67\x31\x50\xd2\xc1\x38\xe9\x08\x07\x5c\x3d\x62\x41\x44\x80\x1d\xc7\x6a\xf8\xb5\x27\x1d\x2b\x1a\xd5\x0d\x20\xfd\x58\x5c\xf4\x53\x18\x44\x31\xd8\x3e\xa5\xc8\xef\x83\x84\xe0\xfe\xc4\x18\x4e\xe9\xe9\x14\x1e\x10\x9c\x12\xdb\xbf\x14\x31\xd4\x29\x51\x2c\x23\xa1\x9d\x3b\x65\xe0\x87\xda\x13\x75\xa8\x71\xa7\x2c\x36\xf8\xd3\x74\xc2\x14\x49\x41\x6a\x6b\x20\x09\x66\x22\xde\x38\xb5\x2d\x28\xc0\xa9\xe3\x1d\xd4\x85\x09\x9d\x06\xb3\x79\xc2\x5f\x9c\x76\xc2\xa2\x9f\xaf\x82\x9c\x16\x72\x1c\x78\x8d\x92\x4e\x38\x8e\xb3\xc8\x0e\x02\xd5\x3c\x8b\x04\xe9\x18\xe9\x2c\xf0\x7f\x67\xb1\xda\x07\x52\xdf\x48\xbd\x82\x62\x8a\xc5\xd9\xda\xef\x74\x22\x9c\x3e\xa1\x18\xa7\xef\x3b\x14\xeb\xc4\x4a\x9f\x58\xe2\x93\xc1\xc3\xe9\xf0\x5a\x92\x4e\x1f\x5d\x0b\x92\x61\x3d\x9d\xf0\xcf\x2d\x9d\x10\xfe\x19\xb2\x81\x60\x14\x8c\x92\xcf\xe0\x14\x02\x16\xee\x64\xac\x7c\x86\x7c\x01\x03\xce\x50\x74\x15\x0a\x49\x86\xed\x20\x7a\x80\x22\xd7\x33\x17\x20\x7c\x75\xd0\x3b\x9d\xb1\xc0\x68\x41\x79\xce\xc5\xd1\x2d\x4e\x6d\x59\x41\xbe\x4d\x89\x74\xae\x96\xce\xa7\xa6\x4b\x60\xbd\x18\x75\x5d\x52\x8e\x74\x49\xad\x8a\xe7\x4a\x75\xbb\x60\xbc\x2e\xe9\xfd\x49\x17\xa2\x49\xe4\x04\x72\x62\x5c\xa0\x5f\xe8\x30\x82\x2f\x9e\x93\x5c\x72\x7f\xd2\x25\x7f\xac\x82\x08\xff\x52\x29\xf3\x42\x12\x13\xf4\xfb\xa4\x0b\x3e\xf3\xf2\x33\x5d\xaf\x7f\xbc\xb4\x14\x07\xad\xca\x97\x9e\x2e\x6d\xe9\xd2\xf0\x74\xd9\x0e\xe5\xb9\xec\xbc\xd2\x05\x10\x70\xc1\xda\x5d\xd6\xd3\x85\xfd\x7e\xd9\x98\x58\x98\xcb\xb7\x0d\x34\x03\x7b\x5c\x58\x88\xcb\x8b\x82\x18\x50\xe9\xf5\xee\xbf\x0b\x01\xcb\xe5\x8d\x75\x1c\x75\x3a\xde\xa3\x81\xc0\xc5\x5c\x74\x85\x97\x8f\x37\x90\xa6\x5a\x5d\x3e\x15\x8f\x0b\xc5\x30\x5b\xd7\xda\xd2\x05\x3d\xbd\x56\x95\x06\x0a\xcf\x7a\xad\x0a\x06\xab\xed\xa1\x3b\xd2\x13\xc3\xc2\x2a\x5c\x2b\x76\x56\x08\xe6\x40\x0a\x6b\x6c\x14\xea\xb3\x61\x29\x81\x04\x2d\x7b\x4b\xb6\xab\x24\x1e\x2b\x23\x48\x34\xb4\xb2\xb3\x21\xc8\xc1\xcc\xad\x00\x2a\x30\xa5\x21\x33\x02\x74\xab\x46\xdf\x67\xb5\x12\x2f\x5b\xad\xb0\x1f\x56\x3b\x3c\x9c\x55\x7a\x17\xab\xef\xc9\xa5\xd5\xbe\xe0\x1c\x0c\x91\x84\xb5\xd7\xbd\x59\x63\x20\x67\xed\x1f\xfc\xb6\xb6\xeb\x2f\xa8\x11\xcd\x58\x23\x8a\xb3\x06\x24\x15\x4f\xb2\x06\xef\x81\xa4\x58\x66\xea\x51\x93\xb5\x0b\xd6\xde\xda\xa5\x50\x49\x6b\x36\x81\x79\xad\xfd\x28\x2b\xfd\x2c\x36\xad\x2f\x47\x20\x59\x6b\xcd\xb3\x92\x53\x5f\xa0\xff\x2d\x63\x9d\x81\x70\xcb\xda\x78\x1b\x22\x2c\x44\x42\xa7\x69\x0d\x11\x0f\xd8\x4e\xce\x0e\xf8\x02\xda\x67\x6d\x7a\xb2\xf6\x7d\x9f\xbf\xc6\x4e\x5e\x4f\x6f\x01\xc1\x8e\x02\x79\xdb\xf0\xc2\x01\x8c\xb1\x34\xd9\xd4\x9a\x00\x75\x9f\xf4\xf3\x1e\x55\xfd\x08\x76\x4c\xfa\xe1\xef\xef\x2f\xfd\xa8\x14\x38\xce\x1f\x95\x06\x5a\xca\x93\x7e\xf4\xd6\x92\x7e\x7c\x4b\x3f\x08\x90\x7f\x00\x2a\x7e\x7c\x05\x94\x0a\xb0\xe8\x67\x01\x0f\xfe\x2c\x2c\xea\x0f\x62\xef\x9f\xc5\x53\xea\x9f\xd5\xcc\x03\xc9\x27\xf1\x10\xff\x23\xed\x94\x70\x4f\x1f\xec\xe9\x8f\x6a\x4f\x1f\x38\xc7\x85\xf4\x49\x1f\xcb\x9f\xf4\xb1\x1d\xbf\xc6\xf7\x86\xe7\x76\xee\x5e\xd3\x07\x70\xfe\x63\x13\xbf\x8c\xbd\xf2\xc1\x94\x3f\x36\x27\x9f\x6f\x4b\x9f\xa6\x9a\x3e\xcd\x0e\x50\x38\xae\x4f\xf3\x3b\x15\xd9\xf0\xd3\x02\xea\x91\x8a\xec\x00\xa3\x45\xf6\x27\x15\xf9\x68\x2a\x08\xf7\x8a\xb4\x73\x41\xb7\x8a\xf4\xe9\x78\x0f\xbe\x4c\x56\x9d\xd6\x52\x41\xdc\x07\xda\x00\xbc\x8b\x7c\x25\x15\x01\xfb\x1b\x65\xf7\x80\x33\x29\xf2\xb0\xfe\xdf\x93\x8a\x0a\xbb\x51\x39\x40\xa2\x81\x7e\x35\x01\x03\xc3\x7e\x17\x3d\x66\x2a\x7a\xa6\x57\xc1\x8b\x9e\x70\x5c\x45\x6d\xbc\xa5\xd5\xd1\x82\x59\xed\x9c\x17\x92\x91\x8a\x7a\x87\x91\x01\x8a\x65\x39\xcf\xe0\x0a\xe2\xb0\x54\x4c\x22\x15\x40\x8b\xf9\x20\x0d\xc0\x94\x62\x99\x3b\xa4\x40\x28\x05\x6e\xe2\xf5\xf1\xc5\x30\x71\xab\x1b\x08\x06\x8e\x28\xa3\x00\x8e\x14\xfb\x0f\x0e\x9e\x38\xb7\x18\x8f\xba\x10\x73\xa6\x62\x34\x6f\xc5\x85\xa4\xa5\xe2\x1b\x4d\x65\x71\x40\x0e\x02\x85\xe2\xa7\xe5\x54\xbc\x69\x79\x90\x9c\xa9\x38\x64\xe9\x18\x26\x72\x16\xda\x2e\xb8\x66\x3a\x95\xe2\x0f\x9a\xae\xfc\x79\x52\x59\x27\x71\x77\x59\x0c\x98\xcb\x6a\x42\x9a\xaf\x54\xd6\x2f\x76\x52\x79\x02\x08\xb7\x4a\xbe\xe0\x08\xab\xec\xa9\x0a\x3a\xac\x72\x36\x9d\xa9\x8a\x21\xc7\x4a\x62\x6c\x56\xe5\xc7\x23\x55\xac\x70\x95\x5a\x05\xd9\xc8\x6d\xe8\x05\xe1\x33\x76\x45\x95\x76\x3a\x28\x31\x77\x15\x7e\x39\xa9\x02\x80\x5c\x25\xb6\x37\xc9\x17\xe8\x49\x9e\xf1\x76\x1d\x1f\x76\x18\x61\x2f\xb7\xf1\x01\xc1\xe0\x28\x93\xca\x23\x43\x6c\xfc\x30\x32\x9c\x7c\x0b\xfb\x45\xf2\xd6\xf8\xb5\xba\x6a\xaa\xf0\xfb\x55\x65\xf7\x1b\x49\x03\xa1\x06\x54\xf8\xbe\xaa\x40\xe7\x98\xa2\xee\xe0\xa3\xbb\x49\xaa\x5a\x10\x09\x55\x2d\xa8\x40\x69\x55\xad\xd8\xd2\x00\x19\x9c\x87\xb6\x95\xaa\x46\x46\x16\xf4\xb8\xd2\x40\x55\x9e\x07\x56\xe0\xa4\x8a\x58\x82\x05\x93\x7c\xe7\xe5\x7b\xaa\xb6\xc3\xfc\x56\xdb\x1b\x95\xa4\x5a\xf9\x80\x50\x2f\xaa\x21\x76\xac\xd8\x91\xd5\xda\x3b\x76\x43\xbc\x5b\xad\x21\x42\xa8\x16\x92\xd9\x9a\x5e\xa5\xda\xc0\x92\x33\x06\xaf\x08\xb9\xb1\x0c\x98\xbe\xfd\x2a\x38\xfc\x72\x13\x54\xdf\x00\xe5\xaa\xef\x5a\x40\xe1\x02\xaa\x57\xfc\x60\x25\xab\x37\x43\x34\x58\xdf\xf8\xba\x7a\x7b\xa5\xeb\x0d\xf2\x74\x8c\x8a\x67\x62\xd5\xc9\x2b\x1a\x82\xdf\xea\xe3\xbf\x65\xd3\x53\x7d\xcf\xc6\xff\x45\x88\xd5\x5f\x4e\xab\xf1\x38\xa8\xf2\xfb\x40\x85\x16\x56\xff\x9a\xa6\xba\xb0\x62\xeb\x38\x50\xb8\x30\xa8\x55\xa6\xf5\xf2\xa4\xba\x06\x27\xb6\x86\x62\xd2\x6b\x5c\x3c\x7b\xaf\x6b\x40\x20\x30\x6b\x75\xf1\x13\x66\x7d\x86\x96\x03\x09\xd5\xbd\x3e\xf3\x4a\x4d\xb0\x79\x1a\x60\x62\x93\xfe\xb1\x96\xda\xfb\xd5\xab\xc9\x98\x4f\x6a\xc2\xc1\xb5\x37\xba\x68\x2a\x91\x9a\xe6\x4f\x6a\x08\x29\x9a\x9e\x32\xd9\x5c\x4f\x9e\x48\xb6\x7f\x41\x75\xd3\x7e\xe9\x9d\x9a\x06\x0b\x07\x4a\xf8\xe3\x37\xb3\xa6\x6b\x42\x2a\x8d\x01\x47\xd3\x7b\xa4\xa6\xbf\x33\x35\x98\xe7\x77\x65\x9b\x43\xb5\x9b\x23\xa2\x6b\x5e\x0d\x86\xb3\xb9\xef\xcc\x0c\xec\x95\xe6\x81\xd1\x3b\x2b\x4c\x79\xab\x4f\x92\x0b\x52\x6e\x88\xf2\xf0\x0a\xd3\x03\x33\xdb\x56\x2e\x1c\xfe\xbb\x7f\x1b\x8f\x1c\xdb\x9a\xc9\xe5\x93\x7c\xd3\x27\xf9\x46\xbf\xe8\x5b\xb1\x53\x93\x6f\x23\x63\xce\xbe\x0d\x4e\xc3\x37\xae\x8b\x6f\x5f\x1e\xdf\x79\xce\x2b\x92\x67\x6c\x09\xcf\xd3\xc1\xd3\x77\x8f\xe4\xc7\x81\x9f\xf2\x09\x43\xf0\x03\x0e\x00\x61\x87\x7f\xe4\x49\xc0\x41\x4e\x8b\xe5\xe5\xa9\xdd\x72\x72\x18\x38\x07\xec\xf5\x86\x1f\x04\xee\x8d\xe7\x70\xde\xca\x93\xbc\xa3\x7d\x47\x20\xee\xdd\xde\xe2\x4e\x08\xe1\x9d\xab\xe3\xef\xb7\x4b\x0f\x40\x46\x8f\x4c\x28\xf8\x9e\x2a\x79\xec\xd6\x60\x68\x3d\x4e\x8c\x34\x78\x80\xed\x61\x27\xe3\x36\x8f\x7e\x21\x7b\x4c\x9e\x14\xbc\x0a\xe9\x6b\x12\x5d\xf8\x9a\xef\x1b\xa0\x80\xaf\x49\xaf\xef\x08\x18\xfd\x8b\x11\x61\xf5\x80\x98\xfd\x06\x74\xf0\xdf\xe7\x44\x2e\x95\x2b\xf9\x1f\xe6\x42\xb8\xd3\x85\xbb\xb6\x63\x3b\xf3\xb0\xae\x4b\x01\xba\xee\x52\x6a\x42\x10\x2e\xa0\x5a\x40\x2d\x83\x72\x14\x5d\x3a\x69\x20\x9e\xee\xc2\xb3\xd2\x2e\xf1\x01\x09\xe7\xf3\x7c\x52\x87\x51\xeb\xb4\x66\x1d\x46\xac\xcb\xb4\xb7\x26\x4f\xac\x3b\x8d\x59\x4b\x9d\x5f\x41\x3a\xfc\x5b\x97\x87\x7b\xb7\x2b\x07\xa1\x02\x1d\xe0\x07\xe5\xae\x32\x84\x25\xc5\xb2\xb4\x04\xb1\x77\x6d\x82\xa8\xbe\x6b\xcb\x56\x52\x57\x87\xe9\xed\xca\x53\xef\xae\x71\x40\x63\xba\x06\x96\xb0\x6b\xc0\xe9\x75\x9d\xa9\x5f\x9c\xfe\xe5\xd3\x53\xbf\x78\x7a\xd2\xaf\x67\x18\x3c\x51\x37\x69\x9e\xba\x65\xce\xd6\x5e\x6f\xdb\x4d\x31\x1a\x3b\xf1\x53\x70\x01\xba\xec\x56\x30\x53\xf8\xbe\x6e\xde\x14\x7d\x5a\x47\xbd\x31\x31\x3b\xe3\xbc\xed\xef\x4f\x52\x7f\x65\x5a\x04\x3b\xad\x97\xf7\xe4\xae\x13\x59\xf1\x58\xb1\x17\xe2\xc8\x5e\x78\x34\xd6\xe1\xd3\x40\x4f\x10\x28\x4f\x77\xad\x20\x33\x75\x07\x9a\xef\x5e\x20\x12\x00\xf6\xee\xf0\xd2\xa9\x7b\xdb\x41\x9e\xd4\x1d\x9d\x7b\x5f\x6f\x95\xa0\x12\xf2\x00\xf7\xdf\xc3\xb0\x8d\xed\x06\xf8\x4c\x81\x10\xfe\xb9\xd8\x0e\xad\x81\x3c\xfd\x86\x7a\xbe\xa7\x61\x3d\x24\x73\xb7\xf6\x10\xec\xf8\x1e\xca\x1b\x16\x3d\xf4\x60\xb1\x62\xfd\x91\xf2\x2a\x48\x0f\x9d\x60\x11\xfa\x7d\x5f\xdf\xa6\xd0\xce\x1e\x56\xa1\xed\x3d\xec\x2d\xf1\x30\x56\x35\xae\x4c\xd8\x97\x02\x09\xfb\x03\x85\x91\xa9\x48\x79\xd2\xd4\xc3\xf7\x45\x4e\x7e\x60\x35\xc3\x79\x4c\xdc\xc3\x69\x16\x7a\x78\x75\x36\x76\x3f\x40\xfb\x3b\x91\x40\x24\x89\x41\xfa\xfc\x57\x6d\xed\xa0\x3c\xb5\xed\x6b\x43\x7c\xdd\xd7\xbe\xc3\x28\xf5\x85\x45\x5d\xa5\xa7\x17\xf2\xf7\x55\x69\x72\x3b\x61\x44\x5f\x1d\x2a\xb6\x10\xd4\xf5\x15\xef\x17\xb4\xbe\xde\x19\xac\xe0\x8e\xef\x34\x5b\x7d\x0d\x54\x9f\xa9\xaf\xbf\x3f\x48\xfa\x09\xa9\xb6\xa7\xff\x96\xf0\x12\xcd\x7f\x4b\xda\x5c\x15\x69\x60\x37\xfe\xb7\x74\x70\x6d\xfe\x5b\x40\xb0\x70\x3f\x20\x7f\xe9\xbf\x85\x29\x85\x6c\xb0\x1c\x21\x39\xc3\x67\x31\xf6\xe5\x77\x97\x90\x5d\x02\xd4\x3c\x05\x80\x0b\x03\xe2\x77\x91\x42\x80\xbc\x03\xd8\x34\x04\xc3\x0f\x69\x80\xc1\xaf\x2d\x0a\xe9\xb6\xa7\xc0\xb2\xf1\x3b\x42\xbc\x67\x09\x21\xb0\x1c\x21\x77\x0a\xf9\xf3\x48\xef\x2d\x14\x7e\x69\x44\x9c\x83\xce\x15\x48\x38\xf4\xfd\x12\x1c\xca\xef\xb1\xa1\x59\x61\x31\x43\x33\xd4\x3f\x34\x7b\xb0\x90\x5f\x46\x42\xb9\x6e\xa1\x07\x9d\x50\x28\x83\x9f\xd0\x03\x7b\x3e\xf4\x34\xb2\x3d\x43\x51\x76\x52\x69\x43\x7f\xde\xaa\x45\x7e\x41\xb9\x37\x42\x0b\xc2\x77\xde\x5d\x08\x25\x46\x0b\xfd\x07\x60\x42\x89\x2c\x42\xe9\x91\x43\xdb\xce\xcc\xa6\x77\xa2\x65\x0a\xa5\x95\x86\xa6\x1a\x0a\x3a\xd0\x51\xe8\xbb\x2b\x43\x79\x7b\x27\xf4\xbd\x70\x14\x3a\xf2\x62\xa2\x8c\x52\x43\x79\x55\x24\x74\xf8\x0a\x56\x1f\xdd\x1b\x07\x34\x56\x41\xc1\x7c\x9b\xcd\x78\xb9\xce\x15\xe8\x6a\xb5\x77\x66\xdf\x57\x7c\x5f\xe3\x60\x78\x36\x15\xd7\x33\xaf\x9a\xc2\x36\xfc\x36\x54\xc3\x26\xa1\x91\xe7\x46\x79\x3f\xea\x87\x1d\xe8\x9f\x2e\x17\x2e\x61\x4f\x3c\x9e\x0f\x73\xbc\xf3\x7e\x0d\xbf\xf1\x87\x11\x3f\x04\x4f\x0b\x83\x5f\x78\x02\x38\x3b\xf8\xb5\x32\x7c\x73\xd2\xc5\x17\x46\x6d\xe1\x95\x07\x39\xdc\x2c\xe1\xfe\x31\x3e\xd7\x14\xd0\xe2\x70\x86\xc7\xc1\x53\xea\xf7\x02\x4e\xc0\xdb\xa4\x20\xe0\x8e\xb5\x51\xe6\x08\x84\x63\x9d\x29\x00\x77\x62\x35\xfc\x6e\x79\x52\x2c\xc0\x87\x21\x3b\x7e\xf0\x2d\x43\x76\x46\xdf\x43\x0e\xbc\x18\x0a\x0b\x8b\x0b\xc2\x94\x21\xe5\xa5\x13\x04\xfd\x0c\xe0\x9d\xf1\x1e\x34\x0f\x44\xa1\x43\xa6\x8d\xe3\x41\xea\xe3\xb2\x34\x04\x2a\x35\x64\x11\x85\x0e\x38\x8e\x21\x4f\x1a\x19\x01\xf5\x80\x77\x18\x19\xca\x3d\xf2\x0b\x97\x47\xd6\x86\xb7\x4b\x2b\x13\x58\xc8\x91\x8d\xe7\xac\x23\xdb\x18\x1e\x23\x8d\xec\xc1\x0f\xe7\x23\xfb\x9a\x69\xe4\x90\x0e\x8a\x58\x73\xe4\xb0\xce\xbc\xb5\xa5\xa1\x82\x1f\x80\xfd\x78\xb7\xc5\xc0\xca\x0f\xcd\xb0\xc1\x43\x33\x74\x19\xb1\x38\x99\x69\x7e\x6d\xc4\x00\x26\x1b\xaa\x9f\x34\xf4\xa4\x8f\x1b\xfc\xa2\x81\xa4\xa4\x01\x0d\x96\x48\x43\x19\xf3\x0e\x86\x5d\xb0\xa7\xef\x18\x35\x4c\x07\x12\x7e\x2a\x1b\x3a\xc6\xcb\x9b\x01\xd6\xd0\xb9\x7a\x1a\xb0\xb7\x69\x5c\x8c\x05\xc6\x25\xc7\x04\xe5\x21\xce\xb8\x28\x8c\x0b\x03\xb8\xd8\xdb\xa5\x61\xc7\x91\xc6\xc5\xd3\xe3\x71\x19\x6b\x03\xd3\x8c\xcb\x3a\x08\xb4\x68\x5c\x08\xcb\xc6\xe5\xc8\x76\x47\x15\x47\x21\xb6\xcb\xb8\x7c\xf1\xb3\xcc\xb8\xb0\xe7\xc6\x15\x56\x51\x06\x8d\x18\xd7\x3a\xa0\xba\xe3\x7a\x12\x9c\x0d\xb4\x76\xc0\xb4\x11\xa3\x0c\x53\x2c\x1a\xd5\x9a\xdf\x0a\x87\x15\x8a\x03\xf1\xc2\x30\xd8\xad\x61\x85\xfd\x5b\x35\xd8\x83\x61\xaf\x2a\xf0\xeb\xf6\x78\xb9\x05\x26\x6b\x44\x33\x03\xfa\x0f\xb5\xb1\xdf\x34\xe0\x3b\xc6\x87\xaf\x3c\x1b\x48\xe3\x63\xf8\x61\xd6\x30\xe6\xe3\x63\x18\xfd\x07\xb6\x7e\x20\xb8\x1f\x45\x6a\x1a\x45\xb5\x83\xd2\x72\x0c\x7a\xd4\xc1\x93\xcd\xf1\x46\xbc\xa3\x18\x6a\x39\x60\xda\x80\xdb\x1f\x14\x2c\xcf\xb1\x47\x85\x15\x1c\x55\xc0\xb8\x22\x22\x19\xd5\x3f\xa4\x3e\xaf\x34\x1a\x8c\xf5\x68\x88\x61\x46\x83\x4e\x35\xca\x1e\xb0\x77\x38\xde\x3d\x67\xf4\xea\xfc\x92\x3d\x28\x73\xdf\x25\x0d\xc7\xaa\xd0\xd3\x0f\x2f\xbb\xb1\x4e\xb1\x1d\xf4\xbd\x30\x32\x78\x5e\x33\xbc\x2a\x00\xcd\x40\xc8\x3c\x9c\xf9\x08\xd5\x06\xd7\xc9\x17\x78\x62\x13\x0f\x87\x9a\xbc\x56\x6c\xf8\xc2\xd0\x3a\x0c\xe0\xa0\xff\x1e\x00\x67\xe8\xbf\xcb\xdd\xd2\xe8\x2a\x1f\xd0\x77\x4c\x9d\xca\xdb\xa9\x3b\xfc\x24\x3c\xfa\xa5\x6c\x44\x49\x75\x5e\x44\x18\xdd\x3e\x7c\x41\x73\x43\xc8\x38\x7a\x21\x05\xbc\xa6\xd5\x84\x6a\x77\x8e\x90\x36\x77\x74\x48\xb2\x07\xf6\x6e\xe7\xe5\xa6\xd1\x69\xe3\x46\x7f\xd2\x80\x7f\x54\x24\xbc\xef\x84\xb0\x8c\x37\xd5\xc6\x1b\x4f\x8c\x29\xbb\xad\x8a\x14\xd2\x9c\xb4\x04\x53\x0c\x3b\x79\xc2\xef\x8d\x49\xd3\x31\xb9\x2c\xb4\x68\x63\xa2\xa3\xc9\x99\x4d\x25\x2b\x05\x03\x2c\xfd\xd4\x50\x4f\xc0\x65\x28\xa4\xba\x4c\x8e\x64\x72\x3d\xa6\x57\x81\x32\x4d\x0a\x7a\xd2\x80\xf0\x18\x75\x4c\xaa\xff\x84\x1f\x3d\xf1\x1a\x8a\xdd\x3f\x83\xb2\x98\xc1\x35\x99\xb1\x78\xba\x3e\xe6\xe2\x0d\xd8\x31\x17\xc7\xfc\x9e\x83\x8e\xf9\x80\xae\x37\xc0\x19\x6b\x03\x5c\x1d\x6b\x83\x31\x1d\xeb\xbd\x3c\x3b\x10\x5f\x8e\xc5\x93\xdd\xb1\x18\xc0\x8c\x75\x0a\xe9\x89\x10\x8e\x07\x48\x63\xf1\x18\x7a\x2c\x54\x6a\x0d\xcd\xdb\xc0\x70\x56\x67\x76\x47\x40\x3a\x56\x0f\xda\x41\x20\xdb\xb1\x82\xdf\xc7\xc6\x42\xa0\x3f\x56\x00\x8c\xf1\xe1\x35\xfc\x63\xc5\x57\xd1\xe6\xbd\x45\x39\xd6\x60\x9c\x35\xee\x7f\x96\xe5\xa6\xa4\x6f\x21\x89\x9a\xc6\x0d\xac\x3e\x6e\x0a\xe1\xa6\x59\xb9\xb1\x73\x6e\xca\xf2\x26\x24\x1e\x37\xf0\xc1\x78\xea\x06\x29\x3e\xb5\x4f\xaf\x69\x3c\x01\xed\x7c\xb8\x24\xef\x0a\x4f\xe1\x0d\xa2\x29\x67\xe2\xbd\x81\x29\xb4\x13\x53\xca\x27\x4d\x69\x20\x1d\xc5\xfc\x14\x34\x65\x20\x63\x4c\xe4\xcc\xe9\x9e\xa6\xfc\x5a\x9a\xbc\xbd\x38\x55\x6a\x9a\xd0\x5e\x04\x7b\x53\x1b\x02\x89\xa9\xad\xd9\x40\x82\xe7\x40\x85\x81\xa7\xdf\x99\xe6\x45\xf6\x97\xe0\x11\xb2\x9a\x17\xda\x5d\x8a\x15\x9f\xd4\xfc\x79\x29\x1e\x31\xad\x79\x81\xcd\xe5\xbc\xd1\x35\xaf\x50\x94\xf2\x6b\xfb\xbc\x10\xab\xcf\x6b\xd5\x0d\x94\xc6\x65\xbe\x77\x5c\x26\x8c\xcb\xb4\x93\x39\x05\xef\x44\x32\xd3\xd0\x9b\xb5\x27\x4d\xeb\x09\xc8\x62\x4f\xf3\x3d\x7c\x9d\x06\x63\x3f\xe9\xd4\xa7\x6f\x80\x83\x69\xfa\x2e\x0f\xe8\x5e\xd0\xd8\x51\x7e\x2a\xc1\xdc\x74\x2b\xe8\x87\xd7\xfe\xa0\xbe\x13\xd5\xeb\x7b\x09\x91\x6a\x3c\xbd\x9d\x8b\x09\x4d\x1c\x95\x7a\xd2\x64\x4d\xef\xf8\x59\x06\xed\xec\x15\xde\x6e\x7a\x34\xd9\xc1\x26\x26\x83\xff\xe9\x63\xa4\xe9\x53\xd0\x70\x85\x71\x64\x84\x38\x93\xa1\xc3\x44\x00\x3a\xfd\x49\x93\x80\x75\x32\x5a\x9c\x21\x08\xbd\x91\x9e\x6f\x62\x0d\xb4\x0d\x68\xf5\x84\xd7\x9d\xbc\x39\x34\x81\x47\x4b\xe2\xbd\xd0\x17\x5c\x4d\xca\x16\xf8\x2e\x4d\x1e\x8d\x4d\x5e\x3d\x99\xbc\x0a\x39\xc3\x4e\x8a\x33\xac\x82\x80\x8d\xf7\x0b\x6d\xdf\x9b\x14\x33\x16\xab\x2d\x3e\x16\x14\xac\x8a\x78\x70\x06\xb0\xd1\x0c\x98\xc4\x89\x15\x5e\x60\xba\xde\x80\xe9\xdf\x26\x9d\xab\x09\x08\x42\xe1\xb9\xe2\x83\xd5\x07\xd0\x9b\x2b\xb8\x2c\xb7\xc2\x14\xcf\x5b\xdb\x7c\xd2\xbc\x61\x16\xe7\x8d\x89\xdd\x94\xca\xed\x69\x3e\xd0\xd6\xa7\x33\xcc\x5c\x67\x79\xd2\xaa\x5b\x68\x29\x92\xd6\x7b\xd5\x60\xb5\xf7\x36\xf0\x6a\x99\x6f\xef\xc5\x94\x57\x6d\x56\xdb\x3d\xad\xc6\x2b\xea\xab\xf1\x13\xe9\x6a\xef\x27\xa6\xd5\x8c\x98\x7a\x35\x5e\xcd\x5e\xcd\x26\xc8\x57\x11\x8c\xac\xf6\x69\x58\x85\xd5\x78\xc6\xba\xda\xb4\x92\x56\x5b\xbc\xa7\xb8\xda\x57\xf1\xda\x79\x9a\xb9\xfa\xc9\x05\x5a\x9d\x9f\x83\x56\xf7\x96\x16\x43\xe9\xd5\x61\x45\x56\x6c\xd2\x12\x0d\xc5\x0b\xbc\x80\xe0\x79\xe5\x7c\x0d\x3d\x56\x41\xc2\x0b\x12\xff\x98\xcf\xf7\x3f\x03\x5f\xc9\xd8\x6e\x5f\xc9\x6b\xd5\xf4\x15\xe8\xdc\x57\xe0\xc7\xbe\xef\x3d\xf8\xaf\x40\x74\x5f\x69\xf8\xd9\xb8\xd2\x57\xba\x47\xfa\xca\x7b\x15\xeb\x0b\x85\xff\xf2\x83\xfa\x57\x2f\x83\x68\xbe\x10\x36\x5e\xdb\x8e\x8a\xbc\x14\x89\xdc\x06\xd6\x1a\x1b\x88\x1d\x0f\x12\x02\xa5\x2f\x82\xdb\xaf\x8e\xa1\x25\x7d\x75\x6a\xa0\x2f\xa3\xcc\xbf\xb6\xf1\x0b\xe2\xd7\xf2\xdb\x9b\x65\xda\x75\x04\x88\x9e\x88\xda\xbf\x56\x0a\xa6\xfb\xb5\x36\xdf\xd4\x8b\x81\x41\x10\x77\x7f\x2d\xd8\x6e\x08\x88\x81\xd5\x78\xf3\x27\xe9\x17\x33\xe5\x29\xf7\x97\x17\x25\x79\xf9\xfb\xeb\x25\x4b\x73\xa4\xab\x22\x6f\x82\x3c\x60\x7f\xff\x23\xde\xd2\x2d\x36\xd3\x0d\x7b\x07\x7b\x0b\xd2\x16\x32\x1a\x48\x1c\xd0\x15\x5a\xdd\x5b\x02\xc1\x74\xba\xb1\x6d\x6e\x19\x1d\x64\xa2\x10\xf8\xe8\x06\x3e\x86\x33\xb9\xdf\xef\x8a\xb7\x0a\x96\x96\x96\xfa\x46\x6c\x55\x90\xd0\x68\xdc\xba\xa5\x5b\xdf\x70\xf8\x56\xfd\x60\xa7\xdd\x6a\x01\x5a\xf8\xcd\xeb\x86\x91\xbc\x75\xa6\x9b\x5f\xaf\x6e\xd8\xc8\xfb\xd2\x97\x82\x13\x2c\xe5\x4d\x13\x79\x03\x4a\xde\x97\x31\x02\xbf\x61\xef\x6e\xdb\xd1\xbf\x1d\x78\x2c\x3b\x48\x49\xd8\x25\xb7\x35\xc0\xd6\x1b\x08\x94\xae\xe2\xb6\xf6\x01\x69\x6c\xca\x4b\x31\x37\xc2\xac\xdb\x06\xc2\xd8\x1b\xd6\xe7\x86\xae\xdc\xff\xee\x28\xdc\x5e\x8e\x74\x23\xae\x49\xb7\x73\xc7\xdc\xee\x3b\x48\x49\xf4\x37\x3c\xdc\xbc\x3d\x0a\x1f\xe3\x01\xc5\x60\x60\x6f\xee\xd0\xfc\x01\xe5\x25\xde\x9b\x86\xec\xe6\xcd\x8d\x9b\x0e\xfc\x81\x49\x7b\x20\xaf\x47\xe9\xf7\x1e\x5f\xf8\xa1\x88\x40\xea\x4f\xb7\x90\xf4\xa7\xe1\x89\x47\x6b\x7f\xee\xe9\xff\x00\x00\x00\xff\xff\x96\xd2\xdb\xc1\x3c\x33\x00\x00") +var _keysWordlistEnglishTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\x5b\xdd\xbe\xbc\x2a\x08\xbd\xf7\x2d\xc9\xa8\xd8\xa3\xe2\x41\x9d\x76\xfb\xe9\xcf\x6f\xad\xfe\x17\x83\xe5\x07\x2a\x22\x2c\xcc\x91\x4d\xda\xee\x2d\xc9\x66\xc5\xe6\x93\x64\x2b\x9a\x64\xf3\x35\x41\xbf\x78\x1e\xda\xf0\x32\x3c\x36\x24\x33\x24\xf3\x7d\xc5\x9e\x64\x5b\x43\x93\xe4\xac\x63\x20\xb1\x9d\x95\x73\xf6\xf5\xa6\x6f\xf1\x65\x0a\x56\xd9\xf6\x24\xd9\xd7\x98\x96\x93\xe4\xff\x96\x05\x72\xc3\xd9\x18\xf5\xa7\x61\x2c\x79\x7a\x80\xc6\xcb\x75\x2e\x29\x49\x76\xe9\x33\xc9\xbe\xe3\x67\x99\x8f\x6f\xf9\xfe\xb3\x06\x5e\xab\x81\xae\x02\xfa\x95\x96\x15\xa9\x21\xd1\xf0\x0d\x3d\x1e\x87\x58\x20\x71\x0c\xfd\x08\xc1\x78\x4e\xb1\x96\xe4\x54\xfc\x30\xe6\x33\x54\x93\x5c\x2a\x7b\x12\xab\x89\x2d\x2c\xba\xc7\x4c\x62\x03\xd2\x29\x12\x35\x49\xd9\x16\x68\xf6\xcb\x4b\x92\xa2\x28\x2f\xa6\x2d\x49\xc1\x7b\xd1\x07\xd4\xef\x24\xa5\x3a\x06\x58\xbc\xa1\x71\xbf\x24\x49\x09\x95\x1d\x15\x86\x27\x29\x53\x23\x49\xb9\xe5\x19\x49\xaa\x4c\x5d\x81\xf4\xcf\xda\x99\xa4\xfa\x4b\x29\xcf\xba\x86\xee\x49\x9a\x94\x07\x1c\x5b\xbe\x20\xa8\x96\x8d\x23\x6f\x27\xf8\xb4\x13\x63\x6c\x67\x3c\x49\x9a\x55\x88\xae\x7d\x98\xd5\x7c\x51\x2a\xad\x51\xa0\xcd\xe7\xc5\x06\xe3\x66\x32\xb5\x35\x41\x6a\xff\x2d\xd4\xfa\x35\x85\x42\xb4\x27\x49\x17\xcc\xae\x7b\xf1\x13\x6f\x5d\x25\x90\x80\x6b\xef\x41\x35\xe9\x61\x25\x49\xe4\x0b\x84\xeb\x1b\x2a\x20\xe0\x19\x27\x38\x42\x6a\x51\x31\x81\xa8\x18\x77\xd4\x27\x49\xf8\x6a\xc8\x09\x0c\x1f\xa9\x62\x66\x11\xf6\xe5\x1b\xe4\x87\xbe\x63\xea\x41\x15\x89\x69\xac\x30\x6f\x8f\x4f\x92\x81\x5f\x57\x94\x8c\x21\x5c\xfc\x31\x94\x94\xf5\xc6\x58\x55\x93\x8c\x79\x55\x49\x32\xaf\xa2\x53\x93\x4c\xaf\x49\xe6\x94\xfc\x41\xa2\x18\xc0\x9c\x36\xd7\x8e\xb2\x7f\x0a\xbe\xfe\x29\xe3\xda\xa1\x57\xeb\xa4\x92\x71\x15\xd6\xa4\xd8\xd7\x74\x90\x55\x5b\x92\xaf\x06\x55\xe8\xeb\x59\x76\x47\x0a\xd5\xba\xe5\xa3\xa0\x41\xfa\x24\xb9\x75\x38\x86\x73\x1f\xab\x24\xb9\x3f\xb7\x40\x11\x7f\x6d\xa4\x4d\xb6\x27\x6d\x92\x2f\x2d\x1e\x78\xf0\x96\x36\xd9\x4f\x4d\x9b\x9c\x69\x93\x42\x85\xde\xa0\x6f\x0d\x15\x4b\x49\x9b\xd4\xcd\x3d\x6d\xd2\xa4\x09\x92\xa6\x68\xc9\x9f\x16\x54\x0a\xea\xf6\x06\xa1\xa2\xfa\x00\x83\x61\x19\xf4\xa3\x33\x6d\x32\x67\xd1\xb4\xa9\xe4\x0b\xb4\x81\xac\xf9\xa4\x4d\xb3\x60\xe3\x6e\x9a\x31\xdc\x4d\xf5\x48\x9b\x1e\x1e\x78\x3e\xc1\x52\x2f\xf9\xe2\xe5\xb2\xb6\xa7\x4d\x0b\xf7\xf7\xa6\x50\xf7\x4d\xcb\x4c\x9b\x36\xf2\x6c\x7a\x18\xde\x06\xc8\x0c\x01\xef\x09\x75\xdf\x74\xde\xaa\xe0\xf4\x38\x58\x58\x7e\x32\xc6\x62\x78\xfe\xe0\x81\xb9\xaf\xc6\x6d\x16\x78\x89\x79\xa5\xcd\xde\xe6\x05\x6b\xb7\x15\xd9\x15\xb4\x92\x36\x4e\xaa\x08\x3a\x2b\x2a\x28\x87\x81\xd8\x0a\x79\x15\x77\xd2\x31\xbc\x22\xe5\x04\xcb\x22\x01\xc3\x35\xae\xb4\x39\x16\x64\x73\x99\x69\xf3\xfd\x49\x9b\x5b\x49\x9b\xd7\x2d\x6d\xd8\xbc\x9b\xb7\x35\xd2\xe6\xfe\x01\x41\x37\x1e\x3b\x46\xe3\x81\xbd\xba\x39\xf5\x75\x83\x39\xdb\x7c\x42\xc9\xb6\x77\xcb\x6d\xfe\x9b\x36\x7f\xd2\x16\x92\x39\xc8\xe0\xc2\x84\x60\x60\x21\xa8\x1f\x14\x28\xcc\x02\xa8\xfe\xe1\xc5\x30\xc7\x30\x6a\x41\x18\x16\x21\xec\xbc\xd0\x9c\xdd\x85\x0d\x94\x7b\xce\x5e\x0c\x0f\x1f\x08\x34\xbc\xb1\xb1\xa3\xfb\x78\xf7\xf8\x16\x7e\xa3\x88\x73\x5c\x1b\x6c\xfc\xb6\x76\x4c\x70\xed\x27\xc6\xb3\x8e\x43\x8a\xa7\x6d\x59\xd9\xd3\xb6\xca\x06\xf2\x01\x29\x2c\x6e\x3b\x9b\xb4\x0f\x98\xad\xd8\xd1\xd1\x8a\xf3\x7d\x83\x20\x20\x97\x35\xac\x51\xe0\x6b\x80\xf3\xbb\x50\xeb\x21\xfd\xfb\x4b\x59\xb6\x0d\x9b\x24\xcb\x66\x0d\xb4\xe0\x39\xcf\x35\x52\x7e\xf3\x3f\x20\xa5\x80\xd4\x94\xa5\x6a\x08\x92\x9e\xb2\xa0\x41\x13\x14\xb5\xac\x4c\xf6\x07\xb4\x39\x4b\x1c\x2d\xdb\x57\xc0\xaa\x3d\xcc\xeb\xff\x3a\xe8\x36\xd9\xae\x4f\x61\xb7\x81\xdf\xc6\x2a\xb1\x83\x9c\x0e\xda\x75\x22\x09\x70\x0d\x3c\x0e\x34\x1e\x17\x88\x35\x54\x19\x93\xfc\xc6\x22\x3b\x54\x99\x52\xfc\x44\x9a\x51\x6d\xea\xe9\x6c\x3e\xdf\x8a\x0b\x4b\xf5\x6e\xa4\x2c\x8b\xc6\x24\x63\x91\xb3\x5a\xc1\xfa\x65\x2d\x8a\xfa\x5a\x61\xbd\xb3\xb6\x01\x49\x68\x9b\x8b\xb9\xa1\xe8\x47\xe3\x1d\xf6\x05\x3f\x94\x2f\x29\x1f\xd0\xda\xc9\xed\xa2\xcd\xcc\x97\xf8\x00\xed\x10\x78\xbe\x24\xde\xcc\x41\x3a\x53\xbe\x54\x3a\x68\x46\x5b\x55\xe6\xeb\x01\xc2\xe9\x5e\xd8\x9d\xf9\xb2\x0c\xf5\x81\xab\x46\x11\xf4\x20\x5f\x56\x9b\xa2\x86\xc3\x8d\xe6\xcb\x9d\x6d\xc3\x9b\xe5\x94\xaf\x95\xe1\x57\xf2\xb5\x1a\x18\xaf\x68\x29\xdb\x09\xf9\x5a\x6b\xf0\x5b\x29\x5b\x60\x53\x67\x9b\xf6\x07\xde\x00\x18\xd9\xbe\x56\x52\x2e\xf0\xad\xb9\x60\x60\x45\xc2\x8e\x07\xe9\x0d\x82\x27\xd8\xa2\x5c\x34\x3e\xa0\x5f\xcc\xaa\x60\x2f\xe4\x42\x47\x97\x8b\x1d\x07\x68\xdd\x40\x39\x98\x62\xe0\xe4\xac\x84\x35\x29\x1c\x6a\xf1\x79\x81\xae\x1d\xf4\x06\xd3\x85\x36\x0b\x3a\x55\xd6\xa0\xc0\xca\xe2\xfa\xb9\xbc\x14\xc2\xf0\xec\x6d\x21\xdd\x35\x65\x3f\x0e\x45\x82\x61\x3b\xd6\xc2\x4b\x81\xc3\xc9\x0e\x53\x9d\xbd\xc0\x03\x64\xaf\x9b\x35\x54\xab\x24\x07\xf0\x42\xf6\x8a\xb1\x79\xa5\x30\xbc\x76\x38\xd3\xec\x0d\xab\x8a\x74\x5f\x64\xd3\x0e\x8b\x8a\xf4\x24\xa0\xc9\xde\xda\xcb\xbf\x0d\x83\x79\xc9\xde\x66\x38\x7a\x6f\x5f\x83\x39\xc9\xb0\x40\xd9\x99\xd5\x3b\x6b\x74\x30\x0e\x68\x0c\xac\x74\x76\x2c\x86\x47\xbc\x7c\x38\xa5\x39\x39\x88\xc5\x59\xae\x36\xb1\xf4\xbe\xe0\xc3\xb3\xaf\x18\x4c\x06\xa7\x47\x81\xfb\xe3\x53\x53\x86\xc1\x02\xc5\xfe\xcf\x21\xc7\x04\xad\x20\x8d\x19\xd8\x20\x21\x94\x63\xc8\x5d\x40\xff\x9e\x94\x43\x59\x49\xe1\x3b\x73\xa8\x82\x87\xde\x29\xc3\xa4\x61\xa3\x85\x41\x4c\x61\xa3\x83\x02\x2e\xe4\x70\x3c\xc3\x76\xe6\x78\x47\x19\x7e\xef\x29\xc7\xca\x86\x79\xc5\x52\x52\xc3\x50\x63\x55\xee\xee\x58\x8d\x35\x17\xc7\x81\x8e\x9f\xc1\xed\xbe\x36\x4d\x79\x95\xb9\x20\x8d\xd5\xf1\x7b\x8d\x7b\x5e\x61\x8e\x8d\xb6\x22\xa8\x4c\xeb\xdf\x0e\x5b\x81\xbd\xb9\xc6\xc5\xad\xb5\x06\xcc\x77\x5e\x90\x01\x3d\xd3\x2e\x7b\xda\xa5\xc2\x50\xed\x30\x49\x3b\x1d\xf2\xfe\x82\xae\x5d\x68\x91\x77\x88\x63\xe7\xc6\x67\xe6\xdd\xd2\x2e\x4f\xda\xb1\x93\x77\xdd\x64\x2a\x92\xb0\x91\x76\xcd\x70\x5d\xbb\x66\xad\x1b\xea\x2a\xa0\x33\x92\x02\x2d\xda\x15\x8b\xc9\xea\x10\xe5\xc0\x03\x6b\x1d\xda\xf8\x72\xbc\xb5\x0e\x30\x27\x60\xdd\xb5\xb0\xa7\x62\x5f\x56\xac\x70\x2d\xbb\x56\x63\xf5\x66\x1c\x41\x23\x76\xda\xb5\xa1\x26\x31\xdd\xae\x5d\x59\xb1\xfb\x30\xbe\xce\x0b\x14\x28\x60\x57\x82\xb0\x5d\x47\x0e\xdb\xf8\xa0\x6c\x32\xec\x6c\x48\x3e\x20\x1d\x86\x69\xd7\x31\xc3\xd1\x64\x8a\xa1\xa7\x09\xc5\xdb\xf5\xab\xc5\x3b\x52\xd8\x8f\x5d\xbf\x50\xa9\xdd\xe4\x84\x0a\xed\x1c\x93\xc1\x50\xec\x48\xe3\x49\x3b\xab\x99\x0e\x45\x89\xce\xb4\xdb\x71\x60\x3a\x76\xd2\x88\xef\x76\x36\xd8\x90\xdd\x8a\xd6\x2a\x69\x37\x62\x9e\xdd\x9a\x0f\x59\x78\xa0\xc2\xef\x86\x61\xda\x78\xa1\xfc\x6e\xe3\x55\xe9\xdd\xc6\x2b\x4a\xc3\x2a\xd9\xa8\x36\x06\xd2\xd7\x87\xef\x36\x3a\x45\x68\x63\xbe\x4b\x0b\x49\x82\xcf\x97\x2b\x63\x5f\x0f\xe6\xfe\xfd\x3d\x69\x77\x86\x28\xbb\xe7\x45\xe3\xbd\xfb\x99\x76\x2f\x05\xa4\x5f\xd6\xd2\xee\x55\x98\x34\xae\xa2\xb7\x8f\xa2\x55\x63\x23\x12\x0c\xc4\x17\x94\x78\x07\x7e\xde\xb9\xb7\xf6\x90\xd3\x1b\x12\xcc\x2e\x84\x81\xd2\x1e\x72\xa7\x9d\x3b\xea\x8d\x78\xf6\x30\xd6\x35\x74\x18\xd6\x3e\xa0\x1d\x84\x8c\x20\xf1\x58\xa8\xfc\xa4\x7d\xe5\x4f\xda\x57\xdd\xd2\xbe\xa0\x31\xeb\xd5\x53\x60\xd9\x9d\x66\x6f\xe7\x4a\xdf\x12\x47\xda\x9f\x26\xb0\x57\x2a\x50\x69\x15\xc4\x11\x2a\x51\x1e\xd0\x06\x32\xaf\xa4\x32\x8c\x39\x63\x82\x3c\x49\xf3\xe5\x49\xf3\x0b\xd4\x34\x7b\xf3\xfa\x24\x05\x64\xe1\xe6\xd7\x7d\xc1\x33\x26\x3d\x68\x11\xf5\x3c\x93\x12\xc3\xa8\x11\x99\x68\xd9\xfc\x4e\x5a\x76\x3e\x6b\x9e\x81\x11\x14\x3d\xa5\x4d\xa4\x14\xaf\x16\xed\xd7\xbf\x8c\xaf\x40\xf2\x5a\x0c\x4c\xcb\xd0\xa4\x75\x93\xf8\x20\x01\x62\xd3\x0a\x8c\x85\x5c\x85\x1b\xd4\xea\x74\xbc\x5a\x7b\x71\x94\x76\x47\xb0\xa3\xb5\xcf\x27\x69\x23\x44\xd0\x06\xbc\x8f\x6d\xa0\x80\x39\x63\x20\x75\x58\x44\x6d\x8a\xc9\x34\x0d\xcc\xad\x1d\xd4\x00\x6d\x27\x8c\x80\xb6\x13\x7b\x50\xdb\x45\x6d\xd1\xf6\x03\xfe\xad\x60\x87\x69\xf3\x75\x5e\x49\x5b\x58\x66\x02\xd5\x80\x7f\x0f\x54\x84\x6d\xc0\x56\x7c\x5f\x02\xad\xb8\x4f\x34\x69\xb7\x01\x97\xa3\xff\x01\x63\xe8\x7f\xcb\x7a\x02\x06\xd2\x80\xde\x6a\xb0\x2c\x7c\x70\x46\x11\x90\x43\xac\x3e\x93\x8e\x2c\x68\x3e\x86\x3c\xa0\xca\x11\x8d\x49\xc1\x4f\x0d\x00\x27\x9d\x97\xe5\x91\x14\xda\xcc\x62\xb8\x61\xfd\xfa\x07\x8f\x5e\xbe\x9a\xf4\x97\x72\xf8\x95\x0a\xa7\xa0\xbf\x8c\xe9\xf5\xf7\x1f\xca\xd0\xdf\x4c\x91\xff\xe6\x82\x30\x49\x7f\x19\xda\xeb\xaf\xd2\x46\xea\xaf\x46\x36\x66\x5c\x02\xed\xd2\xdf\xcb\x36\xac\xff\xaf\x91\x19\xc5\xf2\xcb\x0c\x87\x52\xeb\x6f\x87\x85\xd2\x5f\xc6\x6e\xfa\xdb\x29\x8e\xdf\x5e\xb0\x6d\xf4\xb7\x3b\x79\xf5\x78\xc7\xc0\x10\x4d\x7f\x27\x64\xf1\x28\x7e\x40\xb4\xe9\x10\x60\xe4\x74\x60\xc1\x0f\x81\xb9\x7f\xd2\x01\xbb\x7a\x88\xb5\x09\x3a\xaf\x74\x00\x51\x1e\x02\x55\x39\x10\x28\x1c\x52\xa1\xc1\x07\x62\xea\x91\x0e\x69\xf8\x65\x64\xb4\x09\x85\x3e\x10\xa7\x1e\xf2\xfa\x81\x43\xc0\x06\xb6\xe7\x10\xea\xeb\x21\xd3\x10\xcc\x1e\x8c\x35\x0f\xf9\x7a\x40\x2c\x87\x0a\x5d\xcd\xa1\x5b\x2c\x98\xb2\x43\x77\x85\x3b\x06\x74\x38\x54\x77\x10\xbc\x55\x29\xc8\xc0\x0a\x1c\x3a\xa6\x7d\x59\x07\x3b\xf1\x20\xd0\x39\xf4\x4e\x87\xc1\x25\x1c\xf6\x06\xa0\x87\x69\xd9\xd3\x61\x27\xf9\x43\x9a\x87\x95\x0a\x32\x59\x0b\x8b\x7b\x20\xc2\xa1\x4f\x38\x8c\x0e\xe9\xb0\x06\x2b\x77\x18\xdb\x60\x42\x06\x98\x7e\xd8\xc8\xac\xce\x32\xbc\x4f\x22\xf6\xc3\x7e\xd3\x51\xe4\x04\x81\x88\x0a\x1c\xd9\x51\x30\xf9\x82\x29\xa6\xa3\x60\x1e\x85\x3b\xf7\x00\xd6\x3a\x8a\xb3\x14\x88\xeb\x28\xce\x2a\xdc\x5a\x47\x59\xb6\x83\x92\xc3\x93\x0e\x97\x9a\x0e\xcf\x90\xb5\x9f\xe9\x00\x8c\x3a\x1c\x33\x72\x9e\x8e\x1c\x08\xcb\x0e\xf7\x99\xde\xed\x85\x28\x73\xf0\x05\x81\xc9\x81\x20\x1f\x96\x03\xd6\xeb\x70\x98\xb5\xc3\x83\x61\xf3\xe1\x63\x90\x17\x51\xdc\xc1\x63\x84\xc3\x7f\xd3\x11\x72\x52\x4a\xc1\xa9\x84\xfe\xb7\x60\x43\x8e\x50\x8c\x28\x0c\xaa\x74\xc0\x0c\xa2\x10\x23\x0a\x67\x31\x50\xd2\xc1\x38\xe9\x08\x07\x5c\x3d\x62\x41\x44\x80\x1d\xc7\x6a\xf8\xb5\x27\x1d\x2b\x1a\xd5\x0d\x20\xfd\x58\x5c\xf4\x53\x18\x44\x31\xd8\x3e\xa5\xc8\xef\x83\x84\xe0\xfe\xc4\x18\x4e\xe9\xe9\x14\x1e\x10\x9c\x12\xdb\xbf\x14\x31\xd4\x29\x51\x2c\x23\xa1\x9d\x3b\x65\xe0\x87\xda\x13\x75\xa8\x71\xa7\x2c\x36\xf8\xd3\x74\xc2\x14\x49\x41\x6a\x6b\x20\x09\x66\x22\xde\x38\xb5\x2d\x28\xc0\xa9\xe3\x1d\xd4\x85\x09\x9d\x06\xb3\x79\xc2\x5f\x9c\x76\xc2\xa2\x9f\xaf\x82\x9c\x16\x72\x1c\x78\x8d\x92\x4e\x38\x8e\xb3\xc8\x0e\x02\xd5\x3c\x8b\x04\xe9\x18\xe9\x2c\xf0\x7f\x67\xb1\xda\x07\x52\xdf\x48\xbd\x82\x62\x8a\xc5\xd9\xda\xef\x74\x22\x9c\x3e\xa1\x18\xa7\xef\x3b\x14\xeb\xc4\x4a\x9f\x58\xe2\x93\xc1\xc3\xe9\xf0\x5a\x92\x4e\x1f\x5d\x0b\x92\x61\x3d\x9d\xf0\xcf\x2d\x9d\x10\xfe\x19\xb2\x81\x60\x14\x8c\x92\xcf\xe0\x14\x02\x16\xee\x64\xac\x7c\x86\x7c\x01\x03\xce\x50\x74\x15\x0a\x49\x86\xed\x20\x7a\x80\x22\xd7\x33\x17\x20\x7c\x75\xd0\x3b\x9d\xb1\xc0\x68\x41\x79\xce\xc5\xd1\x2d\x4e\x6d\x59\x41\xbe\x4d\x89\x74\xae\x96\xce\xa7\xa6\x4b\x60\xbd\x18\x75\x5d\x52\x8e\x74\x49\xad\x8a\xe7\x4a\x75\xbb\x60\xbc\x2e\xe9\xfd\x49\x17\xa2\x49\xe4\x04\x72\x62\x5c\xa0\x5f\xe8\x30\x82\x2f\x9e\x93\x5c\x72\x7f\xd2\x25\x7f\xac\x82\x08\xff\x52\x29\xf3\x42\x12\x13\xf4\xfb\xa4\x0b\x3e\xf3\xf2\x33\x5d\xaf\x7f\xbc\xb4\x14\x07\xad\xca\x97\x9e\x2e\x6d\xe9\xd2\xf0\x74\xd9\x0e\xe5\xb9\xec\xbc\xd2\x05\x10\x70\xc1\xda\x5d\xd6\xd3\x85\xfd\x7e\xd9\x98\x58\x98\xcb\xb7\x0d\x34\x03\x7b\x5c\x58\x88\xcb\x8b\x82\x18\x50\xe9\xf5\xee\xbf\x0b\x01\xcb\xe5\x8d\x75\x1c\x75\x3a\xde\xa3\x81\xc0\xc5\x5c\x74\x85\x97\x8f\x37\x90\xa6\x5a\x5d\x3e\x15\x8f\x0b\xc5\x30\x5b\xd7\xda\xd2\x05\x3d\xbd\x56\x95\x06\x0a\xcf\x7a\xad\x0a\x06\xab\xed\xa1\x3b\xd2\x13\xc3\xc2\x2a\x5c\x2b\x76\x56\x08\xe6\x40\x0a\x6b\x6c\x14\xea\xb3\x61\x29\x81\x04\x2d\x7b\x4b\xb6\xab\x24\x1e\x2b\x23\x48\x34\xb4\xb2\xb3\x21\xc8\xc1\xcc\xad\x00\x2a\x30\xa5\x21\x33\x02\x74\xab\x46\xdf\x67\xb5\x12\x2f\x5b\xad\xb0\x1f\x56\x3b\x3c\x9c\x55\x7a\x17\xab\xef\xc9\xa5\xd5\xbe\xe0\x1c\x0c\x91\x84\xb5\xd7\xbd\x59\x63\x20\x67\xed\x1f\xfc\xb6\xb6\xeb\x2f\xa8\x11\xcd\x58\x23\x8a\xb3\x06\x24\x15\x4f\xb2\x06\xef\x81\xa4\x58\x66\xea\x51\x93\xb5\x0b\xd6\xde\xda\xa5\x50\x49\x6b\x36\x81\x79\xad\xfd\x28\x2b\xfd\x2c\x36\xad\x2f\x47\x20\x59\x6b\xcd\xb3\x92\x53\x5f\xa0\xff\x2d\x63\x9d\x81\x70\xcb\xda\x78\x1b\x22\x2c\x44\x42\xa7\x69\x0d\x11\x0f\xd8\x4e\xce\x0e\xf8\x02\xda\x67\x6d\x7a\xb2\xf6\x7d\x9f\xbf\xc6\x4e\x5e\x4f\x6f\x01\xc1\x8e\x02\x79\xdb\xf0\xc2\x01\x8c\xb1\x34\xd9\xd4\x9a\x00\x75\x9f\xf4\xf3\x1e\x55\xfd\x08\x76\x4c\xfa\xe1\xef\xef\x2f\xfd\xa8\x14\x38\xce\x1f\x95\x06\x5a\xca\x93\x7e\xf4\xd6\x92\x7e\x7c\x4b\x3f\x08\x90\x7f\x00\x2a\x7e\x7c\x05\x94\x0a\xb0\xe8\x67\x01\x0f\xfe\x2c\x2c\xea\x0f\x62\xef\x9f\xc5\x53\xea\x9f\xd5\xcc\x03\xc9\x27\xf1\x10\xff\x23\xed\x94\x70\x4f\x1f\xec\xe9\x8f\x6a\x4f\x1f\x38\xc7\x85\xf4\x49\x1f\xcb\x9f\xf4\xb1\x1d\xbf\xc6\xf7\x86\xe7\x76\xee\x5e\xd3\x07\x70\xfe\x63\x13\xbf\x8c\xbd\xf2\xc1\x94\x3f\x36\x27\x9f\x6f\x4b\x9f\xa6\x9a\x3e\xcd\x0e\x50\x38\xae\x4f\xf3\x3b\x15\xd9\xf0\xd3\x02\xea\x91\x8a\xec\x00\xa3\x45\xf6\x27\x15\xf9\x68\x2a\x08\xf7\x8a\xb4\x73\x41\xb7\x8a\xf4\xe9\x78\x0f\xbe\x4c\x56\x9d\xd6\x52\x41\xdc\x07\xda\x00\xbc\x8b\x7c\x25\x15\x01\xfb\x1b\x65\xf7\x80\x33\x29\xf2\xb0\xfe\xdf\x93\x8a\x0a\xbb\x51\x39\x40\xa2\x81\x7e\x35\x01\x03\xc3\x7e\x17\x3d\x66\x2a\x7a\xa6\x57\xc1\x8b\x9e\x70\x5c\x45\x6d\xbc\xa5\xd5\xd1\x82\x59\xed\x9c\x17\x92\x91\x8a\x7a\x87\x91\x01\x8a\x65\x39\xcf\xe0\x0a\xe2\xb0\x54\x4c\x22\x15\x40\x8b\xf9\x20\x0d\xc0\x94\x62\x99\x3b\xa4\x40\x28\x05\x6e\xe2\xf5\xf1\xc5\x30\x71\xab\x1b\x08\x06\x8e\x28\xa3\x00\x8e\x14\xfb\x0f\x0e\x9e\x38\xb7\x18\x8f\xba\x10\x73\xa6\x62\x34\x6f\xc5\x85\xa4\xa5\xe2\x1b\x4d\x65\x71\x40\x0e\x02\x85\xe2\xa7\xe5\x54\xbc\x69\x79\x90\x9c\xa9\x38\x64\xe9\x18\x26\x72\x16\xda\x2e\xb8\x66\x3a\x95\xe2\x0f\x9a\xae\xfc\x79\x52\x59\x27\x71\x77\x59\x0c\x98\xcb\x6a\x42\x9a\xaf\x54\xd6\x2f\x76\x52\x79\x02\x08\xb7\x4a\xbe\xe0\x08\xab\xec\xa9\x0a\x3a\xac\x72\x36\x9d\xa9\x8a\x21\xc7\x4a\x62\x6c\x56\xe5\xc7\x23\x55\xac\x70\x95\x5a\x05\xd9\xc8\x6d\xe8\x05\xe1\x33\x76\x45\x95\x76\x3a\x28\x31\x77\x15\x7e\x39\xa9\x02\x80\x5c\x25\xb6\x37\xc9\x17\xe8\x49\x9e\xf1\x76\x1d\x1f\x76\x18\x61\x2f\xb7\xf1\x01\xc1\xe0\x28\x93\xca\x23\x43\x6c\xfc\x30\x32\x9c\x7c\x0b\xfb\x45\xf2\xd6\xf8\xb5\xba\x6a\xaa\xf0\xfb\x55\x65\xf7\x1b\x49\x03\xa1\x06\x54\xf8\xbe\xaa\x40\xe7\x98\xa2\xee\xe0\xa3\xbb\x49\xaa\x5a\x10\x09\x55\x2d\xa8\x40\x69\x55\xad\xd8\xd2\x00\x19\x9c\x87\xb6\x95\xaa\x46\x46\x16\xf4\xb8\xd2\x40\x55\x9e\x07\x56\xe0\xa4\x8a\x58\x82\x05\x93\x7c\xe7\xe5\x7b\xaa\xb6\xc3\xfc\x56\xdb\x1b\x95\xa4\x5a\xf9\x80\x50\x2f\xaa\x21\x76\xac\xd8\x91\xd5\xda\x3b\x76\x43\xbc\x5b\xad\x21\x42\xa8\x16\x92\xd9\x9a\x5e\xa5\xda\xc0\x92\x33\x06\xaf\x08\xb9\xb1\x0c\x98\xbe\xfd\x2a\x38\xfc\x72\x13\x54\xdf\x00\xe5\xaa\xef\x5a\x40\xe1\x02\xaa\x57\xfc\x60\x25\xab\x37\x43\x34\x58\xdf\xf8\xba\x7a\x7b\xa5\xeb\x0d\xf2\x74\x8c\x8a\x67\x62\xd5\xc9\x2b\x1a\x82\xdf\xea\xe3\xbf\x65\xd3\x53\x7d\xcf\xc6\xff\x45\x88\xd5\x5f\x4e\xab\xf1\x38\xa8\xf2\xfb\x40\x85\x16\x56\xff\x9a\xa6\xba\xb0\x62\xeb\x38\x50\xb8\x30\xa8\x55\xa6\xf5\xf2\xa4\xba\x06\x27\xb6\x86\x62\xd2\x6b\x5c\x3c\x7b\xaf\x6b\x40\x20\x30\x6b\x75\xf1\x13\x66\x7d\x86\x96\x03\x09\xd5\xbd\x3e\xf3\x4a\x4d\xb0\x79\x1a\x60\x62\x93\xfe\xb1\x96\xda\xfb\xd5\xab\xc9\x98\x4f\x6a\xc2\xc1\xb5\x37\xba\x68\x2a\x91\x9a\xe6\x4f\x6a\x08\x29\x9a\x9e\x32\xd9\x5c\x4f\x9e\x48\xb6\x7f\x41\x75\xd3\x7e\xe9\x9d\x9a\x06\x0b\x07\x4a\xf8\xe3\x37\xb3\xa6\x6b\x42\x2a\x8d\x01\x47\xd3\x7b\xa4\xa6\xbf\x33\x35\x98\xe7\x77\x65\x9b\x43\xb5\x9b\x23\xa2\x6b\x5e\x0d\x86\xb3\xb9\xef\xcc\x0c\xec\x95\xe6\x81\xd1\x3b\x2b\x4c\x79\xab\x4f\x92\x0b\x52\x6e\x88\xf2\xf0\x0a\xd3\x03\x33\xdb\x56\x2e\x1c\xfe\xbb\x7f\x1b\x8f\x1c\xdb\x9a\xc9\xe5\x93\x7c\xd3\x27\xf9\x46\xbf\xe8\x5b\xb1\x53\x93\x6f\x23\x63\xce\xbe\x0d\x4e\xc3\x37\xae\x8b\x6f\x5f\x1e\xdf\x79\xce\x2b\x92\x67\x6c\x09\xcf\xd3\xc1\xd3\x77\x8f\xe4\xc7\x81\x9f\xf2\x09\x43\xf0\x03\x0e\x00\x61\x87\x7f\xe4\x49\xc0\x41\x4e\x8b\xe5\xe5\xa9\xdd\x72\x72\x18\x38\x07\xec\xf5\x86\x1f\x04\xee\x8d\xe7\x70\xde\xca\x93\xbc\xa3\x7d\x47\x20\xee\xdd\xde\xe2\x4e\x08\xe1\x9d\xab\xe3\xef\xb7\x4b\x0f\x40\x46\x8f\x4c\x28\xf8\x9e\x2a\x79\xec\xd6\x60\x68\x3d\x4e\x8c\x34\x78\x80\xed\x61\x27\xe3\x36\x8f\x7e\x21\x7b\x4c\x9e\x14\xbc\x0a\xe9\x6b\x12\x5d\xf8\x9a\xef\x1b\xa0\x80\xaf\x49\xaf\xef\x08\x18\xfd\x8b\x11\x61\xf5\x80\x98\xfd\x06\x74\xf0\xdf\xe7\x44\x2e\x95\x2b\xf9\x1f\xe6\x42\xb8\xd3\x85\xbb\xb6\x63\x3b\xf3\xb0\xae\x4b\x01\xba\xee\x52\x6a\x42\x10\x2e\xa0\x5a\x40\x2d\x83\x72\x14\x5d\x3a\x69\x20\x9e\xee\xc2\xb3\xd2\x2e\xf1\x01\x09\xe7\xf3\x7c\x52\x87\x51\xeb\xb4\x66\x1d\x46\xac\xcb\xb4\xb7\x26\x4f\xac\x3b\x8d\x59\x4b\x9d\x5f\x41\x3a\xfc\x5b\x97\x87\x7b\xb7\x2b\x07\xa1\x02\x1d\xe0\x07\xe5\xae\x32\x84\x25\xc5\xb2\xb4\x04\xb1\x77\x6d\x82\xa8\xbe\x6b\xcb\x56\x52\x57\x87\xe9\xed\xca\x53\xef\xae\x71\x40\x63\xba\x06\x96\xb0\x6b\xc0\xe9\x75\x9d\xa9\x5f\x9c\xfe\xe5\xd3\x53\xbf\x78\x7a\xd2\xaf\x67\x18\x3c\x51\x37\x69\x9e\xba\x65\xce\xd6\x5e\x6f\xdb\x4d\x31\x1a\x3b\xf1\x53\x70\x01\xba\xec\x56\x30\x53\xf8\xbe\x6e\xde\x14\x7d\x5a\x47\xbd\x31\x31\x3b\xe3\xbc\xed\xef\x4f\x52\x7f\x65\x5a\x04\x3b\xad\x97\xf7\xe4\xae\x13\x59\xf1\x58\xb1\x17\xe2\xc8\x5e\x78\x34\xd6\xe1\xd3\x40\x4f\x10\x28\x4f\x77\xad\x20\x33\x75\x07\x9a\xef\x5e\x20\x12\x00\xf6\xee\xf0\xd2\xa9\x7b\xdb\x41\x9e\xd4\x1d\x9d\x7b\x5f\x6f\x95\xa0\x12\xf2\x00\xf7\xdf\xc3\xb0\x8d\xed\x06\xf8\x4c\x81\x10\xfe\xb9\xd8\x0e\xad\x81\x3c\xfd\x86\x7a\xbe\xa7\x61\x3d\x24\x73\xb7\xf6\x10\xec\xf8\x1e\xca\x1b\x16\x3d\xf4\x60\xb1\x62\xfd\x91\xf2\x2a\x48\x0f\x9d\x60\x11\xfa\x7d\x5f\xdf\xa6\xd0\xce\x1e\x56\xa1\xed\x3d\xec\x2d\xf1\x30\x56\x35\xae\x4c\xd8\x97\x02\x09\xfb\x03\x85\x91\xa9\x48\x79\xd2\xd4\xc3\xf7\x45\x4e\x7e\x60\x35\xc3\x79\x4c\xdc\xc3\x69\x16\x7a\x78\x75\x36\x76\x3f\x40\xfb\x3b\x91\x40\x24\x89\x41\xfa\xfc\x57\x6d\xed\xa0\x3c\xb5\xed\x6b\x43\x7c\xdd\xd7\xbe\xc3\x28\xf5\x85\x45\x5d\xa5\xa7\x17\xf2\xf7\x55\x69\x72\x3b\x61\x44\x5f\x1d\x2a\xb6\x10\xd4\xf5\x15\xef\x17\xb4\xbe\xde\x19\xac\xe0\x8e\xef\x34\x5b\x7d\x0d\x54\x9f\xa9\xaf\xbf\x3f\x48\xfa\x09\xa9\xb6\xa7\xff\x96\xf0\x12\xcd\x7f\x4b\xda\x5c\x15\x69\x60\x37\xfe\xb7\x74\x70\x6d\xfe\x5b\x40\xb0\x70\x3f\x20\x7f\xe9\xbf\x85\x29\x85\x6c\xb0\x1c\x21\x39\xc3\x67\x31\xf6\xe5\x77\x97\x90\x5d\x02\xd4\x3c\x05\x80\x0b\x03\xe2\x77\x91\x42\x80\xbc\x03\xd8\x34\x04\xc3\x0f\x69\x80\xc1\xaf\x2d\x0a\xe9\xb6\xa7\xc0\xb2\xf1\x3b\x42\xbc\x67\x09\x21\xb0\x1c\x21\x77\x0a\xf9\xf3\x48\xef\x2d\x14\x7e\x69\x44\x9c\x83\xce\x15\x48\x38\xf4\xfd\x12\x1c\xca\xef\xb1\xa1\x59\x61\x31\x43\x33\xd4\x3f\x34\x7b\xb0\x90\x5f\x46\x42\xb9\x6e\xa1\x07\x9d\x50\x28\x83\x9f\xd0\x03\x7b\x3e\xf4\x34\xb2\x3d\x43\x51\x76\x52\x69\x43\x7f\xde\xaa\x45\x7e\x41\xb9\x37\x42\x0b\xc2\x77\xde\x5d\x08\x25\x46\x0b\xfd\x07\x60\x42\x89\x2c\x42\xe9\x91\x43\xdb\xce\xcc\xa6\x77\xa2\x65\x0a\xa5\x95\x86\xa6\x1a\x0a\x3a\xd0\x51\xe8\xbb\x2b\x43\x79\x7b\x27\xf4\xbd\x70\x14\x3a\xf2\x62\xa2\x8c\x52\x43\x79\x55\x24\x74\xf8\x0a\x56\x1f\xdd\x1b\x07\x34\x56\x41\xc1\x7c\x9b\xcd\x78\xb9\xce\x15\xe8\x6a\xb5\x77\x66\xdf\x57\x7c\x5f\xe3\x60\x78\x36\x15\xd7\x33\xaf\x9a\xc2\x36\xfc\x36\x54\xc3\x26\xa1\x91\xe7\x46\x79\x3f\xea\x87\x1d\xe8\x9f\x2e\x17\x2e\x61\x4f\x3c\x9e\x0f\x73\xbc\xf3\x7e\x0d\xbf\xf1\x87\x11\x3f\x04\x4f\x0b\x83\x5f\x78\x02\x38\x3b\xf8\xb5\x32\x7c\x73\xd2\xc5\x17\x46\x6d\xe1\x95\x07\x39\xdc\x2c\xe1\xfe\x31\x3e\xd7\x14\xd0\xe2\x70\x86\xc7\xc1\x53\xea\xf7\x02\x4e\xc0\xdb\xa4\x20\xe0\x8e\xb5\x51\xe6\x08\x84\x63\x9d\x29\x00\x77\x62\x35\xfc\x6e\x79\x52\x2c\xc0\x87\x21\x3b\x7e\xf0\x2d\x43\x76\x46\xdf\x43\x0e\xbc\x18\x0a\x0b\x8b\x0b\xc2\x94\x21\xe5\xa5\x13\x04\xfd\x0c\xe0\x9d\xf1\x1e\x34\x0f\x44\xa1\x43\xa6\x8d\xe3\x41\xea\xe3\xb2\x34\x04\x2a\x35\x64\x11\x85\x0e\x38\x8e\x21\x4f\x1a\x19\x01\xf5\x80\x77\x18\x19\xca\x3d\xf2\x0b\x97\x47\xd6\x86\xb7\x4b\x2b\x13\x58\xc8\x91\x8d\xe7\xac\x23\xdb\x18\x1e\x23\x8d\xec\xc1\x0f\xe7\x23\xfb\x9a\x69\xe4\x90\x0e\x8a\x58\x73\xe4\xb0\xce\xbc\xb5\xa5\xa1\x82\x1f\x80\xfd\x78\xb7\xc5\xc0\xca\x0f\xcd\xb0\xc1\x43\x33\x74\x19\xb1\x38\x99\x69\x7e\x6d\xc4\x00\x26\x1b\xaa\x9f\x34\xf4\xa4\x8f\x1b\xfc\xa2\x81\xa4\xa4\x01\x0d\x96\x48\x43\x19\xf3\x0e\x86\x5d\xb0\xa7\xef\x18\x35\x4c\x07\x12\x7e\x2a\x1b\x3a\xc6\xcb\x9b\x01\xd6\xd0\xb9\x7a\x1a\xb0\xb7\x69\x5c\x8c\x05\xc6\x25\xc7\x04\xe5\x21\xce\xb8\x28\x8c\x0b\x03\xb8\xd8\xdb\xa5\x61\xc7\x91\xc6\xc5\xd3\xe3\x71\x19\x6b\x03\xd3\x8c\xcb\x3a\x08\xb4\x68\x5c\x08\xcb\xc6\xe5\xc8\x76\x47\x15\x47\x21\xb6\xcb\xb8\x7c\xf1\xb3\xcc\xb8\xb0\xe7\xc6\x15\x56\x51\x06\x8d\x18\xd7\x3a\xa0\xba\xe3\x7a\x12\x9c\x0d\xb4\x76\xc0\xb4\x11\xa3\x0c\x53\x2c\x1a\xd5\x9a\xdf\x0a\x87\x15\x8a\x03\xf1\xc2\x30\xd8\xad\x61\x85\xfd\x5b\x35\xd8\x83\x61\xaf\x2a\xf0\xeb\xf6\x78\xb9\x05\x26\x6b\x44\x33\x03\xfa\x0f\xb5\xb1\xdf\x34\xe0\x3b\xc6\x87\xaf\x3c\x1b\x48\xe3\x63\xf8\x61\xd6\x30\xe6\xe3\x63\x18\xfd\x07\xb6\x7e\x20\xb8\x1f\x45\x6a\x1a\x45\xb5\x83\xd2\x72\x0c\x7a\xd4\xc1\x93\xcd\xf1\x46\xbc\xa3\x18\x6a\x39\x60\xda\x80\xdb\x1f\x14\x2c\xcf\xb1\x47\x85\x15\x1c\x55\xc0\xb8\x22\x22\x19\xd5\x3f\xa4\x3e\xaf\x34\x1a\x8c\xf5\x68\x88\x61\x46\x83\x4e\x35\xca\x1e\xb0\x77\x38\xde\x3d\x67\xf4\xea\xfc\x92\x3d\x28\x73\xdf\x25\x0d\xc7\xaa\xd0\xd3\x0f\x2f\xbb\xb1\x4e\xb1\x1d\xf4\xbd\x30\x32\x78\x5e\x33\xbc\x2a\x00\xcd\x40\xc8\x3c\x9c\xf9\x08\xd5\x06\xd7\xc9\x17\x78\x62\x13\x0f\x87\x9a\xbc\x56\x6c\xf8\xc2\xd0\x3a\x0c\xe0\xa0\xff\x1e\x00\x67\xe8\xbf\xcb\xdd\xd2\xe8\x2a\x1f\xd0\x77\x4c\x9d\xca\xdb\xa9\x3b\xfc\x24\x3c\xfa\xa5\x6c\x44\x49\x75\x5e\x44\x18\xdd\x3e\x7c\x41\x73\x43\xc8\x38\x7a\x21\x05\xbc\xa6\xd5\x84\x6a\x77\x8e\x90\x36\x77\x74\x48\xb2\x07\xf6\x6e\xe7\xe5\xa6\xd1\x69\xe3\x46\x7f\xd2\x80\x7f\x54\x24\xbc\xef\x84\xb0\x8c\x37\xd5\xc6\x1b\x4f\x8c\x29\xbb\xad\x8a\x14\xd2\x9c\xb4\x04\x53\x0c\x3b\x79\xc2\xef\x8d\x49\xd3\x31\xb9\x2c\xb4\x68\x63\xa2\xa3\xc9\x99\x4d\x25\x2b\x05\x03\x2c\xfd\xd4\x50\x4f\xc0\x65\x28\xa4\xba\x4c\x8e\x64\x72\x3d\xa6\x57\x81\x32\x4d\x0a\x7a\xd2\x80\xf0\x18\x75\x4c\xaa\xff\x84\x1f\x3d\xf1\x1a\x8a\xdd\x3f\x83\xb2\x98\xc1\x35\x99\xb1\x78\xba\x3e\xe6\xe2\x0d\xd8\x31\x17\xc7\xfc\x9e\x83\x8e\xf9\x80\xae\x37\xc0\x19\x6b\x03\x5c\x1d\x6b\x83\x31\x1d\xeb\xbd\x3c\x3b\x10\x5f\x8e\xc5\x93\xdd\xb1\x18\xc0\x8c\x75\x0a\xe9\x89\x10\x8e\x07\x48\x63\xf1\x18\x7a\x2c\x54\x6a\x0d\xcd\xdb\xc0\x70\x56\x67\x76\x47\x40\x3a\x56\x0f\xda\x41\x20\xdb\xb1\x82\xdf\xc7\xc6\x42\xa0\x3f\x56\x00\x8c\xf1\xe1\x35\xfc\x63\xc5\x57\xd1\xe6\xbd\x45\x39\xd6\x60\x9c\x35\xee\x7f\x96\xe5\xa6\xa4\x6f\x21\x89\x9a\xc6\x0d\xac\x3e\x6e\x0a\xe1\xa6\x59\xb9\xb1\x73\x6e\xca\xf2\x26\x24\x1e\x37\xf0\xc1\x78\xea\x06\x29\x3e\xb5\x4f\xaf\x69\x3c\x01\xed\x7c\xb8\x24\xef\x0a\x4f\xe1\x0d\xa2\x29\x67\xe2\xbd\x81\x29\xb4\x13\x53\xca\x27\x4d\x69\x20\x1d\xc5\xfc\x14\x34\x65\x20\x63\x4c\xe4\xcc\xe9\x9e\xa6\xfc\x5a\x9a\xbc\xbd\x38\x55\x6a\x9a\xd0\x5e\x04\x7b\x53\x1b\x02\x89\xa9\xad\xd9\x40\x82\xe7\x40\x85\x81\xa7\xdf\x99\xe6\x45\xf6\x97\xe0\x11\xb2\x9a\x17\xda\x5d\x8a\x15\x9f\xd4\xfc\x79\x29\x1e\x31\xad\x79\x81\xcd\xe5\xbc\xd1\x35\xaf\x50\x94\xf2\x6b\xfb\xbc\x10\xab\xcf\x6b\xd5\x0d\x94\xc6\x65\xbe\x77\x5c\x26\x8c\xcb\xb4\x93\x39\x05\xef\x44\x32\xd3\xd0\x9b\xb5\x27\x4d\xeb\x09\xc8\x62\x4f\xf3\x3d\x7c\x9d\x06\x63\x3f\xe9\xd4\xa7\x6f\x80\x83\x69\xfa\x2e\x0f\xe8\x5e\xd0\xd8\x51\x7e\x2a\xc1\xdc\x74\x2b\xe8\x87\xd7\xfe\xa0\xbe\x13\xd5\xeb\x7b\x09\x91\x6a\x3c\xbd\x9d\x8b\x09\x4d\x1c\x95\x7a\xd2\x64\x4d\xef\xf8\x59\x06\xed\xec\x15\xde\x6e\x7a\x34\xd9\xc1\x26\x26\x83\xff\xe9\x63\xa4\xe9\x53\xd0\x70\x85\x71\x64\x84\x38\x93\xa1\xc3\x44\x00\x3a\xfd\x49\x93\x80\x75\x32\x5a\x9c\x21\x08\xbd\x91\x9e\x6f\x62\x0d\xb4\x0d\x68\xf5\x84\xd7\x9d\xbc\x39\x34\x81\x47\x4b\xe2\xbd\xd0\x17\x5c\x4d\xca\x16\xf8\x2e\x4d\x1e\x8d\x4d\x5e\x3d\x99\xbc\x0a\x39\xc3\x4e\x8a\x33\xac\x82\x80\x8d\xf7\x0b\x6d\xdf\x9b\x14\x33\x16\xab\x2d\x3e\x16\x14\xac\x8a\x78\x70\x06\xb0\xd1\x0c\x98\xc4\x89\x15\x5e\x60\xba\xde\x80\xe9\xdf\x26\x9d\xab\x09\x08\x42\xe1\xb9\xe2\x83\xd5\x07\xd0\x9b\x2b\xb8\x2c\xb7\xc2\x14\xcf\x5b\xdb\x7c\xd2\xbc\x61\x16\xe7\x8d\x89\xdd\x94\xca\xed\x69\x3e\xd0\xd6\xa7\x33\xcc\x5c\x67\x79\xd2\xaa\x5b\x68\x29\x92\xd6\x7b\xd5\x60\xb5\xf7\x36\xf0\x6a\x99\x6f\xef\xc5\x94\x57\x6d\x56\xdb\x3d\xad\xc6\x2b\xea\xab\xf1\x13\xe9\x6a\xef\x27\xa6\xd5\x8c\x98\x7a\x35\x5e\xcd\x5e\xcd\x26\xc8\x57\x11\x8c\xac\xf6\x69\x58\x85\xd5\x78\xc6\xba\xda\xb4\x92\x56\x5b\xbc\xa7\xb8\xda\x57\xf1\xda\x79\x9a\xb9\xfa\xc9\x05\x5a\x9d\x9f\x83\x56\xf7\x96\x16\x43\xe9\xd5\x61\x45\x56\x6c\xd2\x12\x0d\xc5\x0b\xbc\x80\xe0\x79\xe5\x7c\x0d\x3d\x56\x41\xc2\x0b\x12\xff\x98\xcf\xf7\x3f\x03\x5f\xc9\xd8\x6e\x5f\xc9\x6b\xd5\xf4\x15\xe8\xdc\x57\xe0\xc7\xbe\xef\x3d\xf8\xaf\x40\x74\x5f\x69\xf8\xd9\xb8\xd2\x57\xba\x47\xfa\xca\x7b\x15\xeb\x0b\x85\xff\xf2\x83\xfa\x57\x2f\x83\x68\xbe\x10\x36\x5e\xdb\x8e\x8a\xbc\x14\x89\xdc\x06\xd6\x1a\x1b\x88\x1d\x0f\x12\x02\xa5\x2f\x82\xdb\xaf\x8e\xa1\x25\x7d\x75\x6a\xa0\x2f\xa3\xcc\xbf\xb6\xf1\x0b\xe2\xd7\xf2\xdb\x9b\x65\xda\x75\x04\x88\x9e\x88\xda\xbf\x56\x0a\xa6\xfb\xb5\x36\xdf\xd4\x8b\x81\x41\x10\x77\x7f\x2d\xd8\x6e\x08\x88\x81\xd5\x78\xf3\x27\xe9\x17\x33\xe5\x29\xf7\x97\x17\x25\x79\xf9\xfb\xeb\x25\x4b\x73\xa4\xab\x22\x6f\x82\x3c\x60\x7f\xff\x23\xde\xd2\x2d\x36\xd3\x0d\x7b\x07\x7b\x0b\xd2\x16\x32\x1a\x48\x1c\xd0\x15\x5a\xdd\x5b\x02\xc1\x74\xba\xb1\x6d\x6e\x19\x1d\x64\xa2\x10\xf8\xe8\x06\x3e\x86\x33\xb9\xdf\xef\x8a\xb7\x0a\x96\x96\x96\xfa\x46\x6c\x55\x90\xd0\x68\xdc\xba\xa5\x5b\xdf\x70\xf8\x56\xfd\x60\xa7\xdd\x6a\x01\x5a\xf8\xcd\xeb\x86\x91\xbc\x75\xa6\x9b\x5f\xaf\x6e\xd8\xc8\xfb\xd2\x97\x82\x13\x2c\xe5\x4d\x13\x79\x03\x4a\xde\x97\x31\x02\xbf\x61\xef\x6e\xdb\xd1\xbf\x1d\x78\x2c\x3b\x48\x49\xd8\x25\xb7\x35\xc0\xd6\x1b\x08\x94\xae\xe2\xb6\xf6\x01\x69\x6c\xca\x4b\x31\x37\xc2\xac\xdb\x06\xc2\xd8\x1b\xd6\xe7\x86\xae\xdc\xff\xee\x28\xdc\x5e\x8e\x74\x23\xae\x49\xb7\x73\xc7\xdc\xee\x3b\x48\x49\xf4\x37\x3c\xdc\xbc\x3d\x0a\x1f\xe3\x01\xc5\x60\x60\x6f\xee\xd0\xfc\x01\xe5\x25\xde\x9b\x86\xec\xe6\xcd\x8d\x9b\x0e\xfc\x81\x49\x7b\x20\xaf\x47\xe9\xf7\x1e\x5f\xf8\xa1\x88\x40\xea\x4f\xb7\x90\xf4\xa7\xe1\x89\x47\x6b\x7f\xee\xe9\xff\x00\x00\x00\xff\xff\x96\xd2\xdb\xc1\x3c\x33\x00\x00") func keysWordlistEnglishTxtBytes() ([]byte, error) { return bindataRead( @@ -106,12 +106,12 @@ func keysWordlistEnglishTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/wordlist/english.txt", size: 13116, mode: os.FileMode(420), modTime: time.Unix(1497960590, 0)} + info := bindataFileInfo{name: "keys/wordlist/english.txt", size: 13116, mode: os.FileMode(420), modTime: time.Unix(1511602021, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _keysWordlistJapaneseTxt = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x5c\x5c\xff\x72\xe2\xb8\xd2\xfd\x9f\xa7\x5e\xbc\x5c\x2f\x01\x3c\x0e\x71\x1c\xc7\x61\x58\x87\x8a\x2f\x43\x60\x80\x0c\x59\xb8\x93\x8f\x2c\x3c\x8c\x5f\xe4\x2b\xf5\xe9\x3e\xea\x99\xaa\x54\xea\x1c\x59\xd6\xcf\x56\x77\xab\x25\xd3\xf5\x93\xae\x3f\xe8\xfa\x45\xd7\xcf\xbb\x7e\xd5\x25\x45\xcf\x92\xca\xae\xdf\x92\x3c\x03\x8d\xba\xfe\xdf\x5d\x72\x03\x32\xee\xfa\x8b\x2e\xf9\x93\xef\x64\x5d\x32\x06\x9a\x76\xfd\x49\xd7\x6f\x8c\x58\x72\x11\x92\x93\x09\x79\xd9\xf5\x07\x44\x07\xa0\x4a\xfe\xaf\x40\x1e\xbb\x24\xef\xfa\x29\xc8\x53\xa8\xd1\x5e\x7d\xea\xfa\x19\xd0\xbc\xeb\x9f\x80\x9a\xae\x3f\x64\x86\x26\xfc\x25\x7d\xc7\x93\x51\xd7\xbf\x74\xfd\x21\xb9\x3e\x69\xd9\x8a\x56\xfa\xa4\xd5\xbd\xc8\x70\xfc\xa7\xeb\xe7\x7c\x78\xe9\x92\x91\x11\x57\xf4\xb2\xeb\xaf\x89\xf6\x92\x4d\x9f\x1c\x88\x4e\x1c\xb5\x13\xd3\x8e\x7e\x2c\x2e\x6c\xc5\xa5\xeb\xbf\x1a\x4a\x06\xd2\xa4\x9a\x5c\xeb\xbf\x76\x49\xd2\xf5\x77\x42\x42\x4b\x46\x5d\x1f\xe5\x84\x17\x58\x7f\x92\x76\xc9\x1f\x40\x37\x32\x8b\xb7\x5d\xff\x42\x5e\x11\xd5\x5d\xff\x91\xc4\x8f\x5a\x72\x23\x65\x44\x92\x5b\x5b\x42\x8d\x93\xae\xbf\xb2\xe1\x0a\x4f\x66\xcc\x99\x87\xa1\x30\x52\x58\xcf\x12\x99\x7f\x47\x0a\xa2\xaf\x26\x44\x81\x2c\x7d\x9e\xb5\x27\x3a\x00\x03\x88\x24\xda\x32\x08\x52\x29\x6f\x0f\x58\x3c\x50\x0e\x94\x89\xd8\x0e\x48\xd6\x2c\x24\xe3\x28\x0e\x28\xbd\x03\x59\x08\x8f\x44\x27\x96\x3d\xed\xfa\x6f\x98\x69\x21\x96\x5c\x60\x08\x74\x0d\x11\xb5\x3d\x5b\x44\x17\x11\xea\x81\x71\x7b\xaf\x82\x04\x0f\x44\xca\xff\xc3\x42\x1e\xbb\xe4\x2f\x4f\x72\x36\xeb\xa9\xeb\x5f\x0d\x25\x13\xa0\x19\x0b\x9e\x05\xe1\xef\xbf\x93\x8c\xfd\x13\xad\xe8\x2b\x2b\x9f\x77\xfd\xb4\x4b\x32\x56\x34\x97\x01\x8b\xcd\x7c\xf6\x48\x3b\xd5\x48\xc5\x37\x24\x57\x43\x41\x16\x12\x90\x85\x8c\x75\x4a\xf2\x48\xf4\x4a\xf4\x46\x74\x32\x94\x8c\xfc\x10\xb4\x10\xe6\x41\x5c\x83\xd6\xec\x17\xdf\xe3\x17\x74\x83\xa4\xf1\xd9\x16\x44\x4b\xff\xc2\xbf\x7c\x61\xd9\xf5\x1f\x0c\xd9\x7b\xaf\x7c\xba\x82\x70\x0e\x28\x7f\x40\xda\xac\x6d\x97\xfc\x41\x21\xda\xb1\xb2\x1d\xa7\x6a\xcf\xf9\x7f\x73\x69\x56\xcd\x3b\x27\xe4\xc0\xb4\x23\x87\xf9\x27\xd3\xce\x6c\xce\xd5\xd2\x82\xbc\xa6\x50\x8f\x20\x8d\x89\x42\x92\x58\x8b\x12\x91\x7e\xad\x36\x10\xac\x92\x64\x28\xfa\xb3\x20\x41\x7d\xa2\x19\x88\x6a\x96\x3d\x12\x6d\xb1\x30\x12\x85\x32\xe1\x1a\x0b\xda\x8b\xeb\x27\x89\x55\x66\xa2\x87\x8b\xae\xff\x8f\x0d\x43\x50\x08\x03\xa2\x94\x28\xb6\x27\x37\xb9\x08\x02\x9f\xb2\xa8\xa2\xeb\xdf\xd9\xca\xef\x33\xa9\x64\xb9\x85\x08\x48\x6c\x5b\x21\x3d\x0b\x24\x95\xf5\x90\x19\x92\x02\x53\x91\xce\x07\x20\xed\x46\x2a\x4b\xe5\x44\xf4\xc1\xac\x59\x97\xe4\x40\xb9\xe9\xcf\x35\xf9\x04\xe3\x9e\x8a\x5a\x68\xa4\x7d\x39\xdf\x9c\x8a\x0c\x4f\x49\x56\xee\x49\x18\xb1\x96\x44\x93\xef\xa9\xe5\x41\xb4\xde\x02\xc3\x93\x4a\x8f\xbf\x00\x55\x22\x88\xa9\x91\x30\xd8\x13\xac\xc5\x54\xa6\x6f\x40\xf4\x85\xe8\x96\xb3\x2c\xdc\xf4\x7b\x2a\xab\x49\x1b\xb3\xa0\x16\x27\x9f\x70\x00\x16\x1c\xc9\x05\x17\x6a\x2a\x0b\x6a\x0c\xa9\x4b\xa5\xc7\x39\x55\x48\xaa\x2b\xd2\x8d\x7c\x4b\xf4\xca\x6e\xad\xd9\xca\x35\x74\x05\xd0\x13\x47\x60\xcd\x97\xb6\x44\x3b\xd6\x7f\xea\xfa\x77\x44\xf7\x30\xed\xa9\xcc\xc5\xc4\x72\xc7\xbe\xca\xd2\x01\x12\x1b\x69\x64\x68\x95\x85\x31\x9a\x88\xd4\xd4\xe4\xba\x04\x40\xd6\xd6\x37\x51\x78\x56\x77\x20\x99\x49\x43\x32\xa6\x57\x93\xca\x4a\xa9\x1c\x49\x52\x1b\x46\xd7\xbe\x0c\x9a\x26\x95\xb1\xcf\x88\x4a\xa0\x82\xf6\x05\x64\x61\x43\x07\x3b\xe9\x88\xea\xae\xa1\xc8\xe9\x10\x4f\x40\x26\x44\x19\x97\x0a\xf8\x3d\x91\x6a\x55\x90\x93\x7b\xdb\x96\x13\x48\x0e\x34\xc2\xa4\x0f\x65\xbc\x22\xd2\xa7\x99\x4c\xbc\x16\x17\xdd\x82\xa1\x88\xeb\x9f\xcc\x56\x77\xfd\x25\x50\x2b\xae\x85\x56\xb9\xeb\xfa\xb7\x40\x67\x9d\x4c\x19\x15\xe1\x96\x87\x69\x61\x4e\x1f\x89\x76\x40\x37\x56\x79\x40\x27\x20\xb5\x50\x50\x4b\x1c\x9d\x40\xc6\xcc\x5d\x40\x18\x87\xaa\x75\xac\x8a\xc2\xfc\xc0\x94\xfc\x2b\x56\x0d\xc8\xdc\x7a\xa4\xf3\xf3\x97\xcf\xb9\x42\xce\x91\x8c\xeb\x98\x4b\x7e\x64\x5e\x42\x4d\xa2\x82\x32\x32\x0b\x98\x83\xa4\x6c\xee\xc8\x14\xc1\x85\xe4\x91\x68\xc6\x7a\x52\x8e\x3e\xc8\xd1\x17\xf5\xe1\x9e\xd8\xcc\x8e\xb8\x48\x47\x74\x94\x46\x34\xe3\x40\xaf\x9c\x73\xe1\x09\xf3\x84\x42\xe6\x20\x63\x0c\x34\xc9\x13\xd0\x04\x2e\xa8\xa4\x05\x15\xa9\x19\xbe\x50\x8d\x8d\xe8\x7a\x8d\x44\x5c\x62\x0f\x73\xef\x0d\x09\x57\xaf\x73\x4d\xce\xd7\x6c\x45\x8d\xfc\xb0\x16\xbe\x92\x82\x19\x4a\xdf\xe3\x92\xeb\x5a\x88\xe9\x8b\x11\x66\x04\xeb\x1a\x24\xbe\xf3\x08\x49\x01\x2a\x39\x3d\x22\xde\xf6\xc2\x5c\xc4\x2f\x27\x89\x8d\x6d\x68\x7b\x40\x34\xcf\x33\x9c\x7d\x90\x85\x97\x81\x17\x18\xe5\x91\xac\x14\x1d\xbf\x6f\x10\x27\x90\x95\xd4\xad\x2b\x00\x7c\xed\x25\xea\x95\xaf\xbd\x8a\xc2\x19\x73\x84\xde\x7c\xfb\x2f\xb0\xf5\x42\x92\xbe\xd4\xb1\xb2\xe1\x4b\xb0\x0d\xfc\x46\x12\x93\x29\x6e\x81\x84\x0d\x21\xc8\xc0\x44\x32\x19\x88\xe6\x7b\xef\x99\xc0\x7c\x5a\xf5\xb2\xec\xb1\xb7\x1c\x49\xc3\x34\xb9\xa0\x3a\x01\x99\xb2\x06\x2c\xc6\x3f\x49\x66\xd6\x78\x29\xc7\x93\x68\xa8\x46\xa6\x1f\xb5\x98\x31\x76\x70\x40\xaa\x1f\x27\xd0\x8f\x44\xea\xde\x4f\xbc\x87\x3f\xf6\xbb\xe2\xb1\x2e\x5a\x69\x0b\x48\xed\x1d\xab\xb1\x77\xb8\x41\xfe\x86\xf1\x23\x6f\x7d\xb1\x4b\x9f\x73\xe5\x9f\xe8\x02\x9e\xa8\x73\x28\x8d\x1c\x7b\xff\x70\xec\xf5\xf4\xc4\xfb\x74\x63\x2a\xed\x31\xc5\x77\xcc\xa5\x3c\xfe\x2d\x79\xc2\x96\x4f\xb0\x39\x1c\xd3\xb5\x18\xcb\x62\xbc\x27\x5a\x31\xeb\x03\x5e\x9f\xa0\x7b\x48\x6b\x58\x7b\x03\xf3\x39\xf1\x8a\x71\x22\x02\x9d\x71\x7a\xc0\x0b\x4f\x4a\x8e\xfe\x8b\xf7\xef\xc6\x22\xd6\x0f\x62\x1f\xb5\x7d\x3b\xbe\xb6\x67\x93\x4e\x58\x45\x63\x3f\x40\x67\xb6\xfe\xc2\xb4\x8b\x48\x22\x46\x3d\x2c\xfb\x09\x37\x92\x63\x11\x58\xf4\x41\x06\x16\xd2\x3b\x76\x03\x9b\x8c\x89\x32\x2b\x31\xb4\x2b\x37\x24\x1b\xa5\x09\x4c\x0c\xd2\x0a\x27\x81\xce\xb0\x8f\xbd\x54\x8f\xcd\xa4\xc4\x27\x0d\xdb\x54\xd8\x68\x06\xa4\x1b\x8b\x0c\x01\x1a\xa2\x16\x28\x78\xe1\x3d\xd1\xb2\x03\xbc\x9e\x49\x2f\x06\x86\x2c\x6d\xc8\x52\x54\xdf\x03\xe5\x44\x0b\x43\xf6\xc6\x98\xa5\x8c\x99\xef\x97\x2e\x64\xf2\xb7\x04\xca\xa5\xa1\x23\x23\x61\xfc\xee\x40\xa6\xba\x7e\xad\xb4\x82\xf5\x17\xbe\x59\x05\x2b\x29\x99\xb5\xf4\x69\x17\x43\xa1\xec\x2f\xe8\xf3\xa3\x97\xe7\x2f\xdc\x6a\xe3\x49\xe3\x17\x38\x92\x36\x7e\xa3\xf8\xc5\x36\xe4\xad\xef\x52\xcd\xe6\xc5\x26\xeb\xc6\x3a\xa3\xf9\xcd\x38\x75\x99\xac\x87\xdc\x90\x0d\x5e\xe3\xbb\x16\x97\x44\x26\x95\x0d\xd9\xa4\x17\xec\x89\xf9\xa4\x65\x45\x6d\xd7\xdf\x02\x2d\xd9\x8c\x57\x16\xf2\xca\x2a\xd7\x7c\xba\x86\x82\x03\xd2\x66\x7c\x17\x6f\xb9\x02\xd9\xb2\x75\x3b\x16\xb4\x93\x31\x6b\x40\xf6\x2c\xf5\x9d\x46\x25\xe3\xde\x35\xa3\x86\xca\xe8\x39\x66\xb2\xb2\xb4\xac\x33\xd3\x2e\xec\xfa\xd5\xc6\x2b\xf9\x43\xe3\x7a\xb1\x60\xb3\xc0\x08\xce\x3c\x8b\x25\xaa\xc8\x17\x3d\x1f\xb6\xc9\xe8\x50\x66\x62\x70\x30\xdf\xa2\x59\x64\x56\xf5\xc9\xd0\x1a\x23\x03\xee\xa3\x0d\x19\x97\x74\x46\x7b\x9d\x49\x06\xb4\xd9\x36\xbb\x40\xda\xe6\x8c\x15\x65\xcc\x97\xb3\xdd\x5f\x10\xf1\xc2\x02\xcc\xcc\xc7\xd4\x98\x12\x78\xf0\x6a\x8c\x38\xfd\x72\xcb\xb5\x9c\x23\xcc\x03\x94\x72\x9f\x0c\x92\x11\xdd\xfa\x64\x5d\x40\xb7\xe6\x0f\x0e\xf8\x64\xee\x9f\x34\xd0\x4c\xb9\x77\x0e\x41\x3e\x81\x62\x5d\x71\xbb\x90\x63\x1b\x8e\x42\x0a\xa6\x95\xac\xa5\x64\xb3\x4a\x46\xc9\x84\xc8\x90\xe4\xe6\xfa\x5f\x49\x62\xc1\xb5\x88\x5b\x66\x24\x8c\xbd\x8e\x87\xec\x1d\x44\x5f\xe4\xb4\xf4\xb7\xb6\x80\x97\x7c\xe7\xd9\xd7\xd3\x04\x29\x35\x67\x30\x17\x47\xaa\x60\xbd\x0b\xdf\xd0\x96\x32\x7e\x2b\x2b\xae\xc6\x8a\x93\x27\x61\x8a\x6f\x7b\x66\xea\x52\x9a\xe7\x9c\x6b\x2c\x97\xbd\xa9\xa6\x6d\xf1\x1f\x64\xc7\x9e\x1d\x89\xae\x7e\x73\x0d\xde\x30\x44\x1a\x45\x27\x87\x10\x63\x80\x7a\xa6\x30\x6b\xa2\x0f\x66\x1b\x43\xf1\xe5\xae\xab\x66\x87\x72\xd8\x47\x4c\xcd\xad\xca\x9f\x8e\x5d\x8c\x97\xe4\xe4\x8d\xcf\x19\xd4\xf6\x54\xc4\x70\x0d\x34\xa0\x9e\x9f\x7a\xbd\x09\x12\x91\x7a\x45\x77\x2e\x9e\xd9\xf2\xa1\xd6\x70\x67\xe1\xb2\x54\xb2\xf0\xe5\xb0\xb2\x32\x12\x45\xf0\x62\x6b\x23\xc9\x88\x6b\xfe\x0e\x26\x87\x48\x05\x13\xe4\xd9\x93\x85\x27\x2b\xb6\x30\xa8\x34\x43\xa6\x34\xee\x28\xd6\x77\x76\x16\x12\xb7\x1e\x77\xc1\xe9\x90\x2e\x4c\x29\x40\x92\x66\x7d\xa8\xd8\x81\x2a\x68\x56\xd9\xf0\x4c\xbd\x98\xdf\x31\xb2\x86\x68\xd1\x1b\x90\x9c\x9e\x04\xd9\xfb\x1f\xf9\x0d\x3b\xdd\xd2\x9e\x4f\x79\x46\x31\x55\x43\x61\xd5\xbd\x30\x46\x84\x27\xaa\x58\xa6\x16\x29\x8d\xd9\x96\xbe\x80\x0b\xc7\xa2\xf5\xfa\x07\x7c\xe2\x72\x9a\x82\xbb\xa3\xdc\x4b\x34\x2b\xac\xf0\xba\xe7\x43\x5b\x53\x31\x2f\x77\x44\x35\xd1\x15\xe8\x3b\x87\x6d\xcb\x4e\x6d\xd9\xf4\x3d\x25\xe4\xc0\xb4\x13\x7d\x8d\x3b\x31\x27\x5a\xbb\x1e\x01\x4c\x65\x11\x8d\xad\xf6\x60\x47\x2a\x43\x9a\xc1\x04\x66\x4a\x1d\x3f\x95\x45\x32\x35\x21\x73\xeb\x64\xca\x63\x8a\xa9\x86\x08\xb4\x91\x81\x8c\x88\x20\x75\x01\x65\x4c\xbb\xb3\x16\x3b\x9f\x6e\x6a\x61\xca\x9c\x24\xc6\x10\xc0\x6b\x93\x0c\xe7\xf0\x4d\x75\xe7\xe2\x5e\x5b\xfa\x56\xad\x7c\xb6\xb5\x7f\xb2\xb1\x79\x0a\xe4\xe4\x1b\x7f\x21\xba\xba\x86\x06\xa3\xca\xb7\x2d\xfa\x02\x12\x7a\x5b\x88\xec\xe5\x78\x5b\xac\x59\xff\x3b\xd1\x3b\x24\xf9\x9e\x1e\x65\xe1\xc3\x14\x85\x86\x59\x1d\x51\xf5\x73\x6f\x51\x55\x1d\x87\x7b\x0b\x8f\xc6\x32\x74\xf8\x0a\x0b\x75\xc4\x27\x8f\x44\x1a\xe3\xbc\xf7\x76\xae\x30\x3b\x97\x93\x34\xfe\x89\xee\x4a\x0b\x0b\x54\xc6\x4a\x96\x3e\xdb\xab\x7f\xb2\xf6\x4f\xf6\xbe\xd2\xb3\x6f\xff\xc5\xf5\x34\x48\x1c\x5b\x90\x8c\x30\x0d\xd1\x9d\x2d\xb8\xf5\xba\xa7\x6c\xdf\x8b\x9f\xda\x5a\x9a\x95\xa5\xbb\xad\xc2\x9b\xd9\x82\xf6\x88\x64\xed\x9f\xec\x59\xf9\x2d\x27\x2e\x8e\xee\x94\x6d\x28\x44\x09\x93\xc8\x62\x28\x10\xfb\x00\xaa\xd8\xf0\x9a\x95\xc5\x81\x56\xb5\x12\x0f\xed\x20\xbf\xcf\x30\x1e\x85\x1f\xf9\xc6\x77\xbd\x61\xa9\xd1\xf1\x2d\x10\x43\x06\x6a\x79\x6e\x06\xf2\xc6\xe2\x5b\xc4\xf1\x0a\x3f\x5d\x4b\x3e\x5d\xc9\x96\xe8\x86\xa4\x22\x7a\x33\x64\x42\xbd\x96\x61\x5e\x83\x6c\xf1\xbf\x67\x23\x72\xe1\xa8\xed\xa0\xb6\x04\x25\x43\xcc\xcd\x9e\xf5\x1d\xa0\x6a\x41\x8e\xec\xc8\x91\x19\x3e\x69\x95\xef\xa5\xd4\x78\xfc\x2b\x07\x19\x6e\xea\x2f\x74\x3b\xf0\xa4\x65\xe3\x2e\x36\x6e\x41\xb3\x7d\x81\xa9\x2d\x18\xef\x2c\xe8\x0b\x17\x54\x73\x82\xb4\x09\x66\xd6\x80\xd0\xab\xe0\x55\xa5\x44\xef\x40\x43\x1b\x4f\xf3\x91\x0b\x31\xb5\x5a\xf5\x24\x7a\x6b\x56\x70\x26\x33\x36\x05\xc9\xa5\xf2\x25\xc9\x84\x6f\x16\xdc\x78\x16\x3e\xca\x5a\x50\x77\x16\xbf\x29\xc5\xc2\x94\x62\xcc\x46\x89\x82\xea\x73\xa5\xad\x3d\x79\xef\xfa\x1b\x92\x7f\xfd\x93\x0b\x1b\x5a\x20\x64\x09\x34\x71\x95\xd8\x96\xfd\x41\xc3\xe6\xd2\xb6\xd2\xdc\x9e\x01\x89\xda\x41\x64\xbb\xf3\xa4\x60\x1e\x75\xda\x4a\x1f\x50\x7f\x30\x07\x28\x56\x12\x03\x53\xa5\x77\x64\x1f\x7e\x3b\x68\x2b\xa1\x84\x80\x34\xda\x04\x32\x81\x79\x45\x72\xcc\x70\x85\x40\x94\x3c\xfc\x2b\x65\x2f\x12\x8b\xcb\x59\x42\x4e\x3b\x5b\xc2\xb5\x04\xd2\xbd\x76\xc9\x75\x58\xfa\x4b\x17\x0f\x5c\xfa\x25\x83\x12\xa5\xf9\x23\xda\xd7\x96\x9a\xff\x81\x2b\x1b\xc9\x13\x96\xfd\x62\x1b\x8b\x9c\xd9\x2a\x16\xf5\xe8\xdf\x9e\xb3\xe9\x2d\xbd\xa6\xd2\x1c\x98\x41\x97\x24\xe0\x4b\x4e\xd4\xca\x27\xaf\xf8\xf6\x8a\x31\xeb\x92\x0a\xa2\xa4\xeb\x52\xd2\x65\xc7\xd6\x45\x9b\x19\xf7\xba\xa5\xc4\xcd\x75\x3c\xce\xcc\x7a\x46\x2c\x0f\x07\xfc\x3a\x21\x57\xff\xd2\x55\xdc\xd1\x89\x90\xb0\x8a\xa7\x3d\x1f\x60\x2e\x65\x69\x0e\xfd\xd9\x4d\xc9\x35\x5a\x72\x3d\x96\x8c\x28\x22\xc2\xf1\xdc\x43\xcc\x4d\x46\x07\x03\x92\xe4\x8c\x1c\x97\x8c\x33\x97\x7e\x0d\x96\x74\x5e\x80\xe2\xb6\xb9\xf4\x5e\x4b\x69\x5e\x0b\x66\xd3\x36\x0b\x7c\x52\xfb\x6c\x33\xeb\xa7\xf8\x2f\x44\x0b\xa2\x0b\xd1\xd5\x90\x39\x1a\x15\x37\xba\x15\x0f\xd2\x2a\xbb\x07\xf4\x82\x65\x5f\xf9\x2d\x93\x84\xe2\xa5\xc1\x15\x3b\x55\xc1\xb2\xf7\x34\x36\x6f\xc5\x8d\x30\xd0\x15\x17\x70\xc5\x1d\xcc\x23\x2d\xac\xb8\xe9\xe2\xc5\x54\xec\xd6\x23\x6f\x3d\x54\x22\x6d\x29\x0b\x6a\x10\x58\x02\x5a\x12\x5d\x81\xa2\x35\xab\xec\x2a\x83\x56\x11\x8f\x47\x2b\x9a\x0c\x41\xa6\xa8\x2b\x0a\x6f\x45\x3d\x00\xd4\xa2\x41\x6a\xe4\x1e\x29\x22\x38\xfd\xfd\x02\xb1\x12\x62\xea\xbf\xa2\x5a\xac\xc4\xb4\x5d\x0c\x59\x9a\x1e\xac\x01\x9d\x80\xf6\xac\xfd\xcd\xb7\x55\xaf\x2f\x08\x32\xdf\xb9\xa2\x09\xac\x44\x7b\xc4\x3e\x1f\x39\xba\x27\x66\xf8\xc9\x97\xce\xcc\x77\xe6\xd3\x0b\xd3\xd4\xcc\x55\xf4\x4e\x2b\x2c\x15\x24\x3f\xc2\xaf\x87\x0c\x56\x74\x5a\x2b\x2e\xa2\xca\x0d\x65\x10\xe9\x81\x27\xa9\x27\x23\x1b\xc9\x40\x26\xd4\x13\xd5\x6f\x3b\x6e\x3d\xa1\x74\xcd\x0e\x7c\xea\x4b\x8a\xe8\x81\xcd\xf9\x93\x57\xe7\x40\x66\x9e\xcc\x7d\x51\x8d\x7f\xc7\x8b\x8e\xee\x04\x33\xdf\xce\x8b\x3d\x89\x42\x25\x27\x4c\x28\xe3\x91\xea\xe2\xd1\x42\x5e\xb1\x17\xff\xf1\x2e\x21\x9e\xc7\x16\xfe\xc7\xef\x0f\xc1\xaf\x86\xc2\x7c\xbf\xd9\x3b\x1a\x68\xd6\xd7\xfe\xb2\x3b\x12\x03\xf2\x9c\xc6\x0d\xfc\xc5\x0f\xd6\x5f\x4e\x6c\x83\x0b\x91\x98\x58\x85\x3a\x66\x9c\xc1\x18\xd8\xa8\xa8\xa7\x2a\xaf\x97\x1e\x2d\x68\xf6\x27\x9f\xcc\x10\x68\x20\x5f\xb0\x11\x05\x07\xab\xa6\x6e\x01\xaa\x88\x82\xd1\x7c\xc2\x9d\xb2\x9e\x9e\xdb\x98\x06\x01\x19\x13\xa9\x15\x79\xf2\x07\xe3\x3c\xe8\x51\x3f\xaa\xb6\xfb\x24\x39\xc9\x23\xba\x5a\xeb\x26\xc5\x5e\x8b\x67\x71\x35\x22\xa2\x40\x7a\x27\xa6\xf6\x3e\x7d\xcd\x55\x50\x8b\xb2\xd2\xb4\x02\xfd\x78\xe2\x21\x49\x2d\xa4\x62\x86\x1a\xe1\x87\xda\x5f\xf4\xa8\xbd\x2e\x7a\xb2\x53\x95\x48\x56\xc8\xa3\x1a\xa8\x66\x64\xaa\xe6\xb5\x0b\x04\xe9\xb4\xbe\x3d\xcc\x50\x2d\xb2\x71\xc3\xca\x9f\xbc\x5e\x78\x92\x6d\xe8\x77\x28\xaa\x5a\x86\x4e\xbb\x7d\x64\xda\x07\xb4\x69\xcd\xf9\x7f\xe2\xba\xab\xc5\x8b\xd6\xfa\x2e\xd6\x39\x0b\x05\xd7\x3c\x81\xac\x65\xfd\xa2\xd5\xb8\xbf\x24\xce\x4c\x1d\x2c\xa4\x6c\x67\x6a\x59\x2e\x72\x99\xc5\x5e\xc8\x5c\x9f\xcd\x5c\xd6\xfe\x16\x62\xad\xae\xa4\xbc\x30\xf3\xfe\xfb\xcc\x3c\xc3\x96\x44\x9d\xc1\x28\x90\x33\x7f\x1c\x37\xe3\xc1\xca\xcc\xbc\xb8\x31\x5f\xc8\xb8\x6f\x9f\x21\x16\x4e\x94\x12\xe1\x84\x34\x65\xb6\x29\x51\xc1\x72\x6b\x56\xac\xda\x05\x68\x0a\xf4\x42\xfb\x37\x33\x0d\xa3\xc6\xff\xab\xf0\xf8\x24\x96\xfd\x42\x17\x70\xa6\x07\x72\xb2\xcc\x21\xb0\x33\x31\x66\x7f\xf3\xcd\x96\x61\x37\x90\x6f\xbe\x98\x1f\xfe\xc9\x3b\xd1\xc9\x25\x9b\x5a\x07\x19\xb1\x5e\xbd\x6f\x37\x13\xd1\xd3\x57\xf7\x50\x4e\x33\x89\xf2\x66\x40\x9f\xd8\xc4\xcd\x28\x28\x33\xda\x95\x19\x97\xc0\xcc\xdf\x96\x9b\x49\x35\xc7\x1e\x66\x1c\xb1\x0e\x24\x17\x56\x82\x06\x81\x22\x19\x13\x65\x50\xb2\x20\xf1\x3d\x15\x04\x94\x78\xcf\xe4\xd2\x17\x12\x34\x2c\x49\xed\x9f\xcc\x3c\xf9\x9b\xa8\xf1\x35\x44\x73\x31\xf3\xb1\xa1\x99\x8f\x0d\x81\x68\xb4\x0d\x64\x6b\x63\x1d\xc8\x0f\xbc\x83\x56\x9e\x88\xfe\x75\x6f\xab\x1c\x22\x4a\xe4\x8e\x2b\x90\x94\xb8\xd2\x6c\x9b\x09\x92\xfa\x32\x54\xfe\xbf\xc2\xed\x23\x1a\x51\xf8\x66\x7e\x2f\x06\x12\x9a\x3c\xe7\x6c\xcc\x4d\xff\xde\x61\x06\xc1\xb7\x3d\xbd\xbc\xaa\xc7\xa0\xf1\x8c\x62\xce\xc3\x11\xa0\x7b\x22\x35\x7c\x20\xcf\x9e\xac\x3d\x79\x37\x24\xdd\x26\x19\x01\xc5\x2b\x46\x73\xc6\xba\xe6\xbc\xc9\x31\xe7\x8d\xa1\x39\x57\xe6\xdc\x42\x23\x9a\xf5\x81\x59\x2b\x98\xa0\x39\xa7\x7d\x4e\x23\x31\x97\xbf\xdb\x1e\x63\x2a\xec\x7c\xcb\x52\x5b\xdf\x80\x17\x6a\x14\x3c\xf9\xe2\x07\xe4\x05\x71\x5c\x92\xc2\x3f\x99\xf9\x32\x56\x40\x2b\xde\xfa\x03\xf9\x2f\x26\x6f\x2e\xab\x71\xc8\xb6\xac\x71\x70\x32\x17\xe7\xef\x13\xe8\x93\xd3\xf6\xc9\xa9\xbc\xb0\xf2\x8b\xbd\x1b\x3c\xba\xdc\x50\x58\x86\x43\x90\x3e\x33\x24\xf8\x0f\x22\x97\x56\xfb\x5f\x7b\x76\xa1\x46\xef\x81\xce\x79\xdc\x31\xf7\xf1\x85\xb9\x3f\x65\x07\x79\xf0\xa4\xb2\xf6\xc8\x2a\x63\x43\x7e\x59\x5b\x7f\x23\xaa\x40\x74\xb2\x61\x72\x31\xd4\x86\x1b\x18\x1c\x46\x0d\x98\x3c\xa0\xb2\x6e\x7c\x48\x01\x44\x4d\xc1\x33\xae\x9d\xa0\xfa\x86\x37\x4f\x80\x6e\x91\xe7\x97\x53\xea\x86\x91\x06\x20\xed\xd3\x73\xe7\x2e\x8c\x63\x35\x3f\xdb\x4d\x94\x58\xa0\x9e\x4d\x83\xcc\x7d\x0b\x1a\xdf\x85\x38\x00\x3c\x5f\x8b\x75\xbc\x32\x50\x88\x87\x6b\xff\xe6\xd6\x57\xb0\xf3\x65\xe8\x86\x01\x65\x1c\x7e\xab\xe0\xe8\xc9\x4f\xdf\xd1\x33\xd1\x45\x03\x81\xb2\x5c\x90\x74\x95\x79\xb8\x35\x2e\xca\x0a\xa8\xef\xca\x48\xfc\x98\x9a\x32\x02\xb9\x21\x1a\x31\x0c\x01\x3e\x26\xca\x59\x54\x0a\x01\x8d\x91\xcc\x46\xa6\xb1\x36\x14\xd3\x2c\xfa\xd5\x50\x1a\x81\xb6\x40\x19\x64\xaa\xb1\x73\x51\x2d\xbf\x60\x03\x0a\xdf\xe8\x92\x25\x54\x3c\x68\x7a\xd6\x6d\x81\x98\xb0\xc6\x7b\x88\x8d\x39\x84\x39\xf9\x1c\x9f\xda\xf4\xf4\x43\x18\xfb\xae\xa5\xa1\x49\x69\xa4\xc0\x8a\xf5\xe8\x86\xb6\xc1\x15\x7d\x8c\xf8\xb3\x79\x0f\x03\x92\xe8\x3d\x80\x17\x44\x15\x4f\xfd\x9e\xed\xf2\xaf\x16\xbd\x64\xab\x56\x7e\x18\xd7\x52\x4f\x03\xb2\xe1\x88\x7c\xe7\x20\xe0\x16\x82\xb6\x6a\x4f\x29\x3b\x31\xeb\x07\xcb\xfa\x64\xf7\x2e\xd0\xfc\x0d\x55\xce\xb3\x28\x1a\xe4\x13\x57\xc3\xca\x0f\xa4\xee\xf9\x0f\x5e\x1a\xee\x51\x1a\x5c\x9c\xb7\x2e\x24\x6c\xb5\x1d\xd0\x35\x7a\xef\x57\x76\xb5\x30\x46\x96\x1a\xc5\x3c\xa1\x7c\x24\x63\xa8\xd8\xc6\x89\x49\x02\x0b\xa6\xc9\xd1\x2b\x6d\x64\x1e\xff\x60\xce\x67\xf3\x51\xb4\x61\x05\x5b\x55\x70\x5f\xdb\xd0\x47\x69\x18\x62\x6d\x54\x19\xba\x0c\xf7\x44\xa5\x4f\xa6\x0a\x79\x67\x75\x33\x5f\xc9\xdc\x44\xc6\x9d\x17\x3f\x33\xdc\xd3\x78\x67\xa4\xf1\xce\x08\xf2\xac\x99\xbc\x31\x41\x86\x5b\xe2\x3a\x44\xb5\x91\xc8\x67\x03\x2e\xdb\xa7\x7f\x72\x71\xef\x98\xdb\xf8\x6c\x8e\x44\x4b\x92\x11\x85\x66\x2f\xa8\xac\x17\xdc\xf3\x2d\x28\x07\x0b\x3b\xbf\xd6\x0c\x43\x66\x18\x33\x6d\x0c\xad\xb1\xf0\xa7\x57\x0b\xee\xd5\x17\x76\xce\xfd\x64\xc4\x92\x75\x71\x2f\x7c\xf9\x15\xab\xad\xbc\xb0\x2c\x38\xe4\x0b\x6a\xe9\x05\x07\x7b\xc1\x88\xeb\x42\xbf\xb1\x49\x34\x39\x1e\xfa\x2e\xb8\x81\x5b\x30\x70\xb4\xe0\x72\x12\x24\xbe\xcc\x82\xa3\xbd\xf0\x4a\x79\x81\xa0\x0d\xdd\x82\x05\xf7\x62\x0b\x19\xf7\x06\x48\x6f\xee\x00\xbd\x62\xa8\x17\xb6\xae\x5e\x7b\xfc\x22\xd0\x8e\x5b\x3e\x7a\x8c\x78\x5b\x57\x92\xd4\xab\xde\x85\xc9\x5e\x45\x82\x08\x35\x87\xd1\xbe\x55\x03\xba\xf6\x34\xca\x66\x77\x13\x17\xbf\x0e\x63\x58\x69\xda\x8e\xdc\xe6\xdf\x89\xed\x42\x9d\x58\xa9\xbb\xe5\x66\xbf\x35\x83\xb8\x00\x49\x99\x9c\xfa\x9b\x00\xad\x1e\x06\x4a\xcb\x5a\xdc\xd5\xef\xf9\xef\x06\x05\xd9\xc2\x6d\x79\x2d\xa4\xe5\x65\xe5\x16\x27\xdf\x86\x2c\xed\x9e\xaf\x47\x4b\xd3\x06\xf7\xcb\xda\xa9\xe1\x43\x41\x62\xf3\x5a\x09\x60\xf7\x99\x75\xcd\xb8\x7f\xcb\x73\xf7\x56\x56\xd9\x7f\x59\xdf\x8e\x19\x4e\xd0\x62\xf8\xa6\x31\x7e\xda\xd0\x52\x6b\xb6\x32\xc1\x59\xcf\x36\x68\x8d\x65\xb0\xef\x8c\x80\x90\xd5\x8e\x91\x5a\x19\xfd\x4f\xa2\xab\x35\x5f\x4f\x8a\x76\x24\xa1\x84\x25\xa3\x32\x40\x4b\xa2\x2b\x50\xfc\xb2\x6f\xc9\x89\x5a\x72\xe1\x2e\xd5\x43\x92\x9a\x97\x76\x51\x37\x27\xd1\x2b\x29\x4b\x1e\x9d\x2c\xfd\xc1\xcc\xd2\x7b\x40\x4b\x4a\xef\xd2\x3c\x9a\x98\x1c\x97\xc8\xd2\xbb\x2a\x20\x9f\x7c\xa2\xb1\xe8\x25\xef\xa3\x83\x64\x54\x86\x4b\x91\x86\xa0\x61\xbf\xe9\x29\x61\x5f\xcb\xf9\xe5\xa0\x06\xfc\x0e\xa8\xe6\x48\xcd\xf9\x74\xc1\x4d\xc7\xd2\x7b\x6d\x4b\x7f\xcc\xb2\x34\xe9\xc9\x50\x5d\xd8\x88\x33\xf9\xd3\xbd\x20\x6a\xe4\x9b\x68\x89\x31\x3c\x9d\x25\x55\x06\xd0\x2d\xeb\xda\xc9\x58\xdc\xf4\xec\x33\x57\x4d\x3e\xe1\xf2\x11\xc8\x11\xa1\xa1\x25\x8e\x47\x58\xce\x99\x63\x76\x61\x2d\x17\x19\x9c\x27\xce\xcd\x15\x01\x7a\x23\xc1\xfe\x62\x14\xcc\xe4\x2e\x45\xcb\xbf\x03\xe5\x88\x6f\x00\x35\x28\xe4\x9b\x37\x94\x4b\x7f\x00\xb2\xf4\x9b\x84\x25\x2d\xe4\x92\xbe\xe4\xd2\xdb\x4a\x90\x7b\x1b\x4a\xb7\x8b\x07\xa9\x88\xf4\xe8\xe0\x1b\x6d\xe1\xd2\x6c\x61\x2c\x9e\xd3\xef\x2e\x6d\x80\xfc\xcf\x46\xd3\xec\x1c\x4f\x20\x96\x66\xe0\xd8\x13\x0d\x04\x69\x17\xbe\xd9\x66\x5a\x95\xe8\x37\x1a\xbb\x57\x1a\x3b\x1c\x86\x4d\x90\x16\x6f\x61\xac\x7e\xbb\x85\x81\x87\xb7\x7c\x52\x19\x92\x83\xe7\x9e\x9e\x9e\x59\x89\xfa\x9d\xf1\x8a\xb7\x84\x57\x74\x87\x57\x74\x87\x57\x6c\xe7\x8a\xdf\x1a\xac\xec\x1a\xf1\x88\x44\xc5\x63\x85\xeb\x8e\x44\xf1\x4c\x18\x7c\xc9\x76\xe7\x38\xe9\x05\xd2\x23\xb9\x15\x55\xc0\x8a\xfa\x74\x05\x67\x1a\xa8\x64\x8b\x11\x91\x8e\xc3\x30\x67\x2d\x0d\xd3\x16\xbe\xf2\x5f\xae\xa9\x83\xe7\xcc\xd9\x32\x5c\x08\xb2\xf1\x39\x5f\x7d\x5b\x56\xb2\x74\x86\xe4\x6b\xb6\x77\xfd\x6b\xb2\x8d\xcd\x8e\x17\x9b\xe3\x55\xab\x57\x59\x68\xba\x37\x5f\xd1\x36\xaf\xa8\xb0\xa3\x31\x58\xe9\xc5\x59\x11\xc8\x15\xd5\xf4\xab\x0f\x59\xaf\x64\x55\xb1\x72\x15\xad\x16\xd9\x0a\x86\x6b\xd7\xfe\x02\xe0\xda\x7f\x0c\xb1\xf6\x47\xde\x20\x35\x91\xba\x10\x6b\xbf\xe5\x5c\x53\x50\xd6\x54\x60\x6b\xdc\xf9\x04\xd2\x30\xcf\x9a\x97\x71\x40\x4a\x2c\xf4\xb5\xac\x72\x68\x4e\x2d\xfb\x85\x6b\x6b\x0d\x55\x26\xeb\xf1\x0a\x8e\xea\x2a\x90\x0d\x8f\xfb\x84\x98\x29\x02\xd1\xae\xe9\x95\x98\x35\x75\xd8\x5a\x8f\x99\x45\x48\xd7\xd4\x5c\x40\x5a\xcb\xd5\xb2\x86\xb1\xbf\xb1\x12\x6c\x22\xd6\xf2\xe9\xcb\x1f\x40\x37\xd6\xd4\x80\xde\x89\x4e\x40\x13\xbe\x81\x2b\x3e\xef\x24\x7a\x7d\x7e\x23\xeb\x3a\x05\x1a\xf0\xe7\x15\x36\x3c\xa7\xdc\x70\x99\x6e\xb8\xfc\x36\x92\x6f\x09\xa4\x1b\xd0\x8d\x7d\xa6\x79\x25\xd1\x2b\x4c\x1b\xce\xc1\x86\x47\xc6\xdc\x01\x20\x55\x9d\xd7\x8d\xc5\x53\x77\x20\x0b\xef\x23\x09\x77\xa2\xb6\xe1\x4d\x00\xa0\x8c\x68\xca\x56\xc6\xd0\xd4\xc6\x7f\x00\xb2\x71\x1f\x80\xe4\xe4\xb5\xcf\x39\xf3\x05\x2e\x59\xe0\x9a\x79\xce\x2c\x4a\x43\x47\x1b\x6e\xf2\x36\x32\x3f\x18\x5d\xf3\x50\x2d\x77\xf2\xcb\xc7\x46\x1b\x9d\x17\xcb\x5c\x58\x45\xb6\xeb\xda\xd0\xa6\x6c\x7c\x30\x78\x63\x51\xa7\xf8\xe4\xc9\x5a\x96\xc4\x7b\x7f\x1b\xef\xa1\x6e\x68\x4c\x36\x7e\x63\xb5\xd1\x1d\x94\x0e\x84\xd8\x0f\xa2\x8b\x6b\x99\x08\xdc\xc6\xef\x90\x36\x3e\x22\xfb\x1d\x47\xe9\xd0\xed\xdf\xa9\x9f\xd5\xd2\xf3\x56\xc4\x77\x46\xa2\xbe\x8b\xd6\x53\xaf\xef\x3b\x0f\x98\xbe\x63\x45\x60\x8e\xbf\xe3\x47\x28\x80\x6e\xac\x44\x8d\xab\x69\xbc\x60\xcb\xe3\xb8\x2d\x97\xd5\x96\x71\x97\x2d\x2f\xff\x6e\xa5\xe6\x59\xcf\xae\x55\xeb\xb0\x6c\x79\x53\x05\xf7\xb6\xbe\x1a\x92\xd6\x6c\xe9\x35\x6d\xed\xc0\xac\x06\x99\x33\x4c\xb0\x65\xf0\x77\xcb\x0b\xb5\x5b\x93\xb0\x98\xac\xdf\x31\x6d\x19\xc4\x80\x77\x86\xa4\x13\x37\xc3\x5b\x2a\x8a\x2d\x5d\xaa\xad\x88\xdb\x48\xbc\xa3\x33\xc6\x63\xcb\xaf\x55\xb7\xfa\x91\xb8\x28\xa5\xad\xe8\x8e\x6b\x4f\x7f\x4b\x40\xdb\x12\x10\xbb\x9b\xe8\xcf\xa0\x6c\xa9\x3b\xb6\xf2\xfa\x03\x10\x9c\x9b\x11\xc9\xc8\x0a\x4e\xe2\x85\xef\xad\x85\xc8\x23\xb9\x25\x8a\xe5\xc4\xf7\xfc\x6c\xc9\xc5\x14\xa2\x7f\x88\xf4\x76\xe9\xd6\x6f\xc8\xb7\xce\x1f\x49\xc9\x55\xcb\xef\xb8\x39\xde\x49\x33\xff\x0b\xdb\xb6\xe3\x4d\xa6\x9d\x7d\x9e\x72\x05\x29\x64\xc4\x47\x24\xb5\x21\x99\xc6\x1d\xcf\x8e\x77\x8c\xe1\x0a\x12\x41\xd8\x59\x10\x28\x05\x59\xf0\xa2\xce\x8e\xa7\x5d\x3b\x5a\xd5\x1d\x6e\x38\x00\x7d\xb0\xd4\x4f\xa2\xf8\x3b\x2b\x3b\x5e\xa5\xdb\xd9\xaf\x01\x7c\x27\xd9\xc2\x28\xed\xfc\x3d\xf5\x9d\x7d\xca\x90\x81\x68\x88\x68\x47\x4d\xf1\x46\x57\x6d\xcf\x43\x8f\x37\xbd\x05\x23\x59\xdf\xb8\xeb\x79\xe3\xfd\x97\xbd\x8f\x0b\x83\xdc\x13\x55\x3e\xb9\x66\xd9\xd1\x22\xef\xbd\x45\x06\x59\xb0\xf8\x37\xf7\x82\xc5\x53\xf6\x74\x12\xf6\x74\xef\xf6\xb4\x2f\xf1\xd2\xc8\x9e\xd7\xc4\xf6\x74\xe2\x40\x62\x53\xf5\xc0\x69\x8f\xcb\x51\x86\xec\x69\x85\x8e\xbc\xd1\xa9\x90\x34\x2b\x52\x67\xfc\x87\x9e\xaa\xd8\x4b\x73\xa2\x86\x28\x06\x29\xf6\xfe\x42\xda\xde\x9f\x84\xee\xb9\x39\xda\x9b\x9b\x37\x22\xc9\xf9\xf6\x8b\x6f\x7e\xb4\x51\x7b\x6f\xa3\xf6\x5e\x83\xec\x4d\x69\xc4\x02\xa2\x47\xb9\x57\x1b\xe5\x72\xfe\xc3\x15\xb3\xf7\x3f\x4f\xb2\xe7\x1d\x7a\xa0\x77\x20\x31\xec\x22\xe5\x7b\x9c\x48\x63\xe9\xee\xa5\xc3\x13\xeb\x4f\x50\x22\x63\x2b\xc7\xf6\x10\x7b\x91\xde\x01\x11\xde\x33\xc5\xb2\xc7\x69\x4a\xd7\xff\xd3\x1a\x67\x3f\xd8\xb1\xa7\xad\x03\x1a\x7a\xc2\x91\x55\x57\x21\x27\x89\xa7\x72\x6f\xd0\x3a\x36\xe1\x89\xba\x6f\x7b\x6f\x5d\xf7\x7e\x2f\x05\xa2\x8a\xfa\x07\x6d\x21\x50\xcb\x0c\x4b\xdf\x90\x15\x3b\x14\x43\x89\x20\x3f\x88\x4e\xbe\xb1\xff\xe7\xc9\x27\x0f\x0e\xf7\xde\x6a\xee\x3b\x77\x63\x0d\x44\x35\xe9\x81\xf6\xeb\xc0\xd3\x9e\x03\x17\xca\x81\x63\x71\xe0\xf2\x38\x70\x79\x1c\xa8\x9c\x0f\xdc\xf7\x1c\x78\x4a\x77\x30\xe7\x37\x23\xd1\x82\x4a\x66\x2d\x65\xad\x9c\x58\xb0\xca\xe1\xbb\xfb\x6c\x31\xd6\xa0\x6b\xe9\x20\xeb\x66\x6c\x48\x64\xe8\x20\x8b\xe6\x0f\xd6\xf5\xcc\x12\x1b\x36\xb5\x85\x9b\x70\x30\xe9\xaf\x48\x2a\x66\x40\xad\x07\x56\xf9\x02\xc9\x3d\xf8\x2d\xd2\x3f\xf6\x03\x3d\x23\x92\x05\xab\x6b\xe9\x9b\x1c\x38\xaf\x07\x99\xd4\x7b\x88\xcd\xc1\xbc\xee\x96\xef\xac\x59\xdd\x96\x8d\xdd\x33\xed\x9d\xc3\x16\x83\x37\x07\xee\x99\x0e\xf6\x6b\x2d\x23\x12\x7d\xef\x6a\xb3\x60\x32\x00\xf4\x68\xdd\x0d\x2b\x67\x4a\x84\x5e\x5a\xdb\xdf\x2d\x8e\x89\xe1\xd4\x1f\x13\x59\x93\xa0\x41\x76\xbd\xe1\xe0\xad\xe5\x81\xdf\x73\x09\x72\x1b\x99\x03\x8d\xe8\x41\x96\x68\x44\x29\x51\x66\x28\x89\x95\x17\x4e\x06\xf5\x44\xb4\x25\x29\xac\xbf\xee\x46\xc2\xc1\xbb\xa3\xff\x70\xd5\x21\xf9\x87\x49\x98\x8b\xc7\x1f\x19\x4a\x3f\xea\xa1\xa7\xbc\x70\xf4\xdf\x74\x1c\xfd\xed\xa7\xff\xd9\xd7\x87\x19\x0b\x48\xb9\x81\x03\x39\x02\xe9\x3a\x3a\x52\xc1\x1c\x69\x70\x8e\xf4\x66\x8e\xb2\x7a\x1e\xd0\xaf\xa3\xfe\x52\x97\x05\xa2\x8e\x54\xd5\x47\xae\x9c\xa3\x2c\x9b\x2f\x40\x8f\x18\xde\x23\xae\x17\x01\xcd\x98\x6f\x06\x37\xe9\x48\x5f\xef\xa4\x47\x54\x42\x8e\x34\x36\x47\x1f\x7f\x3b\xf2\x84\xfe\xc8\x5f\xb0\x3a\x9a\xcd\x69\x49\x32\xa2\x82\x65\xbf\xf2\xbd\x15\xbb\xbe\x62\x15\x3b\x3e\xdd\xb3\x85\x07\x5f\xed\x4f\x66\xbd\x10\x5d\x0d\x99\x01\x38\xf2\x7c\xf4\x48\x91\x3d\x8a\x38\x16\x86\xb4\xea\x84\x63\x0d\x1f\x53\x9a\x7c\xd2\x53\x2e\x6d\xb2\x79\x92\xc7\xce\x9d\xaa\x9f\xec\xe0\x28\xe3\x13\x15\x28\x3c\x51\xe3\x86\x53\x06\x15\x9e\x9f\x3e\xca\xfb\xd3\x76\xb6\x03\x92\x8c\xe8\xce\xe7\x29\x7c\x51\x25\x91\xda\x93\x9f\xfe\xdc\x1b\x64\x4e\xa4\xc7\x9f\x3f\x3b\xf7\xab\x0b\x3f\xfd\x39\xf6\xcf\xce\x7e\x34\xe1\xa7\xf8\xa5\x13\x20\xdd\x68\x7c\xe8\x06\x5c\xe4\xec\x43\x37\xc5\xba\xf2\x91\xd3\xf6\x3f\x3f\xbd\x27\xfe\xf1\x9b\x59\xfc\xb0\x10\x63\xc5\x9c\xa5\xf5\xdb\xed\x05\x3f\x3a\xfb\x22\xeb\xcc\x21\x3b\xd3\x17\x84\xe1\xd2\xcd\xc9\xd9\x3e\xa0\xca\x49\x74\xf4\xcf\xfe\xa3\xa5\xb3\x7e\xa7\x64\x45\xc5\xef\x94\xce\x5c\x79\x67\xce\xc8\x99\x1d\x38\xfb\xd6\x7f\x72\x19\x9e\xb9\xe6\xce\xd4\x32\x67\x7a\x4d\x67\xce\xd4\x99\xee\xfb\x99\x87\xce\x67\x4a\xce\x99\x7a\xe8\xdc\xb9\xaf\x26\xcf\x5c\x94\x67\x5c\xff\x21\xd2\x3e\xea\x75\xec\x33\x4d\xd6\xbf\xf8\x59\x39\xdf\xa8\x5f\x3e\x37\x00\x2f\x89\x1a\xb6\x73\xc5\xfd\xce\x99\xf1\x9b\x33\x9d\x9f\x33\x9d\x76\xa0\x29\x11\x7b\xe0\xae\x43\x21\x6c\xb4\x81\x46\x8c\xdf\xfb\x00\xa9\x27\x7b\xe1\x71\xcd\x85\xb1\xc2\x0b\xbe\x56\x02\xd2\xe3\x8b\x8b\x18\xd8\x7e\x4f\xbf\x15\xb2\xf2\xbf\xf2\x0d\xb5\x89\x17\x44\x00\x81\xd6\xf0\xb4\x2f\xb2\x4b\x9f\x02\x6d\xf9\xae\x4a\xc2\x85\x91\xc1\x8b\x98\x8e\x3b\xa0\x21\x9f\x66\xfc\xac\xe0\xc2\x1f\x7e\x8c\x86\x33\xfe\xe0\xd9\x05\xba\x81\x28\xb3\x96\xbb\x4b\x36\x17\x8b\x7e\x87\x17\xae\xbc\x87\x71\xa5\xe1\xb8\x52\xfa\xae\xd4\x33\x57\x04\xa0\x0c\xc9\x54\x5d\x29\x5c\x57\x5a\xb2\xab\xfd\xe2\xc3\x00\xa4\xf6\x28\x96\x3a\x23\x7a\x61\x3b\x5a\x3a\x66\x57\x7f\x22\x77\xa5\x23\x72\xf5\x91\xd5\xab\x74\x61\x45\x84\x06\x96\xcc\x29\x5b\x75\xcb\xa9\x7a\xfb\xea\x77\xba\x57\xc6\xa3\xae\xdc\xdf\xc7\xa3\x8e\x2b\x2f\xdb\x5f\x7d\x70\xff\xca\xaf\x94\xae\x8c\x37\x5d\xdd\xe0\x4a\xfc\x40\x92\x03\xc2\x85\x23\xa0\x50\x93\x6e\x07\x06\x3d\xb7\x31\x50\x34\x24\xaa\x7a\xf6\x9d\x19\xbe\x94\x8c\x77\xf0\x03\xba\x63\x41\xa5\xed\x8d\x71\x2f\x3f\xfe\x7a\xaa\xf2\x37\xa0\x47\xfb\xcd\x46\xbd\xbe\xaf\x0d\xaa\x59\x79\x2d\x66\x47\xd1\xc9\x50\x10\xdf\x80\x66\xac\x62\xc6\x52\xb8\x8d\x0a\x84\x3f\x6e\x14\xc8\xce\x92\xc3\x30\x5e\x81\x86\x4c\xbb\xb1\x2f\xb6\x71\xdb\x4c\x55\x4b\x20\xd0\x60\x7a\x72\x9d\x78\x92\x7a\x32\xf4\x04\x4e\x95\xdd\x22\xb1\x19\x52\x0e\x39\x50\x52\x11\x41\x0b\x2b\x41\xf0\x04\x44\x5d\x3b\x25\x39\x8b\xba\x75\xbf\x60\x17\xf8\x83\xc8\x8e\xdc\x7d\x96\xd5\x10\xd0\x93\xbb\x78\x1d\xf8\x33\xcb\xbd\x58\x9a\xba\xa8\x7a\x87\x13\x97\x56\x95\xc0\x46\x2b\x81\xf7\xa1\x3f\x2c\xa9\xdf\xe3\xa0\xee\x84\x1f\xc5\xda\xa2\x0b\x49\x43\x3e\x44\x2c\x4b\x11\xce\xbc\x40\x62\xf4\x57\x7f\x12\x2a\xe3\xdb\xaf\xf6\xb6\xee\x3d\x13\xfc\xb0\x6b\x4e\x84\x13\xb0\x64\x60\x97\x1c\x92\x01\x45\x31\x8e\xf1\xc0\xb6\x41\x4a\x6a\x8f\xe8\x63\x46\x47\x3a\x19\x50\xaa\xe2\x8c\xf0\xfc\x37\x19\xd8\x6f\x05\x24\x03\xbb\x85\xa3\xe8\x87\x28\xbb\x64\x60\x3f\xdb\x9b\x0c\x4c\x19\x24\xb8\x64\x56\xb8\x66\xe8\x31\x78\x82\x0b\x64\x37\x5c\x77\xa9\xed\x0b\x14\xbd\x3b\x67\x20\x67\xea\x87\x21\xdd\x7c\x24\xa9\x59\xd4\x24\x75\xb7\xab\x12\xba\xd4\x09\x4d\x7c\x82\xef\x9d\xc7\x40\x0c\xe2\x05\xf2\x0d\x8d\x4d\xdd\x01\x55\x82\x26\x20\x83\x6a\x9c\x84\xbf\x49\xa8\x73\x37\x20\x8a\x69\x3c\x0c\x53\xfe\x48\x54\x13\xf1\x06\x4d\xbc\xb9\x19\x7f\x78\x34\x19\x9a\xe3\x90\xd8\x4f\x03\x5a\x45\xb9\xed\x2c\x02\x99\x32\xf9\xde\x37\xab\xe4\xab\x95\x6f\xc9\xdc\xa3\x1c\xe8\x85\xed\x5e\xb2\xac\x57\x9c\x9f\x31\x0f\xfc\xbd\x64\x68\x76\x3b\xa0\xd4\xca\x4a\x32\x0b\x58\x29\xd1\x59\x46\xe4\x2f\x05\xca\x2d\xec\xa2\xe4\x9e\x08\xd6\x5b\xc9\x73\x4f\x57\x6b\xc2\xcf\x69\xf4\x0b\x18\x45\xaa\xc7\x6f\x28\x90\x37\xec\xc1\x8d\x85\xe2\xe4\xaa\x2c\x2a\x1b\x51\xb2\x46\xee\xf7\x90\x94\xcc\x98\x3b\xb7\x1f\x88\x51\xa2\xc9\x53\xa6\xc1\x37\x0b\x68\xc6\xe2\xe6\x4c\x9b\xb3\xd4\x25\xdf\xd8\x1a\xb2\x81\x1a\xd9\xc1\xc9\xc4\x72\x9b\xee\x1d\xf1\xc7\x76\x48\xc6\x7c\xfb\x2f\xfd\x39\x16\xb1\x35\xe0\x6c\x4c\x32\x62\x51\x13\xeb\xaf\x29\x10\x1c\xca\x84\x61\x1e\xbb\xdb\x1f\xc9\xd8\xeb\x5f\x90\x47\x22\x55\x76\x63\xfb\x60\xa5\x10\x82\x0b\x44\xfa\x3b\x5d\xc9\xa4\x8b\x5f\x66\x28\xf9\x42\xa4\x83\x03\x82\x1f\x71\x8b\xd9\xb0\x81\x55\xf2\x49\x92\x41\x35\x4e\xf4\x47\x49\xb4\x00\xbd\x9e\x10\xc9\xd4\x93\xc2\xaa\x8f\xbb\x01\x25\x51\xdc\x27\xde\xee\x4f\x34\x42\x25\x24\xe3\x62\xcd\xec\xfa\xbb\x22\x7c\x53\xab\x64\xce\xdc\xb9\xf8\x6c\x2a\xe7\x2d\xd0\xa3\xcc\xd8\x4d\x4f\x25\xde\x54\x4e\x46\x61\xcd\x28\x0d\x99\x6d\x28\x13\xfe\x36\x52\x82\x5f\x37\xfa\x42\xf4\x83\xe8\xc4\xac\xd8\xcf\xe0\xc7\x7f\x45\x6f\xe0\x27\x87\xfa\x44\x88\xb2\x2b\xd1\xc5\x9f\x9b\xa3\x9d\xc8\x0f\xb3\xc8\x4f\x6a\x83\xd4\xee\x57\x88\x55\xeb\xa6\xbd\xf8\x31\xfa\xff\x07\x00\x00\xff\xff\xaa\x0a\xcc\xb8\xdf\x5e\x00\x00") +var _keysWordlistJapaneseTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x5c\xff\x72\xe2\xb8\xd2\xfd\x9f\xa7\x5e\xbc\x5c\x2f\x01\x3c\x0e\x71\x1c\xc7\x61\x58\x87\x8a\x2f\x43\x60\x80\x0c\x59\xb8\x93\x8f\x2c\x3c\x8c\x5f\xe4\x2b\xf5\xe9\x3e\xea\x99\xaa\x54\xea\x1c\x59\xd6\xcf\x56\x77\xab\x25\xd3\xf5\x93\xae\x3f\xe8\xfa\x45\xd7\xcf\xbb\x7e\xd5\x25\x45\xcf\x92\xca\xae\xdf\x92\x3c\x03\x8d\xba\xfe\xdf\x5d\x72\x03\x32\xee\xfa\x8b\x2e\xf9\x93\xef\x64\x5d\x32\x06\x9a\x76\xfd\x49\xd7\x6f\x8c\x58\x72\x11\x92\x93\x09\x79\xd9\xf5\x07\x44\x07\xa0\x4a\xfe\xaf\x40\x1e\xbb\x24\xef\xfa\x29\xc8\x53\xa8\xd1\x5e\x7d\xea\xfa\x19\xd0\xbc\xeb\x9f\x80\x9a\xae\x3f\x64\x86\x26\xfc\x25\x7d\xc7\x93\x51\xd7\xbf\x74\xfd\x21\xb9\x3e\x69\xd9\x8a\x56\xfa\xa4\xd5\xbd\xc8\x70\xfc\xa7\xeb\xe7\x7c\x78\xe9\x92\x91\x11\x57\xf4\xb2\xeb\xaf\x89\xf6\x92\x4d\x9f\x1c\x88\x4e\x1c\xb5\x13\xd3\x8e\x7e\x2c\x2e\x6c\xc5\xa5\xeb\xbf\x1a\x4a\x06\xd2\xa4\x9a\x5c\xeb\xbf\x76\x49\xd2\xf5\x77\x42\x42\x4b\x46\x5d\x1f\xe5\x84\x17\x58\x7f\x92\x76\xc9\x1f\x40\x37\x32\x8b\xb7\x5d\xff\x42\x5e\x11\xd5\x5d\xff\x91\xc4\x8f\x5a\x72\x23\x65\x44\x92\x5b\x5b\x42\x8d\x93\xae\xbf\xb2\xe1\x0a\x4f\x66\xcc\x99\x87\xa1\x30\x52\x58\xcf\x12\x99\x7f\x47\x0a\xa2\xaf\x26\x44\x81\x2c\x7d\x9e\xb5\x27\x3a\x00\x03\x88\x24\xda\x32\x08\x52\x29\x6f\x0f\x58\x3c\x50\x0e\x94\x89\xd8\x0e\x48\xd6\x2c\x24\xe3\x28\x0e\x28\xbd\x03\x59\x08\x8f\x44\x27\x96\x3d\xed\xfa\x6f\x98\x69\x21\x96\x5c\x60\x08\x74\x0d\x11\xb5\x3d\x5b\x44\x17\x11\xea\x81\x71\x7b\xaf\x82\x04\x0f\x44\xca\xff\xc3\x42\x1e\xbb\xe4\x2f\x4f\x72\x36\xeb\xa9\xeb\x5f\x0d\x25\x13\xa0\x19\x0b\x9e\x05\xe1\xef\xbf\x93\x8c\xfd\x13\xad\xe8\x2b\x2b\x9f\x77\xfd\xb4\x4b\x32\x56\x34\x97\x01\x8b\xcd\x7c\xf6\x48\x3b\xd5\x48\xc5\x37\x24\x57\x43\x41\x16\x12\x90\x85\x8c\x75\x4a\xf2\x48\xf4\x4a\xf4\x46\x74\x32\x94\x8c\xfc\x10\xb4\x10\xe6\x41\x5c\x83\xd6\xec\x17\xdf\xe3\x17\x74\x83\xa4\xf1\xd9\x16\x44\x4b\xff\xc2\xbf\x7c\x61\xd9\xf5\x1f\x0c\xd9\x7b\xaf\x7c\xba\x82\x70\x0e\x28\x7f\x40\xda\xac\x6d\x97\xfc\x41\x21\xda\xb1\xb2\x1d\xa7\x6a\xcf\xf9\x7f\x73\x69\x56\xcd\x3b\x27\xe4\xc0\xb4\x23\x87\xf9\x27\xd3\xce\x6c\xce\xd5\xd2\x82\xbc\xa6\x50\x8f\x20\x8d\x89\x42\x92\x58\x8b\x12\x91\x7e\xad\x36\x10\xac\x92\x64\x28\xfa\xb3\x20\x41\x7d\xa2\x19\x88\x6a\x96\x3d\x12\x6d\xb1\x30\x12\x85\x32\xe1\x1a\x0b\xda\x8b\xeb\x27\x89\x55\x66\xa2\x87\x8b\xae\xff\x8f\x0d\x43\x50\x08\x03\xa2\x94\x28\xb6\x27\x37\xb9\x08\x02\x9f\xb2\xa8\xa2\xeb\xdf\xd9\xca\xef\x33\xa9\x64\xb9\x85\x08\x48\x6c\x5b\x21\x3d\x0b\x24\x95\xf5\x90\x19\x92\x02\x53\x91\xce\x07\x20\xed\x46\x2a\x4b\xe5\x44\xf4\xc1\xac\x59\x97\xe4\x40\xb9\xe9\xcf\x35\xf9\x04\xe3\x9e\x8a\x5a\x68\xa4\x7d\x39\xdf\x9c\x8a\x0c\x4f\x49\x56\xee\x49\x18\xb1\x96\x44\x93\xef\xa9\xe5\x41\xb4\xde\x02\xc3\x93\x4a\x8f\xbf\x00\x55\x22\x88\xa9\x91\x30\xd8\x13\xac\xc5\x54\xa6\x6f\x40\xf4\x85\xe8\x96\xb3\x2c\xdc\xf4\x7b\x2a\xab\x49\x1b\xb3\xa0\x16\x27\x9f\x70\x00\x16\x1c\xc9\x05\x17\x6a\x2a\x0b\x6a\x0c\xa9\x4b\xa5\xc7\x39\x55\x48\xaa\x2b\xd2\x8d\x7c\x4b\xf4\xca\x6e\xad\xd9\xca\x35\x74\x05\xd0\x13\x47\x60\xcd\x97\xb6\x44\x3b\xd6\x7f\xea\xfa\x77\x44\xf7\x30\xed\xa9\xcc\xc5\xc4\x72\xc7\xbe\xca\xd2\x01\x12\x1b\x69\x64\x68\x95\x85\x31\x9a\x88\xd4\xd4\xe4\xba\x04\x40\xd6\xd6\x37\x51\x78\x56\x77\x20\x99\x49\x43\x32\xa6\x57\x93\xca\x4a\xa9\x1c\x49\x52\x1b\x46\xd7\xbe\x0c\x9a\x26\x95\xb1\xcf\x88\x4a\xa0\x82\xf6\x05\x64\x61\x43\x07\x3b\xe9\x88\xea\xae\xa1\xc8\xe9\x10\x4f\x40\x26\x44\x19\x97\x0a\xf8\x3d\x91\x6a\x55\x90\x93\x7b\xdb\x96\x13\x48\x0e\x34\xc2\xa4\x0f\x65\xbc\x22\xd2\xa7\x99\x4c\xbc\x16\x17\xdd\x82\xa1\x88\xeb\x9f\xcc\x56\x77\xfd\x25\x50\x2b\xae\x85\x56\xb9\xeb\xfa\xb7\x40\x67\x9d\x4c\x19\x15\xe1\x96\x87\x69\x61\x4e\x1f\x89\x76\x40\x37\x56\x79\x40\x27\x20\xb5\x50\x50\x4b\x1c\x9d\x40\xc6\xcc\x5d\x40\x18\x87\xaa\x75\xac\x8a\xc2\xfc\xc0\x94\xfc\x2b\x56\x0d\xc8\xdc\x7a\xa4\xf3\xf3\x97\xcf\xb9\x42\xce\x91\x8c\xeb\x98\x4b\x7e\x64\x5e\x42\x4d\xa2\x82\x32\x32\x0b\x98\x83\xa4\x6c\xee\xc8\x14\xc1\x85\xe4\x91\x68\xc6\x7a\x52\x8e\x3e\xc8\xd1\x17\xf5\xe1\x9e\xd8\xcc\x8e\xb8\x48\x47\x74\x94\x46\x34\xe3\x40\xaf\x9c\x73\xe1\x09\xf3\x84\x42\xe6\x20\x63\x0c\x34\xc9\x13\xd0\x04\x2e\xa8\xa4\x05\x15\xa9\x19\xbe\x50\x8d\x8d\xe8\x7a\x8d\x44\x5c\x62\x0f\x73\xef\x0d\x09\x57\xaf\x73\x4d\xce\xd7\x6c\x45\x8d\xfc\xb0\x16\xbe\x92\x82\x19\x4a\xdf\xe3\x92\xeb\x5a\x88\xe9\x8b\x11\x66\x04\xeb\x1a\x24\xbe\xf3\x08\x49\x01\x2a\x39\x3d\x22\xde\xf6\xc2\x5c\xc4\x2f\x27\x89\x8d\x6d\x68\x7b\x40\x34\xcf\x33\x9c\x7d\x90\x85\x97\x81\x17\x18\xe5\x91\xac\x14\x1d\xbf\x6f\x10\x27\x90\x95\xd4\xad\x2b\x00\x7c\xed\x25\xea\x95\xaf\xbd\x8a\xc2\x19\x73\x84\xde\x7c\xfb\x2f\xb0\xf5\x42\x92\xbe\xd4\xb1\xb2\xe1\x4b\xb0\x0d\xfc\x46\x12\x93\x29\x6e\x81\x84\x0d\x21\xc8\xc0\x44\x32\x19\x88\xe6\x7b\xef\x99\xc0\x7c\x5a\xf5\xb2\xec\xb1\xb7\x1c\x49\xc3\x34\xb9\xa0\x3a\x01\x99\xb2\x06\x2c\xc6\x3f\x49\x66\xd6\x78\x29\xc7\x93\x68\xa8\x46\xa6\x1f\xb5\x98\x31\x76\x70\x40\xaa\x1f\x27\xd0\x8f\x44\xea\xde\x4f\xbc\x87\x3f\xf6\xbb\xe2\xb1\x2e\x5a\x69\x0b\x48\xed\x1d\xab\xb1\x77\xb8\x41\xfe\x86\xf1\x23\x6f\x7d\xb1\x4b\x9f\x73\xe5\x9f\xe8\x02\x9e\xa8\x73\x28\x8d\x1c\x7b\xff\x70\xec\xf5\xf4\xc4\xfb\x74\x63\x2a\xed\x31\xc5\x77\xcc\xa5\x3c\xfe\x2d\x79\xc2\x96\x4f\xb0\x39\x1c\xd3\xb5\x18\xcb\x62\xbc\x27\x5a\x31\xeb\x03\x5e\x9f\xa0\x7b\x48\x6b\x58\x7b\x03\xf3\x39\xf1\x8a\x71\x22\x02\x9d\x71\x7a\xc0\x0b\x4f\x4a\x8e\xfe\x8b\xf7\xef\xc6\x22\xd6\x0f\x62\x1f\xb5\x7d\x3b\xbe\xb6\x67\x93\x4e\x58\x45\x63\x3f\x40\x67\xb6\xfe\xc2\xb4\x8b\x48\x22\x46\x3d\x2c\xfb\x09\x37\x92\x63\x11\x58\xf4\x41\x06\x16\xd2\x3b\x76\x03\x9b\x8c\x89\x32\x2b\x31\xb4\x2b\x37\x24\x1b\xa5\x09\x4c\x0c\xd2\x0a\x27\x81\xce\xb0\x8f\xbd\x54\x8f\xcd\xa4\xc4\x27\x0d\xdb\x54\xd8\x68\x06\xa4\x1b\x8b\x0c\x01\x1a\xa2\x16\x28\x78\xe1\x3d\xd1\xb2\x03\xbc\x9e\x49\x2f\x06\x86\x2c\x6d\xc8\x52\x54\xdf\x03\xe5\x44\x0b\x43\xf6\xc6\x98\xa5\x8c\x99\xef\x97\x2e\x64\xf2\xb7\x04\xca\xa5\xa1\x23\x23\x61\xfc\xee\x40\xa6\xba\x7e\xad\xb4\x82\xf5\x17\xbe\x59\x05\x2b\x29\x99\xb5\xf4\x69\x17\x43\xa1\xec\x2f\xe8\xf3\xa3\x97\xe7\x2f\xdc\x6a\xe3\x49\xe3\x17\x38\x92\x36\x7e\xa3\xf8\xc5\x36\xe4\xad\xef\x52\xcd\xe6\xc5\x26\xeb\xc6\x3a\xa3\xf9\xcd\x38\x75\x99\xac\x87\xdc\x90\x0d\x5e\xe3\xbb\x16\x97\x44\x26\x95\x0d\xd9\xa4\x17\xec\x89\xf9\xa4\x65\x45\x6d\xd7\xdf\x02\x2d\xd9\x8c\x57\x16\xf2\xca\x2a\xd7\x7c\xba\x86\x82\x03\xd2\x66\x7c\x17\x6f\xb9\x02\xd9\xb2\x75\x3b\x16\xb4\x93\x31\x6b\x40\xf6\x2c\xf5\x9d\x46\x25\xe3\xde\x35\xa3\x86\xca\xe8\x39\x66\xb2\xb2\xb4\xac\x33\xd3\x2e\xec\xfa\xd5\xc6\x2b\xf9\x43\xe3\x7a\xb1\x60\xb3\xc0\x08\xce\x3c\x8b\x25\xaa\xc8\x17\x3d\x1f\xb6\xc9\xe8\x50\x66\x62\x70\x30\xdf\xa2\x59\x64\x56\xf5\xc9\xd0\x1a\x23\x03\xee\xa3\x0d\x19\x97\x74\x46\x7b\x9d\x49\x06\xb4\xd9\x36\xbb\x40\xda\xe6\x8c\x15\x65\xcc\x97\xb3\xdd\x5f\x10\xf1\xc2\x02\xcc\xcc\xc7\xd4\x98\x12\x78\xf0\x6a\x8c\x38\xfd\x72\xcb\xb5\x9c\x23\xcc\x03\x94\x72\x9f\x0c\x92\x11\xdd\xfa\x64\x5d\x40\xb7\xe6\x0f\x0e\xf8\x64\xee\x9f\x34\xd0\x4c\xb9\x77\x0e\x41\x3e\x81\x62\x5d\x71\xbb\x90\x63\x1b\x8e\x42\x0a\xa6\x95\xac\xa5\x64\xb3\x4a\x46\xc9\x84\xc8\x90\xe4\xe6\xfa\x5f\x49\x62\xc1\xb5\x88\x5b\x66\x24\x8c\xbd\x8e\x87\xec\x1d\x44\x5f\xe4\xb4\xf4\xb7\xb6\x80\x97\x7c\xe7\xd9\xd7\xd3\x04\x29\x35\x67\x30\x17\x47\xaa\x60\xbd\x0b\xdf\xd0\x96\x32\x7e\x2b\x2b\xae\xc6\x8a\x93\x27\x61\x8a\x6f\x7b\x66\xea\x52\x9a\xe7\x9c\x6b\x2c\x97\xbd\xa9\xa6\x6d\xf1\x1f\x64\xc7\x9e\x1d\x89\xae\x7e\x73\x0d\xde\x30\x44\x1a\x45\x27\x87\x10\x63\x80\x7a\xa6\x30\x6b\xa2\x0f\x66\x1b\x43\xf1\xe5\xae\xab\x66\x87\x72\xd8\x47\x4c\xcd\xad\xca\x9f\x8e\x5d\x8c\x97\xe4\xe4\x8d\xcf\x19\xd4\xf6\x54\xc4\x70\x0d\x34\xa0\x9e\x9f\x7a\xbd\x09\x12\x91\x7a\x45\x77\x2e\x9e\xd9\xf2\xa1\xd6\x70\x67\xe1\xb2\x54\xb2\xf0\xe5\xb0\xb2\x32\x12\x45\xf0\x62\x6b\x23\xc9\x88\x6b\xfe\x0e\x26\x87\x48\x05\x13\xe4\xd9\x93\x85\x27\x2b\xb6\x30\xa8\x34\x43\xa6\x34\xee\x28\xd6\x77\x76\x16\x12\xb7\x1e\x77\xc1\xe9\x90\x2e\x4c\x29\x40\x92\x66\x7d\xa8\xd8\x81\x2a\x68\x56\xd9\xf0\x4c\xbd\x98\xdf\x31\xb2\x86\x68\xd1\x1b\x90\x9c\x9e\x04\xd9\xfb\x1f\xf9\x0d\x3b\xdd\xd2\x9e\x4f\x79\x46\x31\x55\x43\x61\xd5\xbd\x30\x46\x84\x27\xaa\x58\xa6\x16\x29\x8d\xd9\x96\xbe\x80\x0b\xc7\xa2\xf5\xfa\x07\x7c\xe2\x72\x9a\x82\xbb\xa3\xdc\x4b\x34\x2b\xac\xf0\xba\xe7\x43\x5b\x53\x31\x2f\x77\x44\x35\xd1\x15\xe8\x3b\x87\x6d\xcb\x4e\x6d\xd9\xf4\x3d\x25\xe4\xc0\xb4\x13\x7d\x8d\x3b\x31\x27\x5a\xbb\x1e\x01\x4c\x65\x11\x8d\xad\xf6\x60\x47\x2a\x43\x9a\xc1\x04\x66\x4a\x1d\x3f\x95\x45\x32\x35\x21\x73\xeb\x64\xca\x63\x8a\xa9\x86\x08\xb4\x91\x81\x8c\x88\x20\x75\x01\x65\x4c\xbb\xb3\x16\x3b\x9f\x6e\x6a\x61\xca\x9c\x24\xc6\x10\xc0\x6b\x93\x0c\xe7\xf0\x4d\x75\xe7\xe2\x5e\x5b\xfa\x56\xad\x7c\xb6\xb5\x7f\xb2\xb1\x79\x0a\xe4\xe4\x1b\x7f\x21\xba\xba\x86\x06\xa3\xca\xb7\x2d\xfa\x02\x12\x7a\x5b\x88\xec\xe5\x78\x5b\xac\x59\xff\x3b\xd1\x3b\x24\xf9\x9e\x1e\x65\xe1\xc3\x14\x85\x86\x59\x1d\x51\xf5\x73\x6f\x51\x55\x1d\x87\x7b\x0b\x8f\xc6\x32\x74\xf8\x0a\x0b\x75\xc4\x27\x8f\x44\x1a\xe3\xbc\xf7\x76\xae\x30\x3b\x97\x93\x34\xfe\x89\xee\x4a\x0b\x0b\x54\xc6\x4a\x96\x3e\xdb\xab\x7f\xb2\xf6\x4f\xf6\xbe\xd2\xb3\x6f\xff\xc5\xf5\x34\x48\x1c\x5b\x90\x8c\x30\x0d\xd1\x9d\x2d\xb8\xf5\xba\xa7\x6c\xdf\x8b\x9f\xda\x5a\x9a\x95\xa5\xbb\xad\xc2\x9b\xd9\x82\xf6\x88\x64\xed\x9f\xec\x59\xf9\x2d\x27\x2e\x8e\xee\x94\x6d\x28\x44\x09\x93\xc8\x62\x28\x10\xfb\x00\xaa\xd8\xf0\x9a\x95\xc5\x81\x56\xb5\x12\x0f\xed\x20\xbf\xcf\x30\x1e\x85\x1f\xf9\xc6\x77\xbd\x61\xa9\xd1\xf1\x2d\x10\x43\x06\x6a\x79\x6e\x06\xf2\xc6\xe2\x5b\xc4\xf1\x0a\x3f\x5d\x4b\x3e\x5d\xc9\x96\xe8\x86\xa4\x22\x7a\x33\x64\x42\xbd\x96\x61\x5e\x83\x6c\xf1\xbf\x67\x23\x72\xe1\xa8\xed\xa0\xb6\x04\x25\x43\xcc\xcd\x9e\xf5\x1d\xa0\x6a\x41\x8e\xec\xc8\x91\x19\x3e\x69\x95\xef\xa5\xd4\x78\xfc\x2b\x07\x19\x6e\xea\x2f\x74\x3b\xf0\xa4\x65\xe3\x2e\x36\x6e\x41\xb3\x7d\x81\xa9\x2d\x18\xef\x2c\xe8\x0b\x17\x54\x73\x82\xb4\x09\x66\xd6\x80\xd0\xab\xe0\x55\xa5\x44\xef\x40\x43\x1b\x4f\xf3\x91\x0b\x31\xb5\x5a\xf5\x24\x7a\x6b\x56\x70\x26\x33\x36\x05\xc9\xa5\xf2\x25\xc9\x84\x6f\x16\xdc\x78\x16\x3e\xca\x5a\x50\x77\x16\xbf\x29\xc5\xc2\x94\x62\xcc\x46\x89\x82\xea\x73\xa5\xad\x3d\x79\xef\xfa\x1b\x92\x7f\xfd\x93\x0b\x1b\x5a\x20\x64\x09\x34\x71\x95\xd8\x96\xfd\x41\xc3\xe6\xd2\xb6\xd2\xdc\x9e\x01\x89\xda\x41\x64\xbb\xf3\xa4\x60\x1e\x75\xda\x4a\x1f\x50\x7f\x30\x07\x28\x56\x12\x03\x53\xa5\x77\x64\x1f\x7e\x3b\x68\x2b\xa1\x84\x80\x34\xda\x04\x32\x81\x79\x45\x72\xcc\x70\x85\x40\x94\x3c\xfc\x2b\x65\x2f\x12\x8b\xcb\x59\x42\x4e\x3b\x5b\xc2\xb5\x04\xd2\xbd\x76\xc9\x75\x58\xfa\x4b\x17\x0f\x5c\xfa\x25\x83\x12\xa5\xf9\x23\xda\xd7\x96\x9a\xff\x81\x2b\x1b\xc9\x13\x96\xfd\x62\x1b\x8b\x9c\xd9\x2a\x16\xf5\xe8\xdf\x9e\xb3\xe9\x2d\xbd\xa6\xd2\x1c\x98\x41\x97\x24\xe0\x4b\x4e\xd4\xca\x27\xaf\xf8\xf6\x8a\x31\xeb\x92\x0a\xa2\xa4\xeb\x52\xd2\x65\xc7\xd6\x45\x9b\x19\xf7\xba\xa5\xc4\xcd\x75\x3c\xce\xcc\x7a\x46\x2c\x0f\x07\xfc\x3a\x21\x57\xff\xd2\x55\xdc\xd1\x89\x90\xb0\x8a\xa7\x3d\x1f\x60\x2e\x65\x69\x0e\xfd\xd9\x4d\xc9\x35\x5a\x72\x3d\x96\x8c\x28\x22\xc2\xf1\xdc\x43\xcc\x4d\x46\x07\x03\x92\xe4\x8c\x1c\x97\x8c\x33\x97\x7e\x0d\x96\x74\x5e\x80\xe2\xb6\xb9\xf4\x5e\x4b\x69\x5e\x0b\x66\xd3\x36\x0b\x7c\x52\xfb\x6c\x33\xeb\xa7\xf8\x2f\x44\x0b\xa2\x0b\xd1\xd5\x90\x39\x1a\x15\x37\xba\x15\x0f\xd2\x2a\xbb\x07\xf4\x82\x65\x5f\xf9\x2d\x93\x84\xe2\xa5\xc1\x15\x3b\x55\xc1\xb2\xf7\x34\x36\x6f\xc5\x8d\x30\xd0\x15\x17\x70\xc5\x1d\xcc\x23\x2d\xac\xb8\xe9\xe2\xc5\x54\xec\xd6\x23\x6f\x3d\x54\x22\x6d\x29\x0b\x6a\x10\x58\x02\x5a\x12\x5d\x81\xa2\x35\xab\xec\x2a\x83\x56\x11\x8f\x47\x2b\x9a\x0c\x41\xa6\xa8\x2b\x0a\x6f\x45\x3d\x00\xd4\xa2\x41\x6a\xe4\x1e\x29\x22\x38\xfd\xfd\x02\xb1\x12\x62\xea\xbf\xa2\x5a\xac\xc4\xb4\x5d\x0c\x59\x9a\x1e\xac\x01\x9d\x80\xf6\xac\xfd\xcd\xb7\x55\xaf\x2f\x08\x32\xdf\xb9\xa2\x09\xac\x44\x7b\xc4\x3e\x1f\x39\xba\x27\x66\xf8\xc9\x97\xce\xcc\x77\xe6\xd3\x0b\xd3\xd4\xcc\x55\xf4\x4e\x2b\x2c\x15\x24\x3f\xc2\xaf\x87\x0c\x56\x74\x5a\x2b\x2e\xa2\xca\x0d\x65\x10\xe9\x81\x27\xa9\x27\x23\x1b\xc9\x40\x26\xd4\x13\xd5\x6f\x3b\x6e\x3d\xa1\x74\xcd\x0e\x7c\xea\x4b\x8a\xe8\x81\xcd\xf9\x93\x57\xe7\x40\x66\x9e\xcc\x7d\x51\x8d\x7f\xc7\x8b\x8e\xee\x04\x33\xdf\xce\x8b\x3d\x89\x42\x25\x27\x4c\x28\xe3\x91\xea\xe2\xd1\x42\x5e\xb1\x17\xff\xf1\x2e\x21\x9e\xc7\x16\xfe\xc7\xef\x0f\xc1\xaf\x86\xc2\x7c\xbf\xd9\x3b\x1a\x68\xd6\xd7\xfe\xb2\x3b\x12\x03\xf2\x9c\xc6\x0d\xfc\xc5\x0f\xd6\x5f\x4e\x6c\x83\x0b\x91\x98\x58\x85\x3a\x66\x9c\xc1\x18\xd8\xa8\xa8\xa7\x2a\xaf\x97\x1e\x2d\x68\xf6\x27\x9f\xcc\x10\x68\x20\x5f\xb0\x11\x05\x07\xab\xa6\x6e\x01\xaa\x88\x82\xd1\x7c\xc2\x9d\xb2\x9e\x9e\xdb\x98\x06\x01\x19\x13\xa9\x15\x79\xf2\x07\xe3\x3c\xe8\x51\x3f\xaa\xb6\xfb\x24\x39\xc9\x23\xba\x5a\xeb\x26\xc5\x5e\x8b\x67\x71\x35\x22\xa2\x40\x7a\x27\xa6\xf6\x3e\x7d\xcd\x55\x50\x8b\xb2\xd2\xb4\x02\xfd\x78\xe2\x21\x49\x2d\xa4\x62\x86\x1a\xe1\x87\xda\x5f\xf4\xa8\xbd\x2e\x7a\xb2\x53\x95\x48\x56\xc8\xa3\x1a\xa8\x66\x64\xaa\xe6\xb5\x0b\x04\xe9\xb4\xbe\x3d\xcc\x50\x2d\xb2\x71\xc3\xca\x9f\xbc\x5e\x78\x92\x6d\xe8\x77\x28\xaa\x5a\x86\x4e\xbb\x7d\x64\xda\x07\xb4\x69\xcd\xf9\x7f\xe2\xba\xab\xc5\x8b\xd6\xfa\x2e\xd6\x39\x0b\x05\xd7\x3c\x81\xac\x65\xfd\xa2\xd5\xb8\xbf\x24\xce\x4c\x1d\x2c\xa4\x6c\x67\x6a\x59\x2e\x72\x99\xc5\x5e\xc8\x5c\x9f\xcd\x5c\xd6\xfe\x16\x62\xad\xae\xa4\xbc\x30\xf3\xfe\xfb\xcc\x3c\xc3\x96\x44\x9d\xc1\x28\x90\x33\x7f\x1c\x37\xe3\xc1\xca\xcc\xbc\xb8\x31\x5f\xc8\xb8\x6f\x9f\x21\x16\x4e\x94\x12\xe1\x84\x34\x65\xb6\x29\x51\xc1\x72\x6b\x56\xac\xda\x05\x68\x0a\xf4\x42\xfb\x37\x33\x0d\xa3\xc6\xff\xab\xf0\xf8\x24\x96\xfd\x42\x17\x70\xa6\x07\x72\xb2\xcc\x21\xb0\x33\x31\x66\x7f\xf3\xcd\x96\x61\x37\x90\x6f\xbe\x98\x1f\xfe\xc9\x3b\xd1\xc9\x25\x9b\x5a\x07\x19\xb1\x5e\xbd\x6f\x37\x13\xd1\xd3\x57\xf7\x50\x4e\x33\x89\xf2\x66\x40\x9f\xd8\xc4\xcd\x28\x28\x33\xda\x95\x19\x97\xc0\xcc\xdf\x96\x9b\x49\x35\xc7\x1e\x66\x1c\xb1\x0e\x24\x17\x56\x82\x06\x81\x22\x19\x13\x65\x50\xb2\x20\xf1\x3d\x15\x04\x94\x78\xcf\xe4\xd2\x17\x12\x34\x2c\x49\xed\x9f\xcc\x3c\xf9\x9b\xa8\xf1\x35\x44\x73\x31\xf3\xb1\xa1\x99\x8f\x0d\x81\x68\xb4\x0d\x64\x6b\x63\x1d\xc8\x0f\xbc\x83\x56\x9e\x88\xfe\x75\x6f\xab\x1c\x22\x4a\xe4\x8e\x2b\x90\x94\xb8\xd2\x6c\x9b\x09\x92\xfa\x32\x54\xfe\xbf\xc2\xed\x23\x1a\x51\xf8\x66\x7e\x2f\x06\x12\x9a\x3c\xe7\x6c\xcc\x4d\xff\xde\x61\x06\xc1\xb7\x3d\xbd\xbc\xaa\xc7\xa0\xf1\x8c\x62\xce\xc3\x11\xa0\x7b\x22\x35\x7c\x20\xcf\x9e\xac\x3d\x79\x37\x24\xdd\x26\x19\x01\xc5\x2b\x46\x73\xc6\xba\xe6\xbc\xc9\x31\xe7\x8d\xa1\x39\x57\xe6\xdc\x42\x23\x9a\xf5\x81\x59\x2b\x98\xa0\x39\xa7\x7d\x4e\x23\x31\x97\xbf\xdb\x1e\x63\x2a\xec\x7c\xcb\x52\x5b\xdf\x80\x17\x6a\x14\x3c\xf9\xe2\x07\xe4\x05\x71\x5c\x92\xc2\x3f\x99\xf9\x32\x56\x40\x2b\xde\xfa\x03\xf9\x2f\x26\x6f\x2e\xab\x71\xc8\xb6\xac\x71\x70\x32\x17\xe7\xef\x13\xe8\x93\xd3\xf6\xc9\xa9\xbc\xb0\xf2\x8b\xbd\x1b\x3c\xba\xdc\x50\x58\x86\x43\x90\x3e\x33\x24\xf8\x0f\x22\x97\x56\xfb\x5f\x7b\x76\xa1\x46\xef\x81\xce\x79\xdc\x31\xf7\xf1\x85\xb9\x3f\x65\x07\x79\xf0\xa4\xb2\xf6\xc8\x2a\x63\x43\x7e\x59\x5b\x7f\x23\xaa\x40\x74\xb2\x61\x72\x31\xd4\x86\x1b\x18\x1c\x46\x0d\x98\x3c\xa0\xb2\x6e\x7c\x48\x01\x44\x4d\xc1\x33\xae\x9d\xa0\xfa\x86\x37\x4f\x80\x6e\x91\xe7\x97\x53\xea\x86\x91\x06\x20\xed\xd3\x73\xe7\x2e\x8c\x63\x35\x3f\xdb\x4d\x94\x58\xa0\x9e\x4d\x83\xcc\x7d\x0b\x1a\xdf\x85\x38\x00\x3c\x5f\x8b\x75\xbc\x32\x50\x88\x87\x6b\xff\xe6\xd6\x57\xb0\xf3\x65\xe8\x86\x01\x65\x1c\x7e\xab\xe0\xe8\xc9\x4f\xdf\xd1\x33\xd1\x45\x03\x81\xb2\x5c\x90\x74\x95\x79\xb8\x35\x2e\xca\x0a\xa8\xef\xca\x48\xfc\x98\x9a\x32\x02\xb9\x21\x1a\x31\x0c\x01\x3e\x26\xca\x59\x54\x0a\x01\x8d\x91\xcc\x46\xa6\xb1\x36\x14\xd3\x2c\xfa\xd5\x50\x1a\x81\xb6\x40\x19\x64\xaa\xb1\x73\x51\x2d\xbf\x60\x03\x0a\xdf\xe8\x92\x25\x54\x3c\x68\x7a\xd6\x6d\x81\x98\xb0\xc6\x7b\x88\x8d\x39\x84\x39\xf9\x1c\x9f\xda\xf4\xf4\x43\x18\xfb\xae\xa5\xa1\x49\x69\xa4\xc0\x8a\xf5\xe8\x86\xb6\xc1\x15\x7d\x8c\xf8\xb3\x79\x0f\x03\x92\xe8\x3d\x80\x17\x44\x15\x4f\xfd\x9e\xed\xf2\xaf\x16\xbd\x64\xab\x56\x7e\x18\xd7\x52\x4f\x03\xb2\xe1\x88\x7c\xe7\x20\xe0\x16\x82\xb6\x6a\x4f\x29\x3b\x31\xeb\x07\xcb\xfa\x64\xf7\x2e\xd0\xfc\x0d\x55\xce\xb3\x28\x1a\xe4\x13\x57\xc3\xca\x0f\xa4\xee\xf9\x0f\x5e\x1a\xee\x51\x1a\x5c\x9c\xb7\x2e\x24\x6c\xb5\x1d\xd0\x35\x7a\xef\x57\x76\xb5\x30\x46\x96\x1a\xc5\x3c\xa1\x7c\x24\x63\xa8\xd8\xc6\x89\x49\x02\x0b\xa6\xc9\xd1\x2b\x6d\x64\x1e\xff\x60\xce\x67\xf3\x51\xb4\x61\x05\x5b\x55\x70\x5f\xdb\xd0\x47\x69\x18\x62\x6d\x54\x19\xba\x0c\xf7\x44\xa5\x4f\xa6\x0a\x79\x67\x75\x33\x5f\xc9\xdc\x44\xc6\x9d\x17\x3f\x33\xdc\xd3\x78\x67\xa4\xf1\xce\x08\xf2\xac\x99\xbc\x31\x41\x86\x5b\xe2\x3a\x44\xb5\x91\xc8\x67\x03\x2e\xdb\xa7\x7f\x72\x71\xef\x98\xdb\xf8\x6c\x8e\x44\x4b\x92\x11\x85\x66\x2f\xa8\xac\x17\xdc\xf3\x2d\x28\x07\x0b\x3b\xbf\xd6\x0c\x43\x66\x18\x33\x6d\x0c\xad\xb1\xf0\xa7\x57\x0b\xee\xd5\x17\x76\xce\xfd\x64\xc4\x92\x75\x71\x2f\x7c\xf9\x15\xab\xad\xbc\xb0\x2c\x38\xe4\x0b\x6a\xe9\x05\x07\x7b\xc1\x88\xeb\x42\xbf\xb1\x49\x34\x39\x1e\xfa\x2e\xb8\x81\x5b\x30\x70\xb4\xe0\x72\x12\x24\xbe\xcc\x82\xa3\xbd\xf0\x4a\x79\x81\xa0\x0d\xdd\x82\x05\xf7\x62\x0b\x19\xf7\x06\x48\x6f\xee\x00\xbd\x62\xa8\x17\xb6\xae\x5e\x7b\xfc\x22\xd0\x8e\x5b\x3e\x7a\x8c\x78\x5b\x57\x92\xd4\xab\xde\x85\xc9\x5e\x45\x82\x08\x35\x87\xd1\xbe\x55\x03\xba\xf6\x34\xca\x66\x77\x13\x17\xbf\x0e\x63\x58\x69\xda\x8e\xdc\xe6\xdf\x89\xed\x42\x9d\x58\xa9\xbb\xe5\x66\xbf\x35\x83\xb8\x00\x49\x99\x9c\xfa\x9b\x00\xad\x1e\x06\x4a\xcb\x5a\xdc\xd5\xef\xf9\xef\x06\x05\xd9\xc2\x6d\x79\x2d\xa4\xe5\x65\xe5\x16\x27\xdf\x86\x2c\xed\x9e\xaf\x47\x4b\xd3\x06\xf7\xcb\xda\xa9\xe1\x43\x41\x62\xf3\x5a\x09\x60\xf7\x99\x75\xcd\xb8\x7f\xcb\x73\xf7\x56\x56\xd9\x7f\x59\xdf\x8e\x19\x4e\xd0\x62\xf8\xa6\x31\x7e\xda\xd0\x52\x6b\xb6\x32\xc1\x59\xcf\x36\x68\x8d\x65\xb0\xef\x8c\x80\x90\xd5\x8e\x91\x5a\x19\xfd\x4f\xa2\xab\x35\x5f\x4f\x8a\x76\x24\xa1\x84\x25\xa3\x32\x40\x4b\xa2\x2b\x50\xfc\xb2\x6f\xc9\x89\x5a\x72\xe1\x2e\xd5\x43\x92\x9a\x97\x76\x51\x37\x27\xd1\x2b\x29\x4b\x1e\x9d\x2c\xfd\xc1\xcc\xd2\x7b\x40\x4b\x4a\xef\xd2\x3c\x9a\x98\x1c\x97\xc8\xd2\xbb\x2a\x20\x9f\x7c\xa2\xb1\xe8\x25\xef\xa3\x83\x64\x54\x86\x4b\x91\x86\xa0\x61\xbf\xe9\x29\x61\x5f\xcb\xf9\xe5\xa0\x06\xfc\x0e\xa8\xe6\x48\xcd\xf9\x74\xc1\x4d\xc7\xd2\x7b\x6d\x4b\x7f\xcc\xb2\x34\xe9\xc9\x50\x5d\xd8\x88\x33\xf9\xd3\xbd\x20\x6a\xe4\x9b\x68\x89\x31\x3c\x9d\x25\x55\x06\xd0\x2d\xeb\xda\xc9\x58\xdc\xf4\xec\x33\x57\x4d\x3e\xe1\xf2\x11\xc8\x11\xa1\xa1\x25\x8e\x47\x58\xce\x99\x63\x76\x61\x2d\x17\x19\x9c\x27\xce\xcd\x15\x01\x7a\x23\xc1\xfe\x62\x14\xcc\xe4\x2e\x45\xcb\xbf\x03\xe5\x88\x6f\x00\x35\x28\xe4\x9b\x37\x94\x4b\x7f\x00\xb2\xf4\x9b\x84\x25\x2d\xe4\x92\xbe\xe4\xd2\xdb\x4a\x90\x7b\x1b\x4a\xb7\x8b\x07\xa9\x88\xf4\xe8\xe0\x1b\x6d\xe1\xd2\x6c\x61\x2c\x9e\xd3\xef\x2e\x6d\x80\xfc\xcf\x46\xd3\xec\x1c\x4f\x20\x96\x66\xe0\xd8\x13\x0d\x04\x69\x17\xbe\xd9\x66\x5a\x95\xe8\x37\x1a\xbb\x57\x1a\x3b\x1c\x86\x4d\x90\x16\x6f\x61\xac\x7e\xbb\x85\x81\x87\xb7\x7c\x52\x19\x92\x83\xe7\x9e\x9e\x9e\x59\x89\xfa\x9d\xf1\x8a\xb7\x84\x57\x74\x87\x57\x74\x87\x57\x6c\xe7\x8a\xdf\x1a\xac\xec\x1a\xf1\x88\x44\xc5\x63\x85\xeb\x8e\x44\xf1\x4c\x18\x7c\xc9\x76\xe7\x38\xe9\x05\xd2\x23\xb9\x15\x55\xc0\x8a\xfa\x74\x05\x67\x1a\xa8\x64\x8b\x11\x91\x8e\xc3\x30\x67\x2d\x0d\xd3\x16\xbe\xf2\x5f\xae\xa9\x83\xe7\xcc\xd9\x32\x5c\x08\xb2\xf1\x39\x5f\x7d\x5b\x56\xb2\x74\x86\xe4\x6b\xb6\x77\xfd\x6b\xb2\x8d\xcd\x8e\x17\x9b\xe3\x55\xab\x57\x59\x68\xba\x37\x5f\xd1\x36\xaf\xa8\xb0\xa3\x31\x58\xe9\xc5\x59\x11\xc8\x15\xd5\xf4\xab\x0f\x59\xaf\x64\x55\xb1\x72\x15\xad\x16\xd9\x0a\x86\x6b\xd7\xfe\x02\xe0\xda\x7f\x0c\xb1\xf6\x47\xde\x20\x35\x91\xba\x10\x6b\xbf\xe5\x5c\x53\x50\xd6\x54\x60\x6b\xdc\xf9\x04\xd2\x30\xcf\x9a\x97\x71\x40\x4a\x2c\xf4\xb5\xac\x72\x68\x4e\x2d\xfb\x85\x6b\x6b\x0d\x55\x26\xeb\xf1\x0a\x8e\xea\x2a\x90\x0d\x8f\xfb\x84\x98\x29\x02\xd1\xae\xe9\x95\x98\x35\x75\xd8\x5a\x8f\x99\x45\x48\xd7\xd4\x5c\x40\x5a\xcb\xd5\xb2\x86\xb1\xbf\xb1\x12\x6c\x22\xd6\xf2\xe9\xcb\x1f\x40\x37\xd6\xd4\x80\xde\x89\x4e\x40\x13\xbe\x81\x2b\x3e\xef\x24\x7a\x7d\x7e\x23\xeb\x3a\x05\x1a\xf0\xe7\x15\x36\x3c\xa7\xdc\x70\x99\x6e\xb8\xfc\x36\x92\x6f\x09\xa4\x1b\xd0\x8d\x7d\xa6\x79\x25\xd1\x2b\x4c\x1b\xce\xc1\x86\x47\xc6\xdc\x01\x20\x55\x9d\xd7\x8d\xc5\x53\x77\x20\x0b\xef\x23\x09\x77\xa2\xb6\xe1\x4d\x00\xa0\x8c\x68\xca\x56\xc6\xd0\xd4\xc6\x7f\x00\xb2\x71\x1f\x80\xe4\xe4\xb5\xcf\x39\xf3\x05\x2e\x59\xe0\x9a\x79\xce\x2c\x4a\x43\x47\x1b\x6e\xf2\x36\x32\x3f\x18\x5d\xf3\x50\x2d\x77\xf2\xcb\xc7\x46\x1b\x9d\x17\xcb\x5c\x58\x45\xb6\xeb\xda\xd0\xa6\x6c\x7c\x30\x78\x63\x51\xa7\xf8\xe4\xc9\x5a\x96\xc4\x7b\x7f\x1b\xef\xa1\x6e\x68\x4c\x36\x7e\x63\xb5\xd1\x1d\x94\x0e\x84\xd8\x0f\xa2\x8b\x6b\x99\x08\xdc\xc6\xef\x90\x36\x3e\x22\xfb\x1d\x47\xe9\xd0\xed\xdf\xa9\x9f\xd5\xd2\xf3\x56\xc4\x77\x46\xa2\xbe\x8b\xd6\x53\xaf\xef\x3b\x0f\x98\xbe\x63\x45\x60\x8e\xbf\xe3\x47\x28\x80\x6e\xac\x44\x8d\xab\x69\xbc\x60\xcb\xe3\xb8\x2d\x97\xd5\x96\x71\x97\x2d\x2f\xff\x6e\xa5\xe6\x59\xcf\xae\x55\xeb\xb0\x6c\x79\x53\x05\xf7\xb6\xbe\x1a\x92\xd6\x6c\xe9\x35\x6d\xed\xc0\xac\x06\x99\x33\x4c\xb0\x65\xf0\x77\xcb\x0b\xb5\x5b\x93\xb0\x98\xac\xdf\x31\x6d\x19\xc4\x80\x77\x86\xa4\x13\x37\xc3\x5b\x2a\x8a\x2d\x5d\xaa\xad\x88\xdb\x48\xbc\xa3\x33\xc6\x63\xcb\xaf\x55\xb7\xfa\x91\xb8\x28\xa5\xad\xe8\x8e\x6b\x4f\x7f\x4b\x40\xdb\x12\x10\xbb\x9b\xe8\xcf\xa0\x6c\xa9\x3b\xb6\xf2\xfa\x03\x10\x9c\x9b\x11\xc9\xc8\x0a\x4e\xe2\x85\xef\xad\x85\xc8\x23\xb9\x25\x8a\xe5\xc4\xf7\xfc\x6c\xc9\xc5\x14\xa2\x7f\x88\xf4\x76\xe9\xd6\x6f\xc8\xb7\xce\x1f\x49\xc9\x55\xcb\xef\xb8\x39\xde\x49\x33\xff\x0b\xdb\xb6\xe3\x4d\xa6\x9d\x7d\x9e\x72\x05\x29\x64\xc4\x47\x24\xb5\x21\x99\xc6\x1d\xcf\x8e\x77\x8c\xe1\x0a\x12\x41\xd8\x59\x10\x28\x05\x59\xf0\xa2\xce\x8e\xa7\x5d\x3b\x5a\xd5\x1d\x6e\x38\x00\x7d\xb0\xd4\x4f\xa2\xf8\x3b\x2b\x3b\x5e\xa5\xdb\xd9\xaf\x01\x7c\x27\xd9\xc2\x28\xed\xfc\x3d\xf5\x9d\x7d\xca\x90\x81\x68\x88\x68\x47\x4d\xf1\x46\x57\x6d\xcf\x43\x8f\x37\xbd\x05\x23\x59\xdf\xb8\xeb\x79\xe3\xfd\x97\xbd\x8f\x0b\x83\xdc\x13\x55\x3e\xb9\x66\xd9\xd1\x22\xef\xbd\x45\x06\x59\xb0\xf8\x37\xf7\x82\xc5\x53\xf6\x74\x12\xf6\x74\xef\xf6\xb4\x2f\xf1\xd2\xc8\x9e\xd7\xc4\xf6\x74\xe2\x40\x62\x53\xf5\xc0\x69\x8f\xcb\x51\x86\xec\x69\x85\x8e\xbc\xd1\xa9\x90\x34\x2b\x52\x67\xfc\x87\x9e\xaa\xd8\x4b\x73\xa2\x86\x28\x06\x29\xf6\xfe\x42\xda\xde\x9f\x84\xee\xb9\x39\xda\x9b\x9b\x37\x22\xc9\xf9\xf6\x8b\x6f\x7e\xb4\x51\x7b\x6f\xa3\xf6\x5e\x83\xec\x4d\x69\xc4\x02\xa2\x47\xb9\x57\x1b\xe5\x72\xfe\xc3\x15\xb3\xf7\x3f\x4f\xb2\xe7\x1d\x7a\xa0\x77\x20\x31\xec\x22\xe5\x7b\x9c\x48\x63\xe9\xee\xa5\xc3\x13\xeb\x4f\x50\x22\x63\x2b\xc7\xf6\x10\x7b\x91\xde\x01\x11\xde\x33\xc5\xb2\xc7\x69\x4a\xd7\xff\xd3\x1a\x67\x3f\xd8\xb1\xa7\xad\x03\x1a\x7a\xc2\x91\x55\x57\x21\x27\x89\xa7\x72\x6f\xd0\x3a\x36\xe1\x89\xba\x6f\x7b\x6f\x5d\xf7\x7e\x2f\x05\xa2\x8a\xfa\x07\x6d\x21\x50\xcb\x0c\x4b\xdf\x90\x15\x3b\x14\x43\x89\x20\x3f\x88\x4e\xbe\xb1\xff\xe7\xc9\x27\x0f\x0e\xf7\xde\x6a\xee\x3b\x77\x63\x0d\x44\x35\xe9\x81\xf6\xeb\xc0\xd3\x9e\x03\x17\xca\x81\x63\x71\xe0\xf2\x38\x70\x79\x1c\xa8\x9c\x0f\xdc\xf7\x1c\x78\x4a\x77\x30\xe7\x37\x23\xd1\x82\x4a\x66\x2d\x65\xad\x9c\x58\xb0\xca\xe1\xbb\xfb\x6c\x31\xd6\xa0\x6b\xe9\x20\xeb\x66\x6c\x48\x64\xe8\x20\x8b\xe6\x0f\xd6\xf5\xcc\x12\x1b\x36\xb5\x85\x9b\x70\x30\xe9\xaf\x48\x2a\x66\x40\xad\x07\x56\xf9\x02\xc9\x3d\xf8\x2d\xd2\x3f\xf6\x03\x3d\x23\x92\x05\xab\x6b\xe9\x9b\x1c\x38\xaf\x07\x99\xd4\x7b\x88\xcd\xc1\xbc\xee\x96\xef\xac\x59\xdd\x96\x8d\xdd\x33\xed\x9d\xc3\x16\x83\x37\x07\xee\x99\x0e\xf6\x6b\x2d\x23\x12\x7d\xef\x6a\xb3\x60\x32\x00\xf4\x68\xdd\x0d\x2b\x67\x4a\x84\x5e\x5a\xdb\xdf\x2d\x8e\x89\xe1\xd4\x1f\x13\x59\x93\xa0\x41\x76\xbd\xe1\xe0\xad\xe5\x81\xdf\x73\x09\x72\x1b\x99\x03\x8d\xe8\x41\x96\x68\x44\x29\x51\x66\x28\x89\x95\x17\x4e\x06\xf5\x44\xb4\x25\x29\xac\xbf\xee\x46\xc2\xc1\xbb\xa3\xff\x70\xd5\x21\xf9\x87\x49\x98\x8b\xc7\x1f\x19\x4a\x3f\xea\xa1\xa7\xbc\x70\xf4\xdf\x74\x1c\xfd\xed\xa7\xff\xd9\xd7\x87\x19\x0b\x48\xb9\x81\x03\x39\x02\xe9\x3a\x3a\x52\xc1\x1c\x69\x70\x8e\xf4\x66\x8e\xb2\x7a\x1e\xd0\xaf\xa3\xfe\x52\x97\x05\xa2\x8e\x54\xd5\x47\xae\x9c\xa3\x2c\x9b\x2f\x40\x8f\x18\xde\x23\xae\x17\x01\xcd\x98\x6f\x06\x37\xe9\x48\x5f\xef\xa4\x47\x54\x42\x8e\x34\x36\x47\x1f\x7f\x3b\xf2\x84\xfe\xc8\x5f\xb0\x3a\x9a\xcd\x69\x49\x32\xa2\x82\x65\xbf\xf2\xbd\x15\xbb\xbe\x62\x15\x3b\x3e\xdd\xb3\x85\x07\x5f\xed\x4f\x66\xbd\x10\x5d\x0d\x99\x01\x38\xf2\x7c\xf4\x48\x91\x3d\x8a\x38\x16\x86\xb4\xea\x84\x63\x0d\x1f\x53\x9a\x7c\xd2\x53\x2e\x6d\xb2\x79\x92\xc7\xce\x9d\xaa\x9f\xec\xe0\x28\xe3\x13\x15\x28\x3c\x51\xe3\x86\x53\x06\x15\x9e\x9f\x3e\xca\xfb\xd3\x76\xb6\x03\x92\x8c\xe8\xce\xe7\x29\x7c\x51\x25\x91\xda\x93\x9f\xfe\xdc\x1b\x64\x4e\xa4\xc7\x9f\x3f\x3b\xf7\xab\x0b\x3f\xfd\x39\xf6\xcf\xce\x7e\x34\xe1\xa7\xf8\xa5\x13\x20\xdd\x68\x7c\xe8\x06\x5c\xe4\xec\x43\x37\xc5\xba\xf2\x91\xd3\xf6\x3f\x3f\xbd\x27\xfe\xf1\x9b\x59\xfc\xb0\x10\x63\xc5\x9c\xa5\xf5\xdb\xed\x05\x3f\x3a\xfb\x22\xeb\xcc\x21\x3b\xd3\x17\x84\xe1\xd2\xcd\xc9\xd9\x3e\xa0\xca\x49\x74\xf4\xcf\xfe\xa3\xa5\xb3\x7e\xa7\x64\x45\xc5\xef\x94\xce\x5c\x79\x67\xce\xc8\x99\x1d\x38\xfb\xd6\x7f\x72\x19\x9e\xb9\xe6\xce\xd4\x32\x67\x7a\x4d\x67\xce\xd4\x99\xee\xfb\x99\x87\xce\x67\x4a\xce\x99\x7a\xe8\xdc\xb9\xaf\x26\xcf\x5c\x94\x67\x5c\xff\x21\xd2\x3e\xea\x75\xec\x33\x4d\xd6\xbf\xf8\x59\x39\xdf\xa8\x5f\x3e\x37\x00\x2f\x89\x1a\xb6\x73\xc5\xfd\xce\x99\xf1\x9b\x33\x9d\x9f\x33\x9d\x76\xa0\x29\x11\x7b\xe0\xae\x43\x21\x6c\xb4\x81\x46\x8c\xdf\xfb\x00\xa9\x27\x7b\xe1\x71\xcd\x85\xb1\xc2\x0b\xbe\x56\x02\xd2\xe3\x8b\x8b\x18\xd8\x7e\x4f\xbf\x15\xb2\xf2\xbf\xf2\x0d\xb5\x89\x17\x44\x00\x81\xd6\xf0\xb4\x2f\xb2\x4b\x9f\x02\x6d\xf9\xae\x4a\xc2\x85\x91\xc1\x8b\x98\x8e\x3b\xa0\x21\x9f\x66\xfc\xac\xe0\xc2\x1f\x7e\x8c\x86\x33\xfe\xe0\xd9\x05\xba\x81\x28\xb3\x96\xbb\x4b\x36\x17\x8b\x7e\x87\x17\xae\xbc\x87\x71\xa5\xe1\xb8\x52\xfa\xae\xd4\x33\x57\x04\xa0\x0c\xc9\x54\x5d\x29\x5c\x57\x5a\xb2\xab\xfd\xe2\xc3\x00\xa4\xf6\x28\x96\x3a\x23\x7a\x61\x3b\x5a\x3a\x66\x57\x7f\x22\x77\xa5\x23\x72\xf5\x91\xd5\xab\x74\x61\x45\x84\x06\x96\xcc\x29\x5b\x75\xcb\xa9\x7a\xfb\xea\x77\xba\x57\xc6\xa3\xae\xdc\xdf\xc7\xa3\x8e\x2b\x2f\xdb\x5f\x7d\x70\xff\xca\xaf\x94\xae\x8c\x37\x5d\xdd\xe0\x4a\xfc\x40\x92\x03\xc2\x85\x23\xa0\x50\x93\x6e\x07\x06\x3d\xb7\x31\x50\x34\x24\xaa\x7a\xf6\x9d\x19\xbe\x94\x8c\x77\xf0\x03\xba\x63\x41\xa5\xed\x8d\x71\x2f\x3f\xfe\x7a\xaa\xf2\x37\xa0\x47\xfb\xcd\x46\xbd\xbe\xaf\x0d\xaa\x59\x79\x2d\x66\x47\xd1\xc9\x50\x10\xdf\x80\x66\xac\x62\xc6\x52\xb8\x8d\x0a\x84\x3f\x6e\x14\xc8\xce\x92\xc3\x30\x5e\x81\x86\x4c\xbb\xb1\x2f\xb6\x71\xdb\x4c\x55\x4b\x20\xd0\x60\x7a\x72\x9d\x78\x92\x7a\x32\xf4\x04\x4e\x95\xdd\x22\xb1\x19\x52\x0e\x39\x50\x52\x11\x41\x0b\x2b\x41\xf0\x04\x44\x5d\x3b\x25\x39\x8b\xba\x75\xbf\x60\x17\xf8\x83\xc8\x8e\xdc\x7d\x96\xd5\x10\xd0\x93\xbb\x78\x1d\xf8\x33\xcb\xbd\x58\x9a\xba\xa8\x7a\x87\x13\x97\x56\x95\xc0\x46\x2b\x81\xf7\xa1\x3f\x2c\xa9\xdf\xe3\xa0\xee\x84\x1f\xc5\xda\xa2\x0b\x49\x43\x3e\x44\x2c\x4b\x11\xce\xbc\x40\x62\xf4\x57\x7f\x12\x2a\xe3\xdb\xaf\xf6\xb6\xee\x3d\x13\xfc\xb0\x6b\x4e\x84\x13\xb0\x64\x60\x97\x1c\x92\x01\x45\x31\x8e\xf1\xc0\xb6\x41\x4a\x6a\x8f\xe8\x63\x46\x47\x3a\x19\x50\xaa\xe2\x8c\xf0\xfc\x37\x19\xd8\x6f\x05\x24\x03\xbb\x85\xa3\xe8\x87\x28\xbb\x64\x60\x3f\xdb\x9b\x0c\x4c\x19\x24\xb8\x64\x56\xb8\x66\xe8\x31\x78\x82\x0b\x64\x37\x5c\x77\xa9\xed\x0b\x14\xbd\x3b\x67\x20\x67\xea\x87\x21\xdd\x7c\x24\xa9\x59\xd4\x24\x75\xb7\xab\x12\xba\xd4\x09\x4d\x7c\x82\xef\x9d\xc7\x40\x0c\xe2\x05\xf2\x0d\x8d\x4d\xdd\x01\x55\x82\x26\x20\x83\x6a\x9c\x84\xbf\x49\xa8\x73\x37\x20\x8a\x69\x3c\x0c\x53\xfe\x48\x54\x13\xf1\x06\x4d\xbc\xb9\x19\x7f\x78\x34\x19\x9a\xe3\x90\xd8\x4f\x03\x5a\x45\xb9\xed\x2c\x02\x99\x32\xf9\xde\x37\xab\xe4\xab\x95\x6f\xc9\xdc\xa3\x1c\xe8\x85\xed\x5e\xb2\xac\x57\x9c\x9f\x31\x0f\xfc\xbd\x64\x68\x76\x3b\xa0\xd4\xca\x4a\x32\x0b\x58\x29\xd1\x59\x46\xe4\x2f\x05\xca\x2d\xec\xa2\xe4\x9e\x08\xd6\x5b\xc9\x73\x4f\x57\x6b\xc2\xcf\x69\xf4\x0b\x18\x45\xaa\xc7\x6f\x28\x90\x37\xec\xc1\x8d\x85\xe2\xe4\xaa\x2c\x2a\x1b\x51\xb2\x46\xee\xf7\x90\x94\xcc\x98\x3b\xb7\x1f\x88\x51\xa2\xc9\x53\xa6\xc1\x37\x0b\x68\xc6\xe2\xe6\x4c\x9b\xb3\xd4\x25\xdf\xd8\x1a\xb2\x81\x1a\xd9\xc1\xc9\xc4\x72\x9b\xee\x1d\xf1\xc7\x76\x48\xc6\x7c\xfb\x2f\xfd\x39\x16\xb1\x35\xe0\x6c\x4c\x32\x62\x51\x13\xeb\xaf\x29\x10\x1c\xca\x84\x61\x1e\xbb\xdb\x1f\xc9\xd8\xeb\x5f\x90\x47\x22\x55\x76\x63\xfb\x60\xa5\x10\x82\x0b\x44\xfa\x3b\x5d\xc9\xa4\x8b\x5f\x66\x28\xf9\x42\xa4\x83\x03\x82\x1f\x71\x8b\xd9\xb0\x81\x55\xf2\x49\x92\x41\x35\x4e\xf4\x47\x49\xb4\x00\xbd\x9e\x10\xc9\xd4\x93\xc2\xaa\x8f\xbb\x01\x25\x51\xdc\x27\xde\xee\x4f\x34\x42\x25\x24\xe3\x62\xcd\xec\xfa\xbb\x22\x7c\x53\xab\x64\xce\xdc\xb9\xf8\x6c\x2a\xe7\x2d\xd0\xa3\xcc\xd8\x4d\x4f\x25\xde\x54\x4e\x46\x61\xcd\x28\x0d\x99\x6d\x28\x13\xfe\x36\x52\x82\x5f\x37\xfa\x42\xf4\x83\xe8\xc4\xac\xd8\xcf\xe0\xc7\x7f\x45\x6f\xe0\x27\x87\xfa\x44\x88\xb2\x2b\xd1\xc5\x9f\x9b\xa3\x9d\xc8\x0f\xb3\xc8\x4f\x6a\x83\xd4\xee\x57\x88\x55\xeb\xa6\xbd\xf8\x31\xfa\xff\x07\x00\x00\xff\xff\xaa\x0a\xcc\xb8\xdf\x5e\x00\x00") func keysWordlistJapaneseTxtBytes() ([]byte, error) { return bindataRead( @@ -126,12 +126,12 @@ func keysWordlistJapaneseTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/wordlist/japanese.txt", size: 24287, mode: os.FileMode(420), modTime: time.Unix(1497960590, 0)} + info := bindataFileInfo{name: "keys/wordlist/japanese.txt", size: 24287, mode: os.FileMode(420), modTime: time.Unix(1511602021, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _keysWordlistSpanishTxt = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x34\x5b\xbb\x76\xfc\x2e\xaf\xed\x79\x4b\x8c\x65\x8f\xe6\x00\xe2\x27\xc0\x2b\x99\xb7\x49\x99\x62\x8a\xff\x4a\x97\xd6\x2f\x76\xd6\xde\xe4\x2b\x46\x98\x3b\xe8\x2e\x60\xee\xaf\x2d\x26\x0b\x71\xdb\xad\x48\x0d\x71\x93\x67\x0c\x71\x53\xf1\x81\x52\x3b\xe3\xce\xb4\x12\xae\x42\x8f\x2f\x26\xea\x21\x6e\x53\x32\x32\xb3\x5b\x88\x29\x6e\xd1\x91\xec\x52\x34\x86\x98\x92\xb0\x38\xe9\xfd\x53\x43\x4c\xa2\x43\x90\xe4\x13\x95\x52\x31\x5a\x92\x36\xa2\x87\xfb\x2b\x29\x66\x4a\x39\x3a\xc7\xa8\xf7\x77\x88\xc9\x4e\x41\xc6\x38\xcc\xd0\x8b\x09\x81\xeb\x0b\xc9\x64\xe3\xb9\x2b\x13\x71\x8e\x31\x3b\x4a\x77\x65\xd3\xbd\xe8\x40\xed\x6e\x9c\x28\xee\xe6\xd8\xcc\x3e\x63\x8d\x48\x32\x1a\xdd\xdf\x2e\x16\xe2\x21\x89\x6d\x0e\xfd\x5b\xf2\xa1\x75\xe5\xbd\x70\x91\xa7\xe6\x10\x4f\x65\xa3\xd3\xea\xfd\x8e\x48\x3b\x86\x38\x6d\x95\xba\x9c\x2b\x55\x14\x4e\x34\x98\xbb\xa1\xef\xd4\xcc\x1c\x30\xfc\xb0\xd3\x00\xdd\x2d\x44\x75\x09\x51\x7b\x46\xbf\xa7\xec\x2e\x2f\xa4\x58\xe5\x73\x76\xa0\x2c\xc7\xe4\xf7\x57\xc5\x47\xd9\x9c\x05\x5e\x62\x88\x79\x8b\xe1\xfe\xca\xdb\x2c\x21\xe6\x14\xf3\x8e\xaa\x5d\x50\x23\x27\xdb\xc9\x13\x83\x66\xf1\xc1\x42\xc2\x43\x33\xb0\x4a\x2a\xe4\xd3\x76\xee\x34\x2b\x29\x9d\x75\x91\x25\xeb\x85\xf5\x67\xce\x52\xc8\x14\xb9\xdc\x6f\xd2\x37\x8f\x05\xe5\x85\xd2\x45\x15\x62\x31\x8f\xe9\x28\x9a\x05\x6b\xcf\x2f\x34\x2b\x71\xcb\x82\xa4\x0e\x26\xcd\x80\x84\x12\x1d\xfb\x2f\xb1\x13\xad\x65\xfb\x4b\x14\xc3\x14\x6e\xbd\x28\x5b\x68\x1f\x71\x0f\xb1\x18\xc6\x6a\x11\xe8\x2a\x2d\x63\x6d\x35\x3d\x08\x35\x56\xa6\x18\xb7\xee\x98\xb3\xee\xf7\x77\x0d\xb1\x92\x0b\xef\xaf\x7a\x4e\xf0\x68\xd5\x9c\x41\x87\xaa\x05\xb9\xfb\xdd\x43\xac\x8b\x68\x75\x08\x98\xa1\x0e\x3d\x27\xea\x86\x3d\x91\xcc\x98\x01\x49\x97\x3a\x6b\xc2\xac\xf7\x7f\x91\xcc\x76\xff\x27\x4f\x66\x2d\xc4\x16\x49\xf2\x16\x3d\x62\xfd\x4d\x06\xf7\xd1\xd0\xbe\x65\x4d\xac\x34\xa0\xb7\x99\x03\x0d\xcd\x3e\x91\x71\xa9\x3b\x28\xd1\xdc\x88\xd8\x36\xa5\x83\x42\x6d\x62\x9b\x4e\x82\x38\x66\x0c\x14\x8a\xfb\xcb\x37\x1d\x6e\xfc\xb0\x1c\xa2\x6f\x93\xac\xe7\xe9\x41\x22\x38\x24\xd9\x39\xa4\xef\x9a\x81\x10\xdf\x27\xdb\x0b\x10\xe1\x14\x31\x57\xe9\x21\x7a\xf9\x63\x5f\xaf\xf7\x37\xf2\x06\x52\x7b\x23\x20\x47\xb8\xcb\x09\xbc\xb9\xdb\x0b\x70\x82\x5f\xb8\x7c\x1f\xca\x75\x76\xfe\x30\x66\x5f\x0c\xd0\x93\x54\x88\x6a\x97\x73\x52\x8c\xbb\x30\xd7\x41\xbd\xfe\xc7\x5a\x5d\x33\x61\xa7\x58\x76\x10\xaf\x5b\xd9\xb8\xaf\xde\x04\x5b\xef\x63\xad\xbe\x8f\x95\x9b\xec\x37\x0b\x3b\x4c\x8e\x32\xe2\x93\xf0\xdf\x14\x24\x1e\xe2\x58\xc3\x0f\xc1\x40\x43\x81\x8b\x41\x8e\xbf\xbf\x86\x81\xe4\xc3\x23\x50\x33\xb8\x9f\x71\xff\xd6\x10\xe7\x1e\x5f\x80\xa0\xd4\x3c\x25\xc4\x89\x69\x67\x59\x43\xcd\x2e\xe4\xda\x39\xb0\xfe\x0b\xdc\x70\xc5\x9a\x04\x09\x16\x76\xe1\x4b\x72\xa6\x26\xb9\x64\xc1\x3e\x7c\xbe\x42\xbc\x96\x02\xb9\x14\xf8\xf8\xc4\xbc\x9f\x73\x8f\x80\xd8\xf0\x2b\x1e\x4b\xa0\x29\x23\x2f\xc3\x2c\xaf\xfb\x97\x9c\xf2\x9a\x07\x44\xf7\x35\x73\xd8\xe2\x16\x01\xcc\xc3\x16\xd3\x43\xc2\x16\x1f\x20\xda\x16\x35\x23\x03\xe1\xde\x62\x8e\xf5\x85\xb2\x9c\x30\xe5\x46\x35\xb0\xc5\xb2\xdd\xbf\x61\x8b\x35\x19\xe0\x8e\x06\x60\xd6\x2d\x3a\xc7\x74\x96\x7b\xd5\x17\x12\xb7\xb0\xdd\x5f\x3d\x61\xfb\x5b\xec\x63\x0d\xd4\x21\xce\x5b\x1c\x31\xb3\x78\x88\xaf\xc9\x41\xb8\x2d\x8e\x39\x38\xe8\x2f\xd6\x89\x7d\x6c\xb2\xdd\xdf\x80\x8a\xd9\x04\xd2\xb6\x49\x67\x45\xe7\xe7\xd0\x18\x36\x85\xd8\x6e\x2a\x35\x6c\x5a\x4f\x0b\x5b\x5e\x6b\xcc\x06\x52\x6e\x79\xf6\x18\x36\xc3\x6f\xd3\xca\xc4\xc2\x66\x09\x5f\x69\x15\xec\x04\x72\x22\x59\x25\x99\x00\xac\xb3\x59\x66\xff\x82\x4d\x5a\xdd\xe3\x8e\x04\xe2\x48\x1b\xb6\x59\xed\xf7\x97\x86\xcd\x1c\x48\x32\x07\x97\x6e\xd6\x39\x35\xa8\xb0\xd9\xb8\xdf\x35\x6c\xf7\xcf\x25\x9c\xe7\x15\x73\xd8\x3c\x5e\x16\x96\xdd\xdb\x5c\xd2\x23\x22\xb9\x24\x6c\x4e\x9d\xb2\xb9\x72\x0b\xae\x98\xdb\xb9\x58\xca\xd3\xe6\x06\x76\xd9\x9c\x43\x3b\x34\xff\xe6\xb3\xb3\x2d\x78\x7a\x9b\x49\x08\x41\xcd\x09\xb5\xb7\x4d\xf9\x0c\xdb\x3c\x16\xc5\xe6\x41\x42\xdc\xbf\x40\xd9\xd4\xe1\x68\x96\xd9\xd1\x37\x8e\x36\x3d\x13\x62\xeb\xb3\x83\x7f\xb6\x39\x22\x16\x30\x5f\xe8\x0b\x93\x8c\x25\xa6\xb8\x41\x5d\xa7\x48\xa4\x26\x18\xf1\x90\x62\x8a\xa8\xd9\xef\xaf\x4b\x1c\x1f\xc2\x3a\x7e\x1f\xf7\x77\x48\xf1\x7e\xef\x28\xd1\x02\x66\x4d\xf1\x89\xcc\x73\x8d\x9b\xf1\x83\x22\x47\x0a\xd5\x08\xfb\x43\xa8\xc0\x7a\x8a\x39\x0b\x60\x41\x9f\x6c\x6c\x76\xa1\x9e\x05\x65\x63\x8f\x22\x6b\x71\x45\x2b\x93\x66\x21\xdd\x5f\x35\x71\x09\x75\x57\x4c\x52\x25\xa3\x47\x3d\xa1\x15\x53\xac\x9a\x98\x1d\xc8\x40\x37\x02\xae\x25\xd9\x86\x9c\xf5\x90\x62\x8b\x2f\x40\x1d\x6b\xe1\x0d\x04\x48\x91\x1e\x40\x8a\x6d\x82\x84\x29\x12\x07\xbe\xb1\xf3\xfd\xe5\x49\x30\x9d\x43\x65\xa4\xe8\x27\xa1\x42\x66\x52\xf4\x8a\xee\xde\xfe\xea\xb8\x10\xe7\x77\x27\x48\x28\xe8\xc2\xf2\xde\x58\x34\xb8\xe5\x61\x9e\xd0\x15\xa4\x4b\x50\x37\x98\x62\xb2\xd3\xcb\x42\x92\xcd\x20\x5b\x49\xa0\xb4\x93\xec\x18\x40\x32\x70\x7e\x7f\x67\x81\xa9\x4f\x92\xe1\xfd\x20\x3f\xd9\x72\xe9\xa6\x24\x55\x41\x4f\xa9\x83\x7d\x1c\x48\xa1\xfb\x93\xc4\x49\x69\x59\xe5\x60\xf0\x24\x4e\x63\x9d\xee\xef\xde\x64\x0f\x49\xd8\xe9\x11\x49\xc5\x47\xcc\x92\x98\x2d\xed\xfe\x45\x4a\x5b\x9a\x1e\xb1\x11\x3a\x33\xca\x26\x0a\x77\x64\x59\x9b\xf4\xa0\xc0\xa6\x87\x61\xe4\xc7\xa4\xaa\x4d\x8f\xd9\x30\xa1\xa6\x4c\xac\xaa\x9c\x06\x98\x09\x59\x00\x1f\x32\xe9\x01\xdc\xeb\xb9\x50\xa9\x60\x09\x8a\x50\x52\x20\x5a\x2b\x86\xd2\xe6\xb0\x4c\x49\x9d\x15\x3e\xc9\x07\xda\xd9\x82\x0d\x26\x19\x2d\xd3\x39\x48\x39\x56\x00\x8c\x97\x63\x17\xc0\x0b\x50\xa9\xc3\x53\xe6\x24\xf9\x7e\x2f\xfe\x31\xe2\xd6\xfe\x5c\xd3\x64\xe9\x41\x0e\x5c\x2a\x26\x19\x66\xbc\x7f\x76\xb8\x20\x09\x86\x3b\xd9\xc1\xf6\x70\x47\x93\x3d\x04\x23\xda\x13\x9a\x22\xc1\x55\x48\xd0\x40\xc9\x32\xd9\xca\xb2\x9c\xca\x32\x78\x05\xc9\xf2\x1a\x32\xe7\x95\x2b\xac\x9a\x85\x85\x05\x5a\x15\x29\xc7\x2d\x4a\xca\xff\x94\x35\x65\x69\x40\x92\xd5\x1d\x2d\xaa\x70\x9e\x7a\xb2\xc8\x28\x21\x56\xfb\x5f\x29\xf9\xda\x40\x2f\x6b\x0a\xe8\x71\x89\xbf\x39\xf4\x37\x52\xa8\xdd\x64\xbe\xff\x15\x1b\xe7\x77\xe7\x38\x7d\xc1\x02\xd1\x31\x98\x76\xba\x9b\x62\x4c\x07\x2a\x5d\x22\x61\x5a\x99\xfb\x8d\x15\xba\x14\x36\x7d\x03\x2a\xe2\x87\xe4\xda\xd8\x5d\xbb\xf6\x90\x1c\x76\x37\xf9\xfd\xb3\x90\xee\xe0\x18\x56\x4f\x76\x9f\xaf\x90\x66\x24\xd3\xcf\x48\xbe\x98\x91\x9c\x39\x37\x02\x44\x18\x09\xb2\x0a\x3c\xcc\xa5\x2a\xe6\x62\x7f\xb8\xfa\x2c\xe4\x6a\xa7\x5c\x80\x0a\xef\x2f\x4d\x08\x0e\xb2\xb9\x11\xb2\x39\xdd\xe6\x34\xe1\x3a\xa2\x09\x36\x3f\x2b\xd7\x32\x8d\xb0\x2d\x2d\xf0\xdb\x28\x65\xf4\x5e\xd2\x74\xa5\xec\x4d\x5f\x90\x93\x0c\xed\x61\x87\x12\xdb\x69\x76\x31\xe5\x1e\x21\x78\x3b\xbc\x8e\x1c\x76\xd9\xc4\xc3\x7e\x7f\x6f\xc8\xdc\xdf\x29\xee\x31\xec\x92\xd4\xc3\x2e\x68\x26\x87\xd4\x8e\xa2\x43\x2b\x0b\x61\xc5\x77\xc9\x07\xd8\x69\x47\x70\xc4\x56\x19\x46\x6b\x97\x62\x8e\xb6\x70\xab\x76\xa9\x23\x62\x82\xe5\x45\xee\x02\x53\x84\x62\x77\xec\x61\x97\xbe\xbc\x8b\x5d\xe0\x76\xed\xd2\xe1\xe8\x23\xad\x93\x23\xf6\xa1\xab\xf6\xba\xdf\x48\x07\x55\xf4\x2e\x43\x2a\x56\x2c\xf0\x4f\x76\x10\x73\xd7\xb8\x65\x43\xb2\x83\xc2\xbb\xfe\xb9\xef\xbb\xc2\xd3\xd9\x35\x22\xb6\xd9\x75\x9b\x4f\x24\x0c\x99\xf6\x25\x66\xbb\x02\xa7\xbb\xca\x2b\xec\x7a\xdc\xef\x04\x1c\xe8\x89\x69\x35\xaf\xb1\xf2\xc4\xa6\xb5\x42\x3f\xed\xea\x82\x20\x6d\x57\xd7\x93\xc5\xd0\xa4\xbb\x76\x81\xda\xdd\xb5\x1f\x1e\x31\xd2\x85\x8e\x17\x57\x6f\x08\x27\x76\x4b\x00\xb0\x2a\xbb\x15\xba\x11\xbb\x55\xfc\xb0\x14\xa3\xe7\xbc\x9b\xc3\x5f\xdc\x0d\xc4\xdb\xad\xe3\x07\xd2\x79\x3c\x41\xea\xdd\xed\x8c\x61\xa7\x25\xd8\xb9\x73\x46\xb2\xfb\x5c\x53\xcf\x8c\x19\xee\x5f\x7c\x42\xcd\xed\xe4\x88\x7d\x52\xb7\xee\xb0\x44\xf7\xf7\x86\xc0\x43\x36\x20\x03\x3e\x81\x07\xa8\x51\x01\x47\x9b\x07\x81\x6e\x92\xfd\x2f\x90\x94\x5d\x11\x53\x1a\x3e\x06\x6b\x27\x6c\xb5\x1c\xdc\xbe\x1c\x9a\xe2\x2b\xc8\x53\xf0\x2b\x2d\x5b\x90\x2c\x07\x71\x2e\xd0\x26\x8e\x64\x29\x7e\xc9\x72\xa1\x67\xd6\xd6\x25\xdc\xdf\x59\xd9\x48\x3f\xd8\xc8\xa0\x79\x24\x33\x1e\x96\xb2\x81\xee\xb2\xe2\x5f\x29\xf6\xb7\x94\xd2\xa0\x73\xa4\x34\xee\x14\xd3\x09\x13\x97\x1e\x83\x54\x6e\xaa\x26\x06\x68\x52\xd3\x63\x1e\x82\x14\x7c\x21\x88\xa8\x58\x0c\xe2\x49\x3d\x80\x67\xa9\x87\x78\x41\x7a\xd2\xc1\x94\xaa\x67\x41\xdb\x1c\x13\x7a\x9a\x17\x24\x2e\x6c\xdb\xe3\x27\x13\xb9\xff\xc3\x2e\xea\x58\x23\x0d\x67\xee\x82\xe2\x96\x4a\xfe\xbc\xbf\x1b\x1c\x29\xf9\x37\xb5\x59\x10\xd7\x97\x05\xe9\xf0\x39\x90\xc0\x53\x91\x0e\xbd\xeb\x48\x5d\x37\xe5\x07\x77\xdc\x05\x51\x61\x90\x7e\x88\x33\x99\xe2\xec\xdd\x20\x8b\xd2\x1b\xb4\xa6\xf4\xc6\x3d\xf5\x66\x9d\xc9\xc4\xaa\xfb\xbf\x79\xbf\x03\xb4\x0a\x86\x03\x9e\x10\x8b\xa0\xf5\x98\x47\x0c\x32\x60\x14\x65\x88\x57\xac\x70\x40\xad\xc9\xa8\x98\xec\x62\x5c\x28\x57\xcc\x13\x7d\xaf\x45\xad\x8b\x67\x05\xf2\xc1\x63\x0b\xf9\x40\x6c\x1b\xe4\x83\xe7\x22\xf2\x91\xe0\x08\xc8\xc7\x6a\xf9\x41\x09\x90\x0f\x45\x70\x2b\x1f\x2b\x3c\xba\xbf\x3f\x94\x95\x8d\x76\x53\x3e\xfe\xc2\x49\xf9\x68\x06\xa1\x95\x8f\xe1\x52\x2c\x1c\xf7\xd7\xe6\x58\x0c\x3e\xa0\xc1\x8e\x98\x1e\xd8\xec\x71\x7f\x41\x06\x0f\xcc\xef\xe1\x88\xc0\xdb\x01\x3f\xee\x88\x70\x33\x0e\x3a\x87\x47\xcc\x9d\x10\x6b\x3d\xa0\xdb\x8e\x58\x34\x2b\x53\x63\x95\x47\xf0\xce\x11\xbd\xc4\xc4\x72\x37\x8c\xea\x1d\xdf\x5d\xc2\x11\x87\x9e\xf8\x9e\x9c\xe0\xe2\x64\x1f\xe1\x80\x0f\xe3\x16\x0e\x3a\xcd\x87\x64\x7d\x85\x43\x90\x77\x8c\x22\x08\xc5\x8e\xfb\xdb\xa1\x38\x0f\x71\x76\x93\x4e\x17\xfc\x50\x9e\x1c\x1c\x4a\x35\x7b\x28\x96\xa6\x50\xec\x87\xfe\x59\xed\x43\x39\xa8\xee\x18\x50\xe9\x2d\x1d\x2a\x19\x80\xcd\x68\x1b\x0e\x45\x28\x1a\x0e\x7d\x72\x80\x27\x9a\x02\x3f\x9a\x61\xc4\x0f\xec\x12\x3d\x32\xec\xce\xa1\x18\xb4\x02\x8d\x5a\x41\x0d\x68\xe8\x81\x72\x07\x4e\x72\x4c\x06\x88\xb8\xe7\xc8\x6b\x47\x50\x41\x47\x36\x96\x40\xb1\x1d\x19\x4a\xf1\xc8\xf7\x2f\x2a\x6c\xc3\x2e\xc1\xc6\x87\x9d\xb0\xc3\x87\x51\xf9\x1c\x06\x22\x1f\x96\xb3\x60\x78\xab\x3b\x20\x27\xe1\x89\xd0\x61\x3e\x88\x48\x73\x04\x56\x07\x38\xf4\x30\x34\xf5\x98\x22\x08\xe2\xeb\x2c\xea\xf0\x58\x41\x4c\x27\x0d\x3c\xce\x1d\x89\xdc\x6f\x47\x52\xd1\x10\x52\x7d\x38\x24\xea\x70\x6e\xc6\xb9\xfe\x09\xcf\xec\x98\xd4\xda\x94\x0f\x94\x81\x82\x13\x2e\xfd\x31\xeb\x1f\x8e\x27\x02\x91\x63\xfa\x5a\xf7\x24\xd9\x66\xc7\xd4\xf7\xef\xd8\xc0\x04\x73\x40\x1d\x9e\x31\xc1\x3f\x3b\xe3\x11\x7b\x38\x23\x1c\xb4\x13\x21\xfa\x19\x59\x9a\x57\xec\x78\x92\xdf\xce\x88\xf0\xec\x8c\xd0\xd6\xe7\x3a\xc7\x39\x23\x3c\x9b\x33\xc2\xce\x9d\xd1\xe3\x53\x90\xbc\x50\xd4\x97\x07\x75\x46\x0a\xe5\x19\x07\x5a\x5c\x9a\xe1\xd9\x9f\x52\xa0\xb5\x4f\x81\xaa\x3f\xa5\x86\xf3\xfe\xa6\x72\x3a\xa5\x2a\xe1\x90\x70\x8a\xc7\x95\xf3\xff\xe5\x21\x86\xa7\x74\x0c\xa5\x27\xf5\xec\xa9\xa5\xc6\x8e\x56\x0a\x5d\x74\x2a\x06\xc9\x60\x76\x0f\x67\x46\x10\x7a\x66\xc3\xee\x4f\xcb\xf8\x1d\x06\x08\xe1\x38\x2d\x37\x09\x27\xe2\xbd\xd3\xe0\x08\x9c\xe6\x60\xb1\x13\xd1\x65\x38\xc1\x1b\xa7\x0d\x41\x39\x88\x79\x3a\xe4\xf2\xf4\xfb\xeb\x80\x4f\x7d\x3a\x14\xee\xe9\x08\x24\x4e\x8f\xf0\x2e\x4e\x87\xe7\x7a\x3a\x6d\xe9\xb9\x42\xcc\xd3\xb5\xb1\x0c\xd5\x20\xe3\xe9\xd6\x0d\xa3\xdd\xbf\x68\x34\xa1\x51\x4e\x9f\x85\xb0\x59\x38\xe7\xda\xd6\x8c\x2b\xe3\x3b\xd6\x3e\x85\x6b\x9a\xa4\xc5\x64\x70\x73\x4e\xb5\x0a\xd8\xf9\x3d\xe2\x6a\xd1\xb9\xac\x49\x9c\x3f\x22\x5c\x9a\xc7\xfd\x05\x97\xe6\x11\xb7\xcc\x32\xb8\x82\x0f\xa8\x99\x40\x4d\xf3\x88\x79\x95\x17\x84\x9f\x8f\xe8\x20\xda\x23\xbe\xf0\x63\x9c\xf6\x90\x8d\xa7\x3a\x0f\xba\x67\x0f\xfa\x2e\x0f\xc9\xb0\x21\x0f\x81\x3c\x3c\xa4\xac\x1a\xf8\x7d\x0f\xf1\x82\x25\x3c\xee\x6f\x37\x41\xf6\x42\x29\x43\x89\x87\xc2\xe5\x09\x8f\xfb\x4d\x5f\xe9\xa1\xa7\x4a\x95\xf0\x80\x74\x3f\xb4\xa0\x97\x22\xfe\xd2\x18\x1e\x96\x80\xe5\x87\xc1\x17\x7f\x18\x10\x80\xc2\x27\x00\x7d\xc2\x87\xc1\x7b\x78\x58\x35\xd4\x57\xd6\x2e\x50\xa0\xd0\x1e\x3c\x2d\x7e\x18\xac\x40\x78\xd8\xa7\x85\xc7\x84\x99\x7f\x4c\x9e\x62\x3f\x26\x4f\x56\x1f\x44\xff\x63\xca\x05\x08\x2f\xfe\x01\x65\xf0\x98\x7f\x5b\xf8\x2d\xb0\x7e\x8f\x59\x34\xef\x82\x14\x99\xba\xb3\x89\x47\x44\xbc\xf8\x18\x16\x14\xbe\x7d\xd0\x5d\x62\x0e\xba\x2b\x78\x0a\xae\x76\xb6\xa0\x67\x96\xae\x11\xe9\xfd\x1b\xf4\x9c\x68\x91\xe5\x64\x32\x3b\x85\x55\x4b\x84\x0c\xac\x68\x5d\x0b\x4d\x8f\x96\xb6\xa0\xc0\x4f\xd1\xb2\xec\x86\x96\x36\xa1\xf3\xa1\xec\x10\x2a\xdf\xef\xba\x6b\x92\x00\xb7\x6c\x20\xa1\x22\xd5\x7a\xd0\x7a\x6b\x5d\xe2\xa4\x95\x3e\x8c\xd6\x42\x7f\x54\x6b\x99\x15\xb5\x15\x32\xa9\xb5\xd3\x99\xd1\xda\x07\x59\x4f\x61\xdc\x11\xc1\xdd\xef\x3a\xb4\xa0\x66\x00\x2b\x5a\xef\x5f\x60\x53\xeb\xa5\xb4\xa3\xea\x31\x28\x38\x5b\x7d\x9d\x49\x6a\xcf\x04\x08\xda\x9f\x71\x8b\xf9\x7e\x23\xc5\x16\x9f\xb1\xac\xc4\xe3\x86\x4a\xdf\x61\x2b\x9e\x64\xda\x27\x4f\xef\x9e\xf1\x55\x58\x26\x87\x84\xa7\xb8\x42\xb1\x3c\xb5\x42\xdd\x3f\xcd\x2b\x78\xf5\x69\x6e\x1b\x92\x4b\x6a\x78\xda\x67\x0c\xcf\x29\x88\xf8\x9f\x53\x2e\xe9\x48\x5e\xe1\x39\x4f\x7a\x72\xcf\x79\x1a\xc0\xe4\x08\x93\x28\x78\x4e\x44\xab\xcf\x59\x4f\xcc\x38\xeb\x2a\x02\xbe\x9f\xf7\x6f\x53\x84\x4c\x4f\x7a\x8c\x4f\x9e\xd0\x3e\xe7\x25\x55\x73\x78\xce\x17\xf8\xf0\xff\xe0\x51\xfc\x9f\x41\x33\xe6\xb8\xa9\x05\xe8\x19\x42\x47\xc9\x8e\xcf\x1d\x51\x53\xc8\xf1\x64\x60\x94\xef\xaf\xd3\x11\xc1\xe6\x78\xc2\x30\xe4\x08\xae\xce\x11\x71\x63\xbe\xbf\x0a\x64\x0d\x69\x8b\x1c\x81\x2d\x2a\x44\x33\xc7\x7a\x32\xa2\x5b\x87\x84\xf9\xfe\x6a\xfa\x0a\x99\xde\x5d\x8e\x88\x68\xf2\xfd\xd5\xc7\x1a\x7a\x30\x37\xe4\x03\xdf\xea\x21\xc7\xe9\x92\x43\x8e\xf0\x38\x73\x7c\x59\xc8\x60\xcc\x2c\x7f\x06\x18\x36\x50\x00\xe1\x5b\x64\xc1\x5a\xe4\xfc\xab\x39\x57\xc8\x95\xe5\x09\x11\xc8\x52\xcf\x19\x91\x60\x33\x70\xfe\x00\xd9\xd0\x1a\xa3\x27\x70\xf7\x2a\x18\x9c\x62\x60\x23\x72\x61\x84\x4f\x81\x0d\xca\xba\x41\xd6\x76\x7c\xb8\x85\xac\x09\x93\xde\xef\x1d\xd3\x2a\x82\x92\x80\x58\x1f\x8b\x84\xe0\x66\x3d\x85\xcd\xb0\xb3\xfb\x5d\xe0\x26\x67\x25\xf3\x64\x2d\x0d\xe8\xd6\x9a\x50\x06\xe3\x9b\xef\x77\x15\x74\xaa\x50\xd5\x48\x59\x0f\x3f\x8f\xdd\xff\x4d\x45\x2b\xe8\xc8\xcc\xb3\x6f\xb8\xdd\xce\x84\x23\xc1\x7b\xc8\x20\x16\x60\x21\xe4\x4e\x79\x06\x91\x33\xaf\x84\x72\x96\xba\x12\xa2\x33\x9b\xaf\xe4\xc2\x06\xf2\xbc\x34\x06\xda\x99\xfc\xe7\xa8\x67\x4b\xcc\xc0\x7d\xc9\xf7\xcf\x09\xf7\x2e\xdb\x89\x99\xa0\xba\x40\x46\x84\xd7\xd9\xe0\x01\x50\x56\x32\xa3\x99\x3c\x11\x6b\xe6\xc9\x39\xe1\x8d\x64\x72\xcc\xac\xd2\x43\x9e\x0d\x9f\x3c\x57\xcf\x13\x2b\x9c\xaf\x50\x62\x82\xa5\x29\x11\x1a\xb9\xc4\x1d\x1b\x2b\x71\x77\x01\x84\x6d\x2f\x51\xd8\xa3\xc4\x43\x51\x75\x2e\x88\x82\xfb\x8d\xfe\x19\xc1\x4e\x59\xf7\x4b\x85\xa7\xc5\x25\x66\x54\x97\xfb\x0b\x70\xe3\xf7\x1c\xa1\xf0\xac\xb7\x44\xe0\xbc\xc4\xca\xd0\xb7\xd0\xf4\x97\x58\x95\xbe\x77\x81\x47\xc3\x52\x36\xe9\x84\x1c\xf7\xfe\x0f\x8c\x5d\xe0\x81\x97\xfb\xeb\xdf\x54\xe6\xd0\xd4\x39\xa8\x0b\xf3\x87\x66\x24\xd0\x84\x25\xf2\xca\xa3\xdc\x5f\x5e\x8c\xa5\x94\xaa\x12\x7d\x48\x47\xf2\x42\xbf\xce\xf1\x3a\xcf\x03\x4b\xec\x7a\xa1\x70\x70\xe0\x41\x3f\xb5\xc4\xa1\xd8\x26\x2f\x1d\xcb\xfd\xf5\x01\x6d\x56\xe2\xa7\xa1\xc9\xcb\x3c\xc5\x50\xe8\x0e\x16\xd9\xd7\xee\x65\x57\x4c\xfb\xbd\x4f\xe6\x9e\xba\x4a\x9f\xe8\x21\xe0\x03\x24\x5c\x0a\x02\x7c\x4c\x81\x40\x09\xb0\xc3\xf5\x29\xf4\x53\x8a\xd4\xfb\x37\x14\xf1\x04\x95\x50\xe0\xbd\x9c\x53\x30\x2c\x3d\x80\x82\x2d\x48\x5f\xa3\x00\x41\x08\x4b\x50\x3b\x8c\xcd\x49\x31\x79\x25\xcc\xac\xb0\x3f\x05\x3a\xbd\xa8\xf0\xae\x85\xd6\xad\x00\x55\x9a\xe3\xc9\x82\x4c\x83\x51\x34\xaf\x95\x71\x93\xc4\xf1\x0a\xd6\xa1\x55\xff\xca\xc0\x39\x45\xad\x49\x28\xf4\x96\x8a\x02\x87\xda\x17\xb6\xb4\x73\xd8\xce\xb6\x90\xd8\xc2\xe5\x5a\x7a\xc0\x2d\xfa\x5f\x1c\x5a\x6c\x47\x66\x87\x41\x2f\x06\xce\x33\xd2\xdd\x60\x22\x8b\x65\xe1\x37\x04\xb1\xd8\x0a\x7d\x8b\x15\x0c\x8f\x20\x3f\x31\x15\x8e\x00\xf6\x2f\xb6\x1a\xc0\xa1\x29\x46\x0f\xab\x18\x6f\xc2\x8a\xd1\x0f\x06\x96\x99\x71\x7e\x77\xd6\x43\xd3\x14\xeb\x1c\xac\x33\x04\x2d\xc6\xeb\xcc\x42\xa1\x2c\xf7\xcf\x85\x9d\x18\xb8\x64\x52\x38\xe6\x8e\x46\x53\x10\x99\x14\x1e\x48\x96\x49\x8b\x59\x26\x44\x04\xd9\x13\x72\x33\x9f\xe8\x4f\xe2\xaf\x83\xd1\x32\x33\x21\x19\x7f\xde\xff\x09\x26\x9d\x8e\x05\x50\xc2\xee\xdf\x9e\x26\x30\x31\xbb\x10\x9e\xab\x50\xd9\xae\x67\x0b\xf5\xfe\x42\xe4\x57\xe3\x42\x1f\xec\x18\x72\x70\x0b\x6b\x5c\x61\x40\x8d\x60\xd0\x1a\x79\xe8\x5b\x63\x8f\x39\xd4\x38\x16\xc4\xb6\x6a\x1c\x9c\xb2\xde\x5f\xb3\x0b\xda\x5f\xac\xbc\x30\xc4\xc5\x63\xfb\x2a\xb0\x44\xf5\xfe\xe6\xa9\x4e\xa5\xe2\xaa\x72\x1a\x4b\x05\x7c\x52\xa9\xb7\x2b\xfc\x31\x64\x06\xc0\x1c\xac\xb8\xd8\xf8\x82\xfe\xa8\xbc\xe6\xa9\x90\xbe\xaa\xb2\x65\x94\xb0\xad\xde\xff\xc9\x8b\x09\xa6\x79\x8f\xd5\xe2\x92\x1c\xaa\x6d\x59\x5e\x31\x54\x83\x55\xa9\xf7\x0f\x99\xaf\x52\x3c\x2a\x83\xa3\xca\x73\xaf\x0a\x8f\xba\xda\xd0\xc4\x8a\x0b\xce\x47\xb5\x0b\xc4\xa8\xc6\x45\xcd\x4d\x42\x9d\x29\x86\x7a\xff\xa6\x2c\x28\xd9\xe9\x45\xf3\x20\xac\xd2\x07\xac\xb0\xf4\x80\xaf\x50\x27\xd1\xfb\x5b\xc0\xe5\x75\x0e\x4c\x68\xb1\x6b\x0f\xc6\x9b\x2b\xdb\xb4\x37\x24\x4f\xec\xc0\xe0\xa3\xda\x0a\x6b\x6d\xeb\xe2\xd8\xb5\x6d\xeb\x10\xcd\x36\x2c\x00\x01\x9f\x31\x4e\xb3\x74\x7f\x43\x91\x61\x4b\x50\x62\x06\xac\x10\x99\x96\x5c\x82\xa5\x11\x2f\x7c\x8f\xb9\x31\xcb\xd3\x4a\x4b\x3c\x44\x87\xe6\x07\xd3\x1a\x6d\x9b\x41\xa3\xd8\xae\xa0\x9b\xf1\x64\xc2\xd6\x39\xa2\x1d\x74\x41\x6d\x9d\x2f\xd9\xb1\xce\x68\x69\x27\x8c\xc7\xb4\x86\x68\xd0\x9e\x16\x2c\xc7\x60\x59\x20\x1c\x96\x0f\xa0\xcd\x32\xd8\x82\x57\x10\x3c\x98\xe6\x89\x9a\xe5\x0b\x44\xb1\xb2\x65\x3d\x2d\x18\x8c\xaf\xc1\x79\xb0\x86\x00\xd8\xda\x62\xc0\xfb\xa7\x01\x8f\xd6\xf8\x44\xc2\x96\x5f\xb9\xde\x58\xdc\x3f\x8d\x27\x23\xc6\x0b\x6d\x0b\xe6\x7f\x4c\xcb\x93\x39\x47\x92\xc3\xfd\xe3\x1b\xa2\x44\xaa\x4f\xc8\x2a\xaa\xe5\x19\x51\x71\x12\x67\x7e\xc2\x19\x34\x3f\x27\x68\x67\xbe\x8e\x18\xcd\xf5\x64\x5b\xea\x54\xc3\x36\xfd\xdf\x3a\x07\x36\xde\x51\x5b\x8f\x3c\xc5\xb4\x9e\x20\x5a\xd6\xe5\x85\xd1\x40\x0d\x8a\xa8\x0d\xaa\x09\x03\xcf\xda\xb5\x66\xbc\xc0\x02\xf7\xcf\x07\x37\xfe\x71\xbf\x4f\xe8\x0c\xfb\x5c\x13\xbe\xe0\x93\x37\x9e\xe0\x34\x9a\xc5\x16\x05\x73\x37\xc4\xe0\x35\x86\x06\x53\xd8\xe2\xfd\xee\x28\x7a\x46\x47\x2e\xf3\x8a\xad\xc5\x9c\x98\x83\x0e\x68\xf7\x57\xc6\x04\x8d\x97\x62\x2d\x66\x5b\x09\x88\xdd\x62\xc5\x2f\x66\xb4\xaa\xca\x4e\x95\x2e\x46\x8b\xf7\x7f\x3c\x9a\x6c\xb1\xdd\x5f\x80\x92\x01\xb9\xfd\x16\xff\xd1\x2d\x6d\x7c\x20\xd0\xa2\x33\x08\x6f\xd1\x65\x07\x54\x96\x19\xc6\xf4\x16\x39\x35\x70\xc5\xbc\xc7\x83\x79\xf6\xee\xec\x0d\xd5\xd3\xe2\xf2\xc3\x1a\xd8\xb7\x21\xe6\x0e\x2d\x2e\xa0\x28\xa0\x74\x34\x5e\x61\x35\x9e\x84\x34\x70\x70\x8b\x9f\x6c\x2f\x91\x57\xc7\x4d\x68\xb2\x1a\x58\x31\x22\x79\x20\xb3\x63\x77\x82\xa8\xa7\x51\xaf\x34\xd1\x2a\xa1\x49\xe6\x77\xde\x79\x7c\xd8\x24\x0b\xba\x64\x05\x07\x37\xc9\x59\x9e\x4c\x09\x20\xd4\x0d\xe6\xb3\x81\xf7\xd1\x6d\xdd\xfd\x35\x59\xd0\x50\xd4\x60\x34\x9a\xfc\x5b\x47\xb9\x6d\x2d\xc1\x61\x9f\x9b\xd0\x26\xb4\x75\x45\xd6\x84\xbe\x02\x22\xa3\xc4\x76\x99\x65\x45\xb9\x13\xe7\xf4\xde\x8d\xb3\x75\x02\xcc\x7e\x7f\x77\x58\xc1\x06\x8e\x83\x1f\xdb\xee\xef\x11\xb9\xba\xe1\xf7\x0f\xb4\x4d\x93\x17\x7e\x93\xb5\x3c\xae\x6b\x9a\x1e\x5c\xa0\x0a\x7e\x3b\x56\xa4\xf4\x2d\x9b\x72\x25\xfa\x84\xd7\xd8\x94\xa8\xd0\x6c\x60\x35\x2d\x4a\x9d\xb1\xb6\xa3\x15\x4e\x76\xd3\xca\xe6\x6b\x68\x08\x75\xd3\x86\x4f\x27\x8d\x94\x38\xd1\xce\x5b\xac\xc6\x7d\xd0\x5b\x6d\xba\xc8\xa2\x2f\xec\x20\xc7\x05\x2b\xc0\xe0\xe7\x27\x21\x86\xce\x02\x63\xdd\x32\x04\xa0\xd1\xc1\x6c\x79\x62\x6d\x99\xa6\xa3\xf1\xe2\xac\xc1\x35\x6d\x46\x5c\x52\x31\x35\x13\xb4\x31\xe9\x90\xbc\x66\x64\x77\xcb\x52\x01\x35\xad\x42\x48\x71\xb3\x0c\x76\xb1\x02\x2d\xd4\x8c\xa7\x37\x8d\xb3\x58\xc1\x46\xa8\x45\x9a\xf9\xd2\x17\x6d\xd9\xe8\x06\x91\x46\x65\x17\xd6\x76\x85\xfd\x6d\x06\x2d\xd8\x6c\xac\xd3\xde\x46\x81\x6e\x30\xd6\x8d\x17\x00\xcd\x25\xd9\x0b\xc9\x39\x89\x47\x97\xa2\x2c\x86\xda\x6c\x0e\xd5\xde\x5c\x2e\x96\x91\xa4\x7e\xbf\x6b\x82\x41\x6d\xae\x7f\x52\xe0\x0a\xf5\xde\xdc\xd0\x83\xaf\x74\x9a\x5b\x5a\x5d\x6d\x9f\xd4\x09\x6e\xa4\xa1\xdb\xc1\x87\x2e\xcd\xed\x74\x92\xd3\x0d\xcb\x74\x2b\x64\x1f\xa7\x8f\xd2\xdc\x1a\x67\x84\xb6\xe1\xa4\x53\x36\x70\xd1\xef\x96\xc9\x86\x33\x3d\x60\x5a\xda\x84\xa6\x6c\x70\x35\x90\xa1\x8e\xff\x53\xa7\x6d\xe6\x13\x99\x0c\x49\x9a\x99\x31\x4d\x9b\xb9\xb1\x06\x2b\x23\xbd\xf8\x4c\xa6\x81\x09\x33\x13\x64\x80\xe1\x09\x2e\x0b\x6d\xfa\xfd\x1d\xfe\x4d\x81\x17\xf1\x6f\x42\x0b\xfe\x9b\x52\x56\xc6\x85\x49\xb7\xf0\x6f\xd2\x6a\xc3\x31\x2f\xd0\xe8\x70\xba\x93\x20\x81\x9e\xf7\xfb\x8b\x77\x20\x1e\x37\x8d\x80\xf8\x5c\x94\xf3\xb8\x6b\x8a\x39\x38\x23\x04\xa2\xc3\x23\x28\xec\xeb\xbc\xcf\x11\x97\x06\xe7\xe1\x83\x23\x28\xdd\x99\x1b\x80\x9d\x35\x9d\x8d\x59\xf0\x09\xf0\x42\x96\x97\x9a\x2e\xff\x7b\x52\xe8\xf2\xf7\xda\xc0\x65\xbd\x6e\x71\xe1\x2b\x0e\x17\xbe\x62\x80\x29\x1c\x31\xf0\xc5\xc6\x0b\x95\xeb\x02\xd7\x25\xb9\x30\x3b\x08\x79\xbd\x07\x8d\xe9\xb2\xf3\x28\xd6\x65\x67\x0c\xe5\x72\x50\xfb\xb8\xac\xc3\x59\x97\xf5\x6a\xc7\xe5\x98\xa7\xa2\xfc\x84\xe4\x3b\x6f\x68\x5c\xce\x8c\x26\x27\x19\xcb\xe5\x71\x7f\xa3\x25\x84\x77\x1d\xc8\xd2\xb8\xb9\x64\xee\x49\xb2\x5c\x4c\x14\x6e\x88\x43\xcd\xb1\x61\xb6\x67\x70\xd2\xc1\x65\x45\x11\x3c\xdf\x77\xa9\x08\x77\x5d\x78\x68\xe4\xd4\x0b\x2e\x8d\x67\x03\x2e\x4d\x06\x4b\x9b\x71\xe6\x36\x34\x07\x97\x8e\x5f\x8a\x44\x47\x87\x42\x70\xe9\x4d\xd8\xa1\x2f\x38\x8b\x60\x89\x43\x1d\xd9\xc1\xa3\x2e\x47\xe4\xcd\xea\x59\x39\xe8\x75\x7f\x63\xa4\x8b\x8a\xc4\xe5\x33\x40\x77\x7a\xa0\xce\x74\xde\xef\xc3\x30\xef\x11\x09\x29\xa7\x47\x0c\x7e\xbf\x4f\x92\x54\x4f\x2c\x5b\x2b\x9f\x26\xb9\x2e\x6d\xcd\xd3\x68\xd7\x7f\x13\x72\xc3\x47\x33\xae\x03\xbb\x84\xea\xe1\x45\x8f\xf3\x9a\x0f\x92\x06\x00\xff\xc7\x6d\x5f\x10\x94\xb3\xf5\xba\xcd\x0d\xd4\xb4\xe7\xea\x01\x42\x19\x7d\x38\xb7\xd2\x58\x53\xf1\xc3\x3a\xe9\xc4\xb8\x35\x82\xd5\x04\xb3\xd2\xf7\x77\x63\x70\xeb\x7c\x0a\xe8\x73\xbb\xdf\x80\x58\x36\xbc\x45\x87\x88\x04\x9f\x24\x31\x4f\x01\x9c\x81\xa7\x2f\xbf\xde\xe1\x38\xf8\x44\x84\xeb\xb3\xb0\x53\xe3\x2b\x48\x9e\xb2\xfb\x1c\x68\xdb\x21\x27\xbb\x85\xce\x73\xd4\xce\x23\x9f\xce\xdb\x8d\x1e\x61\x1e\x7a\x3c\xe3\x0b\xd0\x57\xab\x1c\x01\xd6\x27\x16\xdb\x23\x44\xbd\xc7\x25\xea\x3d\xe6\xbf\xa4\xb3\xdd\x60\x83\xb9\x03\x5e\x1c\xad\x6c\xa8\xf8\x3b\xc1\xef\xb1\xd2\x1d\xea\xb1\x0a\x6b\x2b\x22\x94\x1e\x2b\x05\x87\xc7\xbc\x9d\x87\x15\x3d\x36\x00\xf8\x07\x3d\xfa\xce\x85\x47\x1f\x60\xe3\x1e\xfb\x60\x27\x3e\xa7\xe9\xbc\xe4\xe9\xf1\xc3\xf8\x3c\xa9\xff\xef\x38\xa8\x4b\x32\x00\xb0\x12\xd2\x11\x43\x97\x3d\x74\x39\x27\x96\x2f\xda\x43\xe7\x25\x7e\x97\x7c\xa1\xae\x20\x9e\xef\x52\x48\xcc\x4e\x26\xea\x52\xa1\x43\x79\x3f\x98\x99\x30\xb7\xfc\x9b\x2e\x4d\xd1\xe4\x1f\xcf\xaf\x3b\x70\x29\xae\x02\xb8\x30\xb3\x0e\x89\xbb\x74\x0a\x48\xff\x3b\x52\xea\xc2\xcc\xf8\x2b\xbc\x88\x52\xf9\x20\xc0\x4a\x15\xf6\xb8\xaf\xeb\xa2\xae\x70\xa7\xba\x9e\x58\x26\x2f\xae\xfb\xfd\xce\x11\x08\xd5\x0c\xf5\xdf\x35\x0b\x5f\x82\xf6\xb5\xea\xfb\x5d\x36\x63\xe3\xc2\x42\x87\x77\xd2\xb5\x0f\x18\xc4\xce\xe3\xa1\xae\x7c\xa6\xdc\x69\x3a\x3b\xbd\xff\x4e\xab\xd9\x2d\xe3\x17\x5b\x44\xb2\x93\xf8\x96\x79\x73\xdc\xef\x1f\xfa\x8a\xdd\x78\x29\xd7\x2d\xcf\x3f\x24\x1b\x0f\xc9\xbb\x55\x48\x42\xb7\xba\x5a\x55\x38\xc2\xdd\x2a\xa5\xa9\x1b\x47\x6c\x99\x3d\xd7\x6b\x81\xce\xab\x89\x6e\xbe\xee\x79\x3b\x0a\x91\xef\x8b\xc0\xf7\xcf\x20\x27\x4c\x04\x83\x7d\x6e\x40\xe3\xa4\x9d\xeb\x34\x44\x7d\xca\x89\x69\xe9\x89\xf6\xe5\x59\xf5\x15\xfa\xf6\x79\x38\x9b\x33\x3c\xea\x33\x2f\x26\xe1\x3d\x52\x9f\x70\xbf\x98\x92\x85\xe7\x32\xf0\x7d\x36\xaa\xb5\x3e\xf1\xed\x89\x5f\x7f\x63\xfa\xc9\x86\x9d\x63\x41\x93\x8d\xc8\x27\xea\x23\x6e\xd0\x18\x48\x73\x04\xbc\x7f\xc3\x58\x15\xd0\xe3\x7c\x0f\x3a\x22\xb6\x3c\xe8\x74\x8f\xb8\x4e\x1b\xd7\xeb\xc5\xb1\x84\x66\xc4\x42\x3b\x31\x62\x81\x84\x0f\x5a\xa1\x11\xeb\x1a\xb8\xa1\x5d\x03\x03\x8c\x08\x4e\x1b\xb1\xad\x4e\xff\xa6\xae\x41\x7c\x47\x9d\x0b\xbf\xa1\xe8\x46\xf4\x27\xd8\x6b\x44\xb7\x01\xe8\x18\xcf\x59\x32\x66\x7c\xa2\xf9\x64\xd9\x0b\x45\xb4\x5f\x43\xf8\xca\x65\xd0\x2d\x1e\x92\x30\xf2\xfd\x9d\xf8\x46\x66\xc8\x13\x6c\x30\xe4\x29\x0e\xa8\xcc\xa0\x85\xe4\xfb\xfb\x40\x24\x42\xce\x1a\x02\x65\x33\xd6\x63\x81\x21\x35\xbe\x00\x77\x76\xaa\x0b\x6a\x07\xec\xa8\x36\x5e\xbe\x21\x9c\xe0\xb6\x04\x18\x1f\xf7\xb7\xf3\xd9\xdd\x10\xaf\xd0\x58\x03\x2e\x2f\x7a\x76\xf6\xec\xc6\x35\xf6\x81\x20\x70\x08\x63\x91\x41\x81\x19\xf2\x0a\x43\xa1\xc4\x86\x6e\x93\x27\x6a\x43\xa5\x34\xe4\x29\xc4\x43\x79\xcd\x34\x14\xfc\x33\x14\xfa\x66\xe8\x93\x03\xf0\x02\x64\x28\xcf\x86\x07\x9c\x0a\xec\x0f\x7e\xd0\xe0\xa3\xaf\x01\xcb\x30\xee\x77\x83\x75\x19\xca\x21\xd9\xed\x6f\x16\xb2\xd6\xb8\xdf\x43\x56\xff\x01\xf5\x3b\x14\xb8\xb5\x45\x67\xdb\x18\xe9\x0f\x83\x62\x1d\x96\xb8\x43\xc3\x2c\x76\xa2\x3a\xf3\xb3\xb0\x92\x55\xe4\x11\x6b\x2c\x68\x12\x06\x5f\xb5\x8d\xfb\xc7\xe3\x47\x18\xc6\x30\x7f\x98\x17\x2a\x0f\x98\x48\x61\x9e\xa0\x09\x07\x73\xac\x85\xcf\x4c\x86\xf9\x98\x9c\xa6\xe3\x87\x3d\xf0\x6d\xd5\x80\xb3\x87\x9c\xc7\x8d\x7c\xea\xeb\x3e\x7e\xbd\x48\x1e\xff\xbb\x0b\x1c\x8e\x48\x72\xf0\xf6\x73\x78\x2c\xfc\x86\xbf\xb5\x4c\xf2\xf0\x08\xcf\x6e\x38\x5f\xdb\x0e\xbf\xbf\x37\xcb\x61\xc0\xbf\x45\xa9\x2c\x0c\xba\x54\x00\x6e\x08\x4e\xc0\x70\xdd\x26\x20\x87\x46\xb4\x30\x9c\xcf\xf8\x86\xeb\xac\x07\x0a\xed\x10\x26\x85\x95\xb4\x98\x83\xc6\x72\xf0\xe1\xea\x70\x38\xd5\xc3\x27\xcb\xf9\x4c\x75\xf8\x04\xf3\xcf\x6d\x5d\xeb\x8e\xb9\x59\x18\x93\x6f\x14\xc6\x84\xf9\x19\x34\x86\xe3\xfe\xad\x92\x99\x90\xb9\xa7\xf3\xf9\xe9\x98\xce\xd3\xc1\x31\xe1\x71\x0c\x3e\xaf\x9e\x1b\x23\xa5\xfb\x37\x33\x66\x9c\xd0\x72\x39\xcc\x65\xa5\xe8\x8a\xcc\xaa\x17\xe2\xb1\x30\x2b\x7e\x50\x8b\x0c\xb1\xa6\xd3\x09\x9d\xbe\x49\x98\xbe\xae\x7c\x27\x62\x2b\xfe\x0d\x64\xf6\xc9\xe7\x4a\xeb\xce\x69\x0e\xe3\xab\x8f\x79\xc5\x70\x21\x0c\xba\x62\x02\xcb\x5d\x91\x6f\xc2\x2e\x3e\xe4\xbf\x40\x85\x2b\x2a\x0b\xd6\xd1\xed\x15\xb3\x84\xeb\x2f\x7e\xbf\xf8\x6e\xea\xe2\xa3\x56\x94\x5d\x93\x2d\x4a\x83\x1f\x75\x45\x47\xc6\x95\x03\x91\x6d\x2f\x84\xc6\x97\x90\x15\xaf\x75\x59\x72\xc9\xe3\x7e\xf3\xc0\xef\x02\xd9\x24\x5c\xf2\x94\x57\xe0\x21\xd6\x25\x34\xfa\x97\x64\x43\x09\x56\x21\x7c\x11\x7b\x51\xb8\x2e\xa9\xc2\x81\x2a\xd7\x2a\x40\xcd\x45\xee\xbc\xa4\xce\x1e\x2e\xb6\xe4\xad\xf2\x25\xbe\x11\xee\x98\xc0\x85\xbd\xfd\x49\xc8\x25\xf9\x40\x63\x20\xe4\x52\x30\xdd\xa5\x1b\xb4\xf5\xc5\xa3\xa4\xeb\x7e\x27\x5e\x0c\x5d\x8a\x8e\xf7\x1b\x06\xe7\xd2\x1d\xd8\xbc\x14\x7e\x31\xef\xef\xa4\x87\x8b\x5e\xde\xa5\x19\x3f\xec\x40\x6b\x84\xd0\xf3\xc5\xd6\xa5\xf7\x7f\x90\x93\x4b\x2d\xdf\xef\x1a\x2e\x05\x61\x2f\x75\x20\x59\x7d\xcc\x3d\x5c\xda\x89\xca\x77\x67\xb0\xbe\x5c\xcd\x4b\x47\xe4\x09\xe0\xa5\x93\xdd\xaf\xf8\x02\x24\x6e\x14\x76\xfe\xd2\xcb\xc2\x65\x99\xf7\xa7\x97\x65\xba\xb3\x97\x65\x62\xc0\x1c\xcd\xe9\xd3\x5d\x08\xa7\x2f\x20\x93\xd6\xeb\x9a\x7c\x98\xf9\xc9\x0b\xec\x4f\xf8\xc7\x9f\x94\xa0\x4f\xe8\xd5\x4f\xde\x48\x7e\x42\x71\x7d\x42\x6b\x7c\x42\x6b\x7c\xda\x39\x3d\xbc\xe2\x01\x02\xbf\x78\xd4\xfa\x8a\x0d\x22\xf9\xe2\x1b\x85\x97\x55\x00\xe8\xfe\xd7\x2c\x00\xb0\xb5\xff\x1f\x00\x00\xff\xff\x11\x91\x1a\xde\x5b\x35\x00\x00") +var _keysWordlistSpanishTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x5b\xbb\x76\xfc\x2e\xaf\xed\x79\x4b\x8c\x65\x8f\xe6\x00\xe2\x27\xc0\x2b\x99\xb7\x49\x99\x62\x8a\xff\x4a\x97\xd6\x2f\x76\xd6\xde\xe4\x2b\x46\x98\x3b\xe8\x2e\x60\xee\xaf\x2d\x26\x0b\x71\xdb\xad\x48\x0d\x71\x93\x67\x0c\x71\x53\xf1\x81\x52\x3b\xe3\xce\xb4\x12\xae\x42\x8f\x2f\x26\xea\x21\x6e\x53\x32\x32\xb3\x5b\x88\x29\x6e\xd1\x91\xec\x52\x34\x86\x98\x92\xb0\x38\xe9\xfd\x53\x43\x4c\xa2\x43\x90\xe4\x13\x95\x52\x31\x5a\x92\x36\xa2\x87\xfb\x2b\x29\x66\x4a\x39\x3a\xc7\xa8\xf7\x77\x88\xc9\x4e\x41\xc6\x38\xcc\xd0\x8b\x09\x81\xeb\x0b\xc9\x64\xe3\xb9\x2b\x13\x71\x8e\x31\x3b\x4a\x77\x65\xd3\xbd\xe8\x40\xed\x6e\x9c\x28\xee\xe6\xd8\xcc\x3e\x63\x8d\x48\x32\x1a\xdd\xdf\x2e\x16\xe2\x21\x89\x6d\x0e\xfd\x5b\xf2\xa1\x75\xe5\xbd\x70\x91\xa7\xe6\x10\x4f\x65\xa3\xd3\xea\xfd\x8e\x48\x3b\x86\x38\x6d\x95\xba\x9c\x2b\x55\x14\x4e\x34\x98\xbb\xa1\xef\xd4\xcc\x1c\x30\xfc\xb0\xd3\x00\xdd\x2d\x44\x75\x09\x51\x7b\x46\xbf\xa7\xec\x2e\x2f\xa4\x58\xe5\x73\x76\xa0\x2c\xc7\xe4\xf7\x57\xc5\x47\xd9\x9c\x05\x5e\x62\x88\x79\x8b\xe1\xfe\xca\xdb\x2c\x21\xe6\x14\xf3\x8e\xaa\x5d\x50\x23\x27\xdb\xc9\x13\x83\x66\xf1\xc1\x42\xc2\x43\x33\xb0\x4a\x2a\xe4\xd3\x76\xee\x34\x2b\x29\x9d\x75\x91\x25\xeb\x85\xf5\x67\xce\x52\xc8\x14\xb9\xdc\x6f\xd2\x37\x8f\x05\xe5\x85\xd2\x45\x15\x62\x31\x8f\xe9\x28\x9a\x05\x6b\xcf\x2f\x34\x2b\x71\xcb\x82\xa4\x0e\x26\xcd\x80\x84\x12\x1d\xfb\x2f\xb1\x13\xad\x65\xfb\x4b\x14\xc3\x14\x6e\xbd\x28\x5b\x68\x1f\x71\x0f\xb1\x18\xc6\x6a\x11\xe8\x2a\x2d\x63\x6d\x35\x3d\x08\x35\x56\xa6\x18\xb7\xee\x98\xb3\xee\xf7\x77\x0d\xb1\x92\x0b\xef\xaf\x7a\x4e\xf0\x68\xd5\x9c\x41\x87\xaa\x05\xb9\xfb\xdd\x43\xac\x8b\x68\x75\x08\x98\xa1\x0e\x3d\x27\xea\x86\x3d\x91\xcc\x98\x01\x49\x97\x3a\x6b\xc2\xac\xf7\x7f\x91\xcc\x76\xff\x27\x4f\x66\x2d\xc4\x16\x49\xf2\x16\x3d\x62\xfd\x4d\x06\xf7\xd1\xd0\xbe\x65\x4d\xac\x34\xa0\xb7\x99\x03\x0d\xcd\x3e\x91\x71\xa9\x3b\x28\xd1\xdc\x88\xd8\x36\xa5\x83\x42\x6d\x62\x9b\x4e\x82\x38\x66\x0c\x14\x8a\xfb\xcb\x37\x1d\x6e\xfc\xb0\x1c\xa2\x6f\x93\xac\xe7\xe9\x41\x22\x38\x24\xd9\x39\xa4\xef\x9a\x81\x10\xdf\x27\xdb\x0b\x10\xe1\x14\x31\x57\xe9\x21\x7a\xf9\x63\x5f\xaf\xf7\x37\xf2\x06\x52\x7b\x23\x20\x47\xb8\xcb\x09\xbc\xb9\xdb\x0b\x70\x82\x5f\xb8\x7c\x1f\xca\x75\x76\xfe\x30\x66\x5f\x0c\xd0\x93\x54\x88\x6a\x97\x73\x52\x8c\xbb\x30\xd7\x41\xbd\xfe\xc7\x5a\x5d\x33\x61\xa7\x58\x76\x10\xaf\x5b\xd9\xb8\xaf\xde\x04\x5b\xef\x63\xad\xbe\x8f\x95\x9b\xec\x37\x0b\x3b\x4c\x8e\x32\xe2\x93\xf0\xdf\x14\x24\x1e\xe2\x58\xc3\x0f\xc1\x40\x43\x81\x8b\x41\x8e\xbf\xbf\x86\x81\xe4\xc3\x23\x50\x33\xb8\x9f\x71\xff\xd6\x10\xe7\x1e\x5f\x80\xa0\xd4\x3c\x25\xc4\x89\x69\x67\x59\x43\xcd\x2e\xe4\xda\x39\xb0\xfe\x0b\xdc\x70\xc5\x9a\x04\x09\x16\x76\xe1\x4b\x72\xa6\x26\xb9\x64\xc1\x3e\x7c\xbe\x42\xbc\x96\x02\xb9\x14\xf8\xf8\xc4\xbc\x9f\x73\x8f\x80\xd8\xf0\x2b\x1e\x4b\xa0\x29\x23\x2f\xc3\x2c\xaf\xfb\x97\x9c\xf2\x9a\x07\x44\xf7\x35\x73\xd8\xe2\x16\x01\xcc\xc3\x16\xd3\x43\xc2\x16\x1f\x20\xda\x16\x35\x23\x03\xe1\xde\x62\x8e\xf5\x85\xb2\x9c\x30\xe5\x46\x35\xb0\xc5\xb2\xdd\xbf\x61\x8b\x35\x19\xe0\x8e\x06\x60\xd6\x2d\x3a\xc7\x74\x96\x7b\xd5\x17\x12\xb7\xb0\xdd\x5f\x3d\x61\xfb\x5b\xec\x63\x0d\xd4\x21\xce\x5b\x1c\x31\xb3\x78\x88\xaf\xc9\x41\xb8\x2d\x8e\x39\x38\xe8\x2f\xd6\x89\x7d\x6c\xb2\xdd\xdf\x80\x8a\xd9\x04\xd2\xb6\x49\x67\x45\xe7\xe7\xd0\x18\x36\x85\xd8\x6e\x2a\x35\x6c\x5a\x4f\x0b\x5b\x5e\x6b\xcc\x06\x52\x6e\x79\xf6\x18\x36\xc3\x6f\xd3\xca\xc4\xc2\x66\x09\x5f\x69\x15\xec\x04\x72\x22\x59\x25\x99\x00\xac\xb3\x59\x66\xff\x82\x4d\x5a\xdd\xe3\x8e\x04\xe2\x48\x1b\xb6\x59\xed\xf7\x97\x86\xcd\x1c\x48\x32\x07\x97\x6e\xd6\x39\x35\xa8\xb0\xd9\xb8\xdf\x35\x6c\xf7\xcf\x25\x9c\xe7\x15\x73\xd8\x3c\x5e\x16\x96\xdd\xdb\x5c\xd2\x23\x22\xb9\x24\x6c\x4e\x9d\xb2\xb9\x72\x0b\xae\x98\xdb\xb9\x58\xca\xd3\xe6\x06\x76\xd9\x9c\x43\x3b\x34\xff\xe6\xb3\xb3\x2d\x78\x7a\x9b\x49\x08\x41\xcd\x09\xb5\xb7\x4d\xf9\x0c\xdb\x3c\x16\xc5\xe6\x41\x42\xdc\xbf\x40\xd9\xd4\xe1\x68\x96\xd9\xd1\x37\x8e\x36\x3d\x13\x62\xeb\xb3\x83\x7f\xb6\x39\x22\x16\x30\x5f\xe8\x0b\x93\x8c\x25\xa6\xb8\x41\x5d\xa7\x48\xa4\x26\x18\xf1\x90\x62\x8a\xa8\xd9\xef\xaf\x4b\x1c\x1f\xc2\x3a\x7e\x1f\xf7\x77\x48\xf1\x7e\xef\x28\xd1\x02\x66\x4d\xf1\x89\xcc\x73\x8d\x9b\xf1\x83\x22\x47\x0a\xd5\x08\xfb\x43\xa8\xc0\x7a\x8a\x39\x0b\x60\x41\x9f\x6c\x6c\x76\xa1\x9e\x05\x65\x63\x8f\x22\x6b\x71\x45\x2b\x93\x66\x21\xdd\x5f\x35\x71\x09\x75\x57\x4c\x52\x25\xa3\x47\x3d\xa1\x15\x53\xac\x9a\x98\x1d\xc8\x40\x37\x02\xae\x25\xd9\x86\x9c\xf5\x90\x62\x8b\x2f\x40\x1d\x6b\xe1\x0d\x04\x48\x91\x1e\x40\x8a\x6d\x82\x84\x29\x12\x07\xbe\xb1\xf3\xfd\xe5\x49\x30\x9d\x43\x65\xa4\xe8\x27\xa1\x42\x66\x52\xf4\x8a\xee\xde\xfe\xea\xb8\x10\xe7\x77\x27\x48\x28\xe8\xc2\xf2\xde\x58\x34\xb8\xe5\x61\x9e\xd0\x15\xa4\x4b\x50\x37\x98\x62\xb2\xd3\xcb\x42\x92\xcd\x20\x5b\x49\xa0\xb4\x93\xec\x18\x40\x32\x70\x7e\x7f\x67\x81\xa9\x4f\x92\xe1\xfd\x20\x3f\xd9\x72\xe9\xa6\x24\x55\x41\x4f\xa9\x83\x7d\x1c\x48\xa1\xfb\x93\xc4\x49\x69\x59\xe5\x60\xf0\x24\x4e\x63\x9d\xee\xef\xde\x64\x0f\x49\xd8\xe9\x11\x49\xc5\x47\xcc\x92\x98\x2d\xed\xfe\x45\x4a\x5b\x9a\x1e\xb1\x11\x3a\x33\xca\x26\x0a\x77\x64\x59\x9b\xf4\xa0\xc0\xa6\x87\x61\xe4\xc7\xa4\xaa\x4d\x8f\xd9\x30\xa1\xa6\x4c\xac\xaa\x9c\x06\x98\x09\x59\x00\x1f\x32\xe9\x01\xdc\xeb\xb9\x50\xa9\x60\x09\x8a\x50\x52\x20\x5a\x2b\x86\xd2\xe6\xb0\x4c\x49\x9d\x15\x3e\xc9\x07\xda\xd9\x82\x0d\x26\x19\x2d\xd3\x39\x48\x39\x56\x00\x8c\x97\x63\x17\xc0\x0b\x50\xa9\xc3\x53\xe6\x24\xf9\x7e\x2f\xfe\x31\xe2\xd6\xfe\x5c\xd3\x64\xe9\x41\x0e\x5c\x2a\x26\x19\x66\xbc\x7f\x76\xb8\x20\x09\x86\x3b\xd9\xc1\xf6\x70\x47\x93\x3d\x04\x23\xda\x13\x9a\x22\xc1\x55\x48\xd0\x40\xc9\x32\xd9\xca\xb2\x9c\xca\x32\x78\x05\xc9\xf2\x1a\x32\xe7\x95\x2b\xac\x9a\x85\x85\x05\x5a\x15\x29\xc7\x2d\x4a\xca\xff\x94\x35\x65\x69\x40\x92\xd5\x1d\x2d\xaa\x70\x9e\x7a\xb2\xc8\x28\x21\x56\xfb\x5f\x29\xf9\xda\x40\x2f\x6b\x0a\xe8\x71\x89\xbf\x39\xf4\x37\x52\xa8\xdd\x64\xbe\xff\x15\x1b\xe7\x77\xe7\x38\x7d\xc1\x02\xd1\x31\x98\x76\xba\x9b\x62\x4c\x07\x2a\x5d\x22\x61\x5a\x99\xfb\x8d\x15\xba\x14\x36\x7d\x03\x2a\xe2\x87\xe4\xda\xd8\x5d\xbb\xf6\x90\x1c\x76\x37\xf9\xfd\xb3\x90\xee\xe0\x18\x56\x4f\x76\x9f\xaf\x90\x66\x24\xd3\xcf\x48\xbe\x98\x91\x9c\x39\x37\x02\x44\x18\x09\xb2\x0a\x3c\xcc\xa5\x2a\xe6\x62\x7f\xb8\xfa\x2c\xe4\x6a\xa7\x5c\x80\x0a\xef\x2f\x4d\x08\x0e\xb2\xb9\x11\xb2\x39\xdd\xe6\x34\xe1\x3a\xa2\x09\x36\x3f\x2b\xd7\x32\x8d\xb0\x2d\x2d\xf0\xdb\x28\x65\xf4\x5e\xd2\x74\xa5\xec\x4d\x5f\x90\x93\x0c\xed\x61\x87\x12\xdb\x69\x76\x31\xe5\x1e\x21\x78\x3b\xbc\x8e\x1c\x76\xd9\xc4\xc3\x7e\x7f\x6f\xc8\xdc\xdf\x29\xee\x31\xec\x92\xd4\xc3\x2e\x68\x26\x87\xd4\x8e\xa2\x43\x2b\x0b\x61\xc5\x77\xc9\x07\xd8\x69\x47\x70\xc4\x56\x19\x46\x6b\x97\x62\x8e\xb6\x70\xab\x76\xa9\x23\x62\x82\xe5\x45\xee\x02\x53\x84\x62\x77\xec\x61\x97\xbe\xbc\x8b\x5d\xe0\x76\xed\xd2\xe1\xe8\x23\xad\x93\x23\xf6\xa1\xab\xf6\xba\xdf\x48\x07\x55\xf4\x2e\x43\x2a\x56\x2c\xf0\x4f\x76\x10\x73\xd7\xb8\x65\x43\xb2\x83\xc2\xbb\xfe\xb9\xef\xbb\xc2\xd3\xd9\x35\x22\xb6\xd9\x75\x9b\x4f\x24\x0c\x99\xf6\x25\x66\xbb\x02\xa7\xbb\xca\x2b\xec\x7a\xdc\xef\x04\x1c\xe8\x89\x69\x35\xaf\xb1\xf2\xc4\xa6\xb5\x42\x3f\xed\xea\x82\x20\x6d\x57\xd7\x93\xc5\xd0\xa4\xbb\x76\x81\xda\xdd\xb5\x1f\x1e\x31\xd2\x85\x8e\x17\x57\x6f\x08\x27\x76\x4b\x00\xb0\x2a\xbb\x15\xba\x11\xbb\x55\xfc\xb0\x14\xa3\xe7\xbc\x9b\xc3\x5f\xdc\x0d\xc4\xdb\xad\xe3\x07\xd2\x79\x3c\x41\xea\xdd\xed\x8c\x61\xa7\x25\xd8\xb9\x73\x46\xb2\xfb\x5c\x53\xcf\x8c\x19\xee\x5f\x7c\x42\xcd\xed\xe4\x88\x7d\x52\xb7\xee\xb0\x44\xf7\xf7\x86\xc0\x43\x36\x20\x03\x3e\x81\x07\xa8\x51\x01\x47\x9b\x07\x81\x6e\x92\xfd\x2f\x90\x94\x5d\x11\x53\x1a\x3e\x06\x6b\x27\x6c\xb5\x1c\xdc\xbe\x1c\x9a\xe2\x2b\xc8\x53\xf0\x2b\x2d\x5b\x90\x2c\x07\x71\x2e\xd0\x26\x8e\x64\x29\x7e\xc9\x72\xa1\x67\xd6\xd6\x25\xdc\xdf\x59\xd9\x48\x3f\xd8\xc8\xa0\x79\x24\x33\x1e\x96\xb2\x81\xee\xb2\xe2\x5f\x29\xf6\xb7\x94\xd2\xa0\x73\xa4\x34\xee\x14\xd3\x09\x13\x97\x1e\x83\x54\x6e\xaa\x26\x06\x68\x52\xd3\x63\x1e\x82\x14\x7c\x21\x88\xa8\x58\x0c\xe2\x49\x3d\x80\x67\xa9\x87\x78\x41\x7a\xd2\xc1\x94\xaa\x67\x41\xdb\x1c\x13\x7a\x9a\x17\x24\x2e\x6c\xdb\xe3\x27\x13\xb9\xff\xc3\x2e\xea\x58\x23\x0d\x67\xee\x82\xe2\x96\x4a\xfe\xbc\xbf\x1b\x1c\x29\xf9\x37\xb5\x59\x10\xd7\x97\x05\xe9\xf0\x39\x90\xc0\x53\x91\x0e\xbd\xeb\x48\x5d\x37\xe5\x07\x77\xdc\x05\x51\x61\x90\x7e\x88\x33\x99\xe2\xec\xdd\x20\x8b\xd2\x1b\xb4\xa6\xf4\xc6\x3d\xf5\x66\x9d\xc9\xc4\xaa\xfb\xbf\x79\xbf\x03\xb4\x0a\x86\x03\x9e\x10\x8b\xa0\xf5\x98\x47\x0c\x32\x60\x14\x65\x88\x57\xac\x70\x40\xad\xc9\xa8\x98\xec\x62\x5c\x28\x57\xcc\x13\x7d\xaf\x45\xad\x8b\x67\x05\xf2\xc1\x63\x0b\xf9\x40\x6c\x1b\xe4\x83\xe7\x22\xf2\x91\xe0\x08\xc8\xc7\x6a\xf9\x41\x09\x90\x0f\x45\x70\x2b\x1f\x2b\x3c\xba\xbf\x3f\x94\x95\x8d\x76\x53\x3e\xfe\xc2\x49\xf9\x68\x06\xa1\x95\x8f\xe1\x52\x2c\x1c\xf7\xd7\xe6\x58\x0c\x3e\xa0\xc1\x8e\x98\x1e\xd8\xec\x71\x7f\x41\x06\x0f\xcc\xef\xe1\x88\xc0\xdb\x01\x3f\xee\x88\x70\x33\x0e\x3a\x87\x47\xcc\x9d\x10\x6b\x3d\xa0\xdb\x8e\x58\x34\x2b\x53\x63\x95\x47\xf0\xce\x11\xbd\xc4\xc4\x72\x37\x8c\xea\x1d\xdf\x5d\xc2\x11\x87\x9e\xf8\x9e\x9c\xe0\xe2\x64\x1f\xe1\x80\x0f\xe3\x16\x0e\x3a\xcd\x87\x64\x7d\x85\x43\x90\x77\x8c\x22\x08\xc5\x8e\xfb\xdb\xa1\x38\x0f\x71\x76\x93\x4e\x17\xfc\x50\x9e\x1c\x1c\x4a\x35\x7b\x28\x96\xa6\x50\xec\x87\xfe\x59\xed\x43\x39\xa8\xee\x18\x50\xe9\x2d\x1d\x2a\x19\x80\xcd\x68\x1b\x0e\x45\x28\x1a\x0e\x7d\x72\x80\x27\x9a\x02\x3f\x9a\x61\xc4\x0f\xec\x12\x3d\x32\xec\xce\xa1\x18\xb4\x02\x8d\x5a\x41\x0d\x68\xe8\x81\x72\x07\x4e\x72\x4c\x06\x88\xb8\xe7\xc8\x6b\x47\x50\x41\x47\x36\x96\x40\xb1\x1d\x19\x4a\xf1\xc8\xf7\x2f\x2a\x6c\xc3\x2e\xc1\xc6\x87\x9d\xb0\xc3\x87\x51\xf9\x1c\x06\x22\x1f\x96\xb3\x60\x78\xab\x3b\x20\x27\xe1\x89\xd0\x61\x3e\x88\x48\x73\x04\x56\x07\x38\xf4\x30\x34\xf5\x98\x22\x08\xe2\xeb\x2c\xea\xf0\x58\x41\x4c\x27\x0d\x3c\xce\x1d\x89\xdc\x6f\x47\x52\xd1\x10\x52\x7d\x38\x24\xea\x70\x6e\xc6\xb9\xfe\x09\xcf\xec\x98\xd4\xda\x94\x0f\x94\x81\x82\x13\x2e\xfd\x31\xeb\x1f\x8e\x27\x02\x91\x63\xfa\x5a\xf7\x24\xd9\x66\xc7\xd4\xf7\xef\xd8\xc0\x04\x73\x40\x1d\x9e\x31\xc1\x3f\x3b\xe3\x11\x7b\x38\x23\x1c\xb4\x13\x21\xfa\x19\x59\x9a\x57\xec\x78\x92\xdf\xce\x88\xf0\xec\x8c\xd0\xd6\xe7\x3a\xc7\x39\x23\x3c\x9b\x33\xc2\xce\x9d\xd1\xe3\x53\x90\xbc\x50\xd4\x97\x07\x75\x46\x0a\xe5\x19\x07\x5a\x5c\x9a\xe1\xd9\x9f\x52\xa0\xb5\x4f\x81\xaa\x3f\xa5\x86\xf3\xfe\xa6\x72\x3a\xa5\x2a\xe1\x90\x70\x8a\xc7\x95\xf3\xff\xe5\x21\x86\xa7\x74\x0c\xa5\x27\xf5\xec\xa9\xa5\xc6\x8e\x56\x0a\x5d\x74\x2a\x06\xc9\x60\x76\x0f\x67\x46\x10\x7a\x66\xc3\xee\x4f\xcb\xf8\x1d\x06\x08\xe1\x38\x2d\x37\x09\x27\xe2\xbd\xd3\xe0\x08\x9c\xe6\x60\xb1\x13\xd1\x65\x38\xc1\x1b\xa7\x0d\x41\x39\x88\x79\x3a\xe4\xf2\xf4\xfb\xeb\x80\x4f\x7d\x3a\x14\xee\xe9\x08\x24\x4e\x8f\xf0\x2e\x4e\x87\xe7\x7a\x3a\x6d\xe9\xb9\x42\xcc\xd3\xb5\xb1\x0c\xd5\x20\xe3\xe9\xd6\x0d\xa3\xdd\xbf\x68\x34\xa1\x51\x4e\x9f\x85\xb0\x59\x38\xe7\xda\xd6\x8c\x2b\xe3\x3b\xd6\x3e\x85\x6b\x9a\xa4\xc5\x64\x70\x73\x4e\xb5\x0a\xd8\xf9\x3d\xe2\x6a\xd1\xb9\xac\x49\x9c\x3f\x22\x5c\x9a\xc7\xfd\x05\x97\xe6\x11\xb7\xcc\x32\xb8\x82\x0f\xa8\x99\x40\x4d\xf3\x88\x79\x95\x17\x84\x9f\x8f\xe8\x20\xda\x23\xbe\xf0\x63\x9c\xf6\x90\x8d\xa7\x3a\x0f\xba\x67\x0f\xfa\x2e\x0f\xc9\xb0\x21\x0f\x81\x3c\x3c\xa4\xac\x1a\xf8\x7d\x0f\xf1\x82\x25\x3c\xee\x6f\x37\x41\xf6\x42\x29\x43\x89\x87\xc2\xe5\x09\x8f\xfb\x4d\x5f\xe9\xa1\xa7\x4a\x95\xf0\x80\x74\x3f\xb4\xa0\x97\x22\xfe\xd2\x18\x1e\x96\x80\xe5\x87\xc1\x17\x7f\x18\x10\x80\xc2\x27\x00\x7d\xc2\x87\xc1\x7b\x78\x58\x35\xd4\x57\xd6\x2e\x50\xa0\xd0\x1e\x3c\x2d\x7e\x18\xac\x40\x78\xd8\xa7\x85\xc7\x84\x99\x7f\x4c\x9e\x62\x3f\x26\x4f\x56\x1f\x44\xff\x63\xca\x05\x08\x2f\xfe\x01\x65\xf0\x98\x7f\x5b\xf8\x2d\xb0\x7e\x8f\x59\x34\xef\x82\x14\x99\xba\xb3\x89\x47\x44\xbc\xf8\x18\x16\x14\xbe\x7d\xd0\x5d\x62\x0e\xba\x2b\x78\x0a\xae\x76\xb6\xa0\x67\x96\xae\x11\xe9\xfd\x1b\xf4\x9c\x68\x91\xe5\x64\x32\x3b\x85\x55\x4b\x84\x0c\xac\x68\x5d\x0b\x4d\x8f\x96\xb6\xa0\xc0\x4f\xd1\xb2\xec\x86\x96\x36\xa1\xf3\xa1\xec\x10\x2a\xdf\xef\xba\x6b\x92\x00\xb7\x6c\x20\xa1\x22\xd5\x7a\xd0\x7a\x6b\x5d\xe2\xa4\x95\x3e\x8c\xd6\x42\x7f\x54\x6b\x99\x15\xb5\x15\x32\xa9\xb5\xd3\x99\xd1\xda\x07\x59\x4f\x61\xdc\x11\xc1\xdd\xef\x3a\xb4\xa0\x66\x00\x2b\x5a\xef\x5f\x60\x53\xeb\xa5\xb4\xa3\xea\x31\x28\x38\x5b\x7d\x9d\x49\x6a\xcf\x04\x08\xda\x9f\x71\x8b\xf9\x7e\x23\xc5\x16\x9f\xb1\xac\xc4\xe3\x86\x4a\xdf\x61\x2b\x9e\x64\xda\x27\x4f\xef\x9e\xf1\x55\x58\x26\x87\x84\xa7\xb8\x42\xb1\x3c\xb5\x42\xdd\x3f\xcd\x2b\x78\xf5\x69\x6e\x1b\x92\x4b\x6a\x78\xda\x67\x0c\xcf\x29\x88\xf8\x9f\x53\x2e\xe9\x48\x5e\xe1\x39\x4f\x7a\x72\xcf\x79\x1a\xc0\xe4\x08\x93\x28\x78\x4e\x44\xab\xcf\x59\x4f\xcc\x38\xeb\x2a\x02\xbe\x9f\xf7\x6f\x53\x84\x4c\x4f\x7a\x8c\x4f\x9e\xd0\x3e\xe7\x25\x55\x73\x78\xce\x17\xf8\xf0\xff\xe0\x51\xfc\x9f\x41\x33\xe6\xb8\xa9\x05\xe8\x19\x42\x47\xc9\x8e\xcf\x1d\x51\x53\xc8\xf1\x64\x60\x94\xef\xaf\xd3\x11\xc1\xe6\x78\xc2\x30\xe4\x08\xae\xce\x11\x71\x63\xbe\xbf\x0a\x64\x0d\x69\x8b\x1c\x81\x2d\x2a\x44\x33\xc7\x7a\x32\xa2\x5b\x87\x84\xf9\xfe\x6a\xfa\x0a\x99\xde\x5d\x8e\x88\x68\xf2\xfd\xd5\xc7\x1a\x7a\x30\x37\xe4\x03\xdf\xea\x21\xc7\xe9\x92\x43\x8e\xf0\x38\x73\x7c\x59\xc8\x60\xcc\x2c\x7f\x06\x18\x36\x50\x00\xe1\x5b\x64\xc1\x5a\xe4\xfc\xab\x39\x57\xc8\x95\xe5\x09\x11\xc8\x52\xcf\x19\x91\x60\x33\x70\xfe\x00\xd9\xd0\x1a\xa3\x27\x70\xf7\x2a\x18\x9c\x62\x60\x23\x72\x61\x84\x4f\x81\x0d\xca\xba\x41\xd6\x76\x7c\xb8\x85\xac\x09\x93\xde\xef\x1d\xd3\x2a\x82\x92\x80\x58\x1f\x8b\x84\xe0\x66\x3d\x85\xcd\xb0\xb3\xfb\x5d\xe0\x26\x67\x25\xf3\x64\x2d\x0d\xe8\xd6\x9a\x50\x06\xe3\x9b\xef\x77\x15\x74\xaa\x50\xd5\x48\x59\x0f\x3f\x8f\xdd\xff\x4d\x45\x2b\xe8\xc8\xcc\xb3\x6f\xb8\xdd\xce\x84\x23\xc1\x7b\xc8\x20\x16\x60\x21\xe4\x4e\x79\x06\x91\x33\xaf\x84\x72\x96\xba\x12\xa2\x33\x9b\xaf\xe4\xc2\x06\xf2\xbc\x34\x06\xda\x99\xfc\xe7\xa8\x67\x4b\xcc\xc0\x7d\xc9\xf7\xcf\x09\xf7\x2e\xdb\x89\x99\xa0\xba\x40\x46\x84\xd7\xd9\xe0\x01\x50\x56\x32\xa3\x99\x3c\x11\x6b\xe6\xc9\x39\xe1\x8d\x64\x72\xcc\xac\xd2\x43\x9e\x0d\x9f\x3c\x57\xcf\x13\x2b\x9c\xaf\x50\x62\x82\xa5\x29\x11\x1a\xb9\xc4\x1d\x1b\x2b\x71\x77\x01\x84\x6d\x2f\x51\xd8\xa3\xc4\x43\x51\x75\x2e\x88\x82\xfb\x8d\xfe\x19\xc1\x4e\x59\xf7\x4b\x85\xa7\xc5\x25\x66\x54\x97\xfb\x0b\x70\xe3\xf7\x1c\xa1\xf0\xac\xb7\x44\xe0\xbc\xc4\xca\xd0\xb7\xd0\xf4\x97\x58\x95\xbe\x77\x81\x47\xc3\x52\x36\xe9\x84\x1c\xf7\xfe\x0f\x8c\x5d\xe0\x81\x97\xfb\xeb\xdf\x54\xe6\xd0\xd4\x39\xa8\x0b\xf3\x87\x66\x24\xd0\x84\x25\xf2\xca\xa3\xdc\x5f\x5e\x8c\xa5\x94\xaa\x12\x7d\x48\x47\xf2\x42\xbf\xce\xf1\x3a\xcf\x03\x4b\xec\x7a\xa1\x70\x70\xe0\x41\x3f\xb5\xc4\xa1\xd8\x26\x2f\x1d\xcb\xfd\xf5\x01\x6d\x56\xe2\xa7\xa1\xc9\xcb\x3c\xc5\x50\xe8\x0e\x16\xd9\xd7\xee\x65\x57\x4c\xfb\xbd\x4f\xe6\x9e\xba\x4a\x9f\xe8\x21\xe0\x03\x24\x5c\x0a\x02\x7c\x4c\x81\x40\x09\xb0\xc3\xf5\x29\xf4\x53\x8a\xd4\xfb\x37\x14\xf1\x04\x95\x50\xe0\xbd\x9c\x53\x30\x2c\x3d\x80\x82\x2d\x48\x5f\xa3\x00\x41\x08\x4b\x50\x3b\x8c\xcd\x49\x31\x79\x25\xcc\xac\xb0\x3f\x05\x3a\xbd\xa8\xf0\xae\x85\xd6\xad\x00\x55\x9a\xe3\xc9\x82\x4c\x83\x51\x34\xaf\x95\x71\x93\xc4\xf1\x0a\xd6\xa1\x55\xff\xca\xc0\x39\x45\xad\x49\x28\xf4\x96\x8a\x02\x87\xda\x17\xb6\xb4\x73\xd8\xce\xb6\x90\xd8\xc2\xe5\x5a\x7a\xc0\x2d\xfa\x5f\x1c\x5a\x6c\x47\x66\x87\x41\x2f\x06\xce\x33\xd2\xdd\x60\x22\x8b\x65\xe1\x37\x04\xb1\xd8\x0a\x7d\x8b\x15\x0c\x8f\x20\x3f\x31\x15\x8e\x00\xf6\x2f\xb6\x1a\xc0\xa1\x29\x46\x0f\xab\x18\x6f\xc2\x8a\xd1\x0f\x06\x96\x99\x71\x7e\x77\xd6\x43\xd3\x14\xeb\x1c\xac\x33\x04\x2d\xc6\xeb\xcc\x42\xa1\x2c\xf7\xcf\x85\x9d\x18\xb8\x64\x52\x38\xe6\x8e\x46\x53\x10\x99\x14\x1e\x48\x96\x49\x8b\x59\x26\x44\x04\xd9\x13\x72\x33\x9f\xe8\x4f\xe2\xaf\x83\xd1\x32\x33\x21\x19\x7f\xde\xff\x09\x26\x9d\x8e\x05\x50\xc2\xee\xdf\x9e\x26\x30\x31\xbb\x10\x9e\xab\x50\xd9\xae\x67\x0b\xf5\xfe\x42\xe4\x57\xe3\x42\x1f\xec\x18\x72\x70\x0b\x6b\x5c\x61\x40\x8d\x60\xd0\x1a\x79\xe8\x5b\x63\x8f\x39\xd4\x38\x16\xc4\xb6\x6a\x1c\x9c\xb2\xde\x5f\xb3\x0b\xda\x5f\xac\xbc\x30\xc4\xc5\x63\xfb\x2a\xb0\x44\xf5\xfe\xe6\xa9\x4e\xa5\xe2\xaa\x72\x1a\x4b\x05\x7c\x52\xa9\xb7\x2b\xfc\x31\x64\x06\xc0\x1c\xac\xb8\xd8\xf8\x82\xfe\xa8\xbc\xe6\xa9\x90\xbe\xaa\xb2\x65\x94\xb0\xad\xde\xff\xc9\x8b\x09\xa6\x79\x8f\xd5\xe2\x92\x1c\xaa\x6d\x59\x5e\x31\x54\x83\x55\xa9\xf7\x0f\x99\xaf\x52\x3c\x2a\x83\xa3\xca\x73\xaf\x0a\x8f\xba\xda\xd0\xc4\x8a\x0b\xce\x47\xb5\x0b\xc4\xa8\xc6\x45\xcd\x4d\x42\x9d\x29\x86\x7a\xff\xa6\x2c\x28\xd9\xe9\x45\xf3\x20\xac\xd2\x07\xac\xb0\xf4\x80\xaf\x50\x27\xd1\xfb\x5b\xc0\xe5\x75\x0e\x4c\x68\xb1\x6b\x0f\xc6\x9b\x2b\xdb\xb4\x37\x24\x4f\xec\xc0\xe0\xa3\xda\x0a\x6b\x6d\xeb\xe2\xd8\xb5\x6d\xeb\x10\xcd\x36\x2c\x00\x01\x9f\x31\x4e\xb3\x74\x7f\x43\x91\x61\x4b\x50\x62\x06\xac\x10\x99\x96\x5c\x82\xa5\x11\x2f\x7c\x8f\xb9\x31\xcb\xd3\x4a\x4b\x3c\x44\x87\xe6\x07\xd3\x1a\x6d\x9b\x41\xa3\xd8\xae\xa0\x9b\xf1\x64\xc2\xd6\x39\xa2\x1d\x74\x41\x6d\x9d\x2f\xd9\xb1\xce\x68\x69\x27\x8c\xc7\xb4\x86\x68\xd0\x9e\x16\x2c\xc7\x60\x59\x20\x1c\x96\x0f\xa0\xcd\x32\xd8\x82\x57\x10\x3c\x98\xe6\x89\x9a\xe5\x0b\x44\xb1\xb2\x65\x3d\x2d\x18\x8c\xaf\xc1\x79\xb0\x86\x00\xd8\xda\x62\xc0\xfb\xa7\x01\x8f\xd6\xf8\x44\xc2\x96\x5f\xb9\xde\x58\xdc\x3f\x8d\x27\x23\xc6\x0b\x6d\x0b\xe6\x7f\x4c\xcb\x93\x39\x47\x92\xc3\xfd\xe3\x1b\xa2\x44\xaa\x4f\xc8\x2a\xaa\xe5\x19\x51\x71\x12\x67\x7e\xc2\x19\x34\x3f\x27\x68\x67\xbe\x8e\x18\xcd\xf5\x64\x5b\xea\x54\xc3\x36\xfd\xdf\x3a\x07\x36\xde\x51\x5b\x8f\x3c\xc5\xb4\x9e\x20\x5a\xd6\xe5\x85\xd1\x40\x0d\x8a\xa8\x0d\xaa\x09\x03\xcf\xda\xb5\x66\xbc\xc0\x02\xf7\xcf\x07\x37\xfe\x71\xbf\x4f\xe8\x0c\xfb\x5c\x13\xbe\xe0\x93\x37\x9e\xe0\x34\x9a\xc5\x16\x05\x73\x37\xc4\xe0\x35\x86\x06\x53\xd8\xe2\xfd\xee\x28\x7a\x46\x47\x2e\xf3\x8a\xad\xc5\x9c\x98\x83\x0e\x68\xf7\x57\xc6\x04\x8d\x97\x62\x2d\x66\x5b\x09\x88\xdd\x62\xc5\x2f\x66\xb4\xaa\xca\x4e\x95\x2e\x46\x8b\xf7\x7f\x3c\x9a\x6c\xb1\xdd\x5f\x80\x92\x01\xb9\xfd\x16\xff\xd1\x2d\x6d\x7c\x20\xd0\xa2\x33\x08\x6f\xd1\x65\x07\x54\x96\x19\xc6\xf4\x16\x39\x35\x70\xc5\xbc\xc7\x83\x79\xf6\xee\xec\x0d\xd5\xd3\xe2\xf2\xc3\x1a\xd8\xb7\x21\xe6\x0e\x2d\x2e\xa0\x28\xa0\x74\x34\x5e\x61\x35\x9e\x84\x34\x70\x70\x8b\x9f\x6c\x2f\x91\x57\xc7\x4d\x68\xb2\x1a\x58\x31\x22\x79\x20\xb3\x63\x77\x82\xa8\xa7\x51\xaf\x34\xd1\x2a\xa1\x49\xe6\x77\xde\x79\x7c\xd8\x24\x0b\xba\x64\x05\x07\x37\xc9\x59\x9e\x4c\x09\x20\xd4\x0d\xe6\xb3\x81\xf7\xd1\x6d\xdd\xfd\x35\x59\xd0\x50\xd4\x60\x34\x9a\xfc\x5b\x47\xb9\x6d\x2d\xc1\x61\x9f\x9b\xd0\x26\xb4\x75\x45\xd6\x84\xbe\x02\x22\xa3\xc4\x76\x99\x65\x45\xb9\x13\xe7\xf4\xde\x8d\xb3\x75\x02\xcc\x7e\x7f\x77\x58\xc1\x06\x8e\x83\x1f\xdb\xee\xef\x11\xb9\xba\xe1\xf7\x0f\xb4\x4d\x93\x17\x7e\x93\xb5\x3c\xae\x6b\x9a\x1e\x5c\xa0\x0a\x7e\x3b\x56\xa4\xf4\x2d\x9b\x72\x25\xfa\x84\xd7\xd8\x94\xa8\xd0\x6c\x60\x35\x2d\x4a\x9d\xb1\xb6\xa3\x15\x4e\x76\xd3\xca\xe6\x6b\x68\x08\x75\xd3\x86\x4f\x27\x8d\x94\x38\xd1\xce\x5b\xac\xc6\x7d\xd0\x5b\x6d\xba\xc8\xa2\x2f\xec\x20\xc7\x05\x2b\xc0\xe0\xe7\x27\x21\x86\xce\x02\x63\xdd\x32\x04\xa0\xd1\xc1\x6c\x79\x62\x6d\x99\xa6\xa3\xf1\xe2\xac\xc1\x35\x6d\x46\x5c\x52\x31\x35\x13\xb4\x31\xe9\x90\xbc\x66\x64\x77\xcb\x52\x01\x35\xad\x42\x48\x71\xb3\x0c\x76\xb1\x02\x2d\xd4\x8c\xa7\x37\x8d\xb3\x58\xc1\x46\xa8\x45\x9a\xf9\xd2\x17\x6d\xd9\xe8\x06\x91\x46\x65\x17\xd6\x76\x85\xfd\x6d\x06\x2d\xd8\x6c\xac\xd3\xde\x46\x81\x6e\x30\xd6\x8d\x17\x00\xcd\x25\xd9\x0b\xc9\x39\x89\x47\x97\xa2\x2c\x86\xda\x6c\x0e\xd5\xde\x5c\x2e\x96\x91\xa4\x7e\xbf\x6b\x82\x41\x6d\xae\x7f\x52\xe0\x0a\xf5\xde\xdc\xd0\x83\xaf\x74\x9a\x5b\x5a\x5d\x6d\x9f\xd4\x09\x6e\xa4\xa1\xdb\xc1\x87\x2e\xcd\xed\x74\x92\xd3\x0d\xcb\x74\x2b\x64\x1f\xa7\x8f\xd2\xdc\x1a\x67\x84\xb6\xe1\xa4\x53\x36\x70\xd1\xef\x96\xc9\x86\x33\x3d\x60\x5a\xda\x84\xa6\x6c\x70\x35\x90\xa1\x8e\xff\x53\xa7\x6d\xe6\x13\x99\x0c\x49\x9a\x99\x31\x4d\x9b\xb9\xb1\x06\x2b\x23\xbd\xf8\x4c\xa6\x81\x09\x33\x13\x64\x80\xe1\x09\x2e\x0b\x6d\xfa\xfd\x1d\xfe\x4d\x81\x17\xf1\x6f\x42\x0b\xfe\x9b\x52\x56\xc6\x85\x49\xb7\xf0\x6f\xd2\x6a\xc3\x31\x2f\xd0\xe8\x70\xba\x93\x20\x81\x9e\xf7\xfb\x8b\x77\x20\x1e\x37\x8d\x80\xf8\x5c\x94\xf3\xb8\x6b\x8a\x39\x38\x23\x04\xa2\xc3\x23\x28\xec\xeb\xbc\xcf\x11\x97\x06\xe7\xe1\x83\x23\x28\xdd\x99\x1b\x80\x9d\x35\x9d\x8d\x59\xf0\x09\xf0\x42\x96\x97\x9a\x2e\xff\x7b\x52\xe8\xf2\xf7\xda\xc0\x65\xbd\x6e\x71\xe1\x2b\x0e\x17\xbe\x62\x80\x29\x1c\x31\xf0\xc5\xc6\x0b\x95\xeb\x02\xd7\x25\xb9\x30\x3b\x08\x79\xbd\x07\x8d\xe9\xb2\xf3\x28\xd6\x65\x67\x0c\xe5\x72\x50\xfb\xb8\xac\xc3\x59\x97\xf5\x6a\xc7\xe5\x98\xa7\xa2\xfc\x84\xe4\x3b\x6f\x68\x5c\xce\x8c\x26\x27\x19\xcb\xe5\x71\x7f\xa3\x25\x84\x77\x1d\xc8\xd2\xb8\xb9\x64\xee\x49\xb2\x5c\x4c\x14\x6e\x88\x43\xcd\xb1\x61\xb6\x67\x70\xd2\xc1\x65\x45\x11\x3c\xdf\x77\xa9\x08\x77\x5d\x78\x68\xe4\xd4\x0b\x2e\x8d\x67\x03\x2e\x4d\x06\x4b\x9b\x71\xe6\x36\x34\x07\x97\x8e\x5f\x8a\x44\x47\x87\x42\x70\xe9\x4d\xd8\xa1\x2f\x38\x8b\x60\x89\x43\x1d\xd9\xc1\xa3\x2e\x47\xe4\xcd\xea\x59\x39\xe8\x75\x7f\x63\xa4\x8b\x8a\xc4\xe5\x33\x40\x77\x7a\xa0\xce\x74\xde\xef\xc3\x30\xef\x11\x09\x29\xa7\x47\x0c\x7e\xbf\x4f\x92\x54\x4f\x2c\x5b\x2b\x9f\x26\xb9\x2e\x6d\xcd\xd3\x68\xd7\x7f\x13\x72\xc3\x47\x33\xae\x03\xbb\x84\xea\xe1\x45\x8f\xf3\x9a\x0f\x92\x06\x00\xff\xc7\x6d\x5f\x10\x94\xb3\xf5\xba\xcd\x0d\xd4\xb4\xe7\xea\x01\x42\x19\x7d\x38\xb7\xd2\x58\x53\xf1\xc3\x3a\xe9\xc4\xb8\x35\x82\xd5\x04\xb3\xd2\xf7\x77\x63\x70\xeb\x7c\x0a\xe8\x73\xbb\xdf\x80\x58\x36\xbc\x45\x87\x88\x04\x9f\x24\x31\x4f\x01\x9c\x81\xa7\x2f\xbf\xde\xe1\x38\xf8\x44\x84\xeb\xb3\xb0\x53\xe3\x2b\x48\x9e\xb2\xfb\x1c\x68\xdb\x21\x27\xbb\x85\xce\x73\xd4\xce\x23\x9f\xce\xdb\x8d\x1e\x61\x1e\x7a\x3c\xe3\x0b\xd0\x57\xab\x1c\x01\xd6\x27\x16\xdb\x23\x44\xbd\xc7\x25\xea\x3d\xe6\xbf\xa4\xb3\xdd\x60\x83\xb9\x03\x5e\x1c\xad\x6c\xa8\xf8\x3b\xc1\xef\xb1\xd2\x1d\xea\xb1\x0a\x6b\x2b\x22\x94\x1e\x2b\x05\x87\xc7\xbc\x9d\x87\x15\x3d\x36\x00\xf8\x07\x3d\xfa\xce\x85\x47\x1f\x60\xe3\x1e\xfb\x60\x27\x3e\xa7\xe9\xbc\xe4\xe9\xf1\xc3\xf8\x3c\xa9\xff\xef\x38\xa8\x4b\x32\x00\xb0\x12\xd2\x11\x43\x97\x3d\x74\x39\x27\x96\x2f\xda\x43\xe7\x25\x7e\x97\x7c\xa1\xae\x20\x9e\xef\x52\x48\xcc\x4e\x26\xea\x52\xa1\x43\x79\x3f\x98\x99\x30\xb7\xfc\x9b\x2e\x4d\xd1\xe4\x1f\xcf\xaf\x3b\x70\x29\xae\x02\xb8\x30\xb3\x0e\x89\xbb\x74\x0a\x48\xff\x3b\x52\xea\xc2\xcc\xf8\x2b\xbc\x88\x52\xf9\x20\xc0\x4a\x15\xf6\xb8\xaf\xeb\xa2\xae\x70\xa7\xba\x9e\x58\x26\x2f\xae\xfb\xfd\xce\x11\x08\xd5\x0c\xf5\xdf\x35\x0b\x5f\x82\xf6\xb5\xea\xfb\x5d\x36\x63\xe3\xc2\x42\x87\x77\xd2\xb5\x0f\x18\xc4\xce\xe3\xa1\xae\x7c\xa6\xdc\x69\x3a\x3b\xbd\xff\x4e\xab\xd9\x2d\xe3\x17\x5b\x44\xb2\x93\xf8\x96\x79\x73\xdc\xef\x1f\xfa\x8a\xdd\x78\x29\xd7\x2d\xcf\x3f\x24\x1b\x0f\xc9\xbb\x55\x48\x42\xb7\xba\x5a\x55\x38\xc2\xdd\x2a\xa5\xa9\x1b\x47\x6c\x99\x3d\xd7\x6b\x81\xce\xab\x89\x6e\xbe\xee\x79\x3b\x0a\x91\xef\x8b\xc0\xf7\xcf\x20\x27\x4c\x04\x83\x7d\x6e\x40\xe3\xa4\x9d\xeb\x34\x44\x7d\xca\x89\x69\xe9\x89\xf6\xe5\x59\xf5\x15\xfa\xf6\x79\x38\x9b\x33\x3c\xea\x33\x2f\x26\xe1\x3d\x52\x9f\x70\xbf\x98\x92\x85\xe7\x32\xf0\x7d\x36\xaa\xb5\x3e\xf1\xed\x89\x5f\x7f\x63\xfa\xc9\x86\x9d\x63\x41\x93\x8d\xc8\x27\xea\x23\x6e\xd0\x18\x48\x73\x04\xbc\x7f\xc3\x58\x15\xd0\xe3\x7c\x0f\x3a\x22\xb6\x3c\xe8\x74\x8f\xb8\x4e\x1b\xd7\xeb\xc5\xb1\x84\x66\xc4\x42\x3b\x31\x62\x81\x84\x0f\x5a\xa1\x11\xeb\x1a\xb8\xa1\x5d\x03\x03\x8c\x08\x4e\x1b\xb1\xad\x4e\xff\xa6\xae\x41\x7c\x47\x9d\x0b\xbf\xa1\xe8\x46\xf4\x27\xd8\x6b\x44\xb7\x01\xe8\x18\xcf\x59\x32\x66\x7c\xa2\xf9\x64\xd9\x0b\x45\xb4\x5f\x43\xf8\xca\x65\xd0\x2d\x1e\x92\x30\xf2\xfd\x9d\xf8\x46\x66\xc8\x13\x6c\x30\xe4\x29\x0e\xa8\xcc\xa0\x85\xe4\xfb\xfb\x40\x24\x42\xce\x1a\x02\x65\x33\xd6\x63\x81\x21\x35\xbe\x00\x77\x76\xaa\x0b\x6a\x07\xec\xa8\x36\x5e\xbe\x21\x9c\xe0\xb6\x04\x18\x1f\xf7\xb7\xf3\xd9\xdd\x10\xaf\xd0\x58\x03\x2e\x2f\x7a\x76\xf6\xec\xc6\x35\xf6\x81\x20\x70\x08\x63\x91\x41\x81\x19\xf2\x0a\x43\xa1\xc4\x86\x6e\x93\x27\x6a\x43\xa5\x34\xe4\x29\xc4\x43\x79\xcd\x34\x14\xfc\x33\x14\xfa\x66\xe8\x93\x03\xf0\x02\x64\x28\xcf\x86\x07\x9c\x0a\xec\x0f\x7e\xd0\xe0\xa3\xaf\x01\xcb\x30\xee\x77\x83\x75\x19\xca\x21\xd9\xed\x6f\x16\xb2\xd6\xb8\xdf\x43\x56\xff\x01\xf5\x3b\x14\xb8\xb5\x45\x67\xdb\x18\xe9\x0f\x83\x62\x1d\x96\xb8\x43\xc3\x2c\x76\xa2\x3a\xf3\xb3\xb0\x92\x55\xe4\x11\x6b\x2c\x68\x12\x06\x5f\xb5\x8d\xfb\xc7\xe3\x47\x18\xc6\x30\x7f\x98\x17\x2a\x0f\x98\x48\x61\x9e\xa0\x09\x07\x73\xac\x85\xcf\x4c\x86\xf9\x98\x9c\xa6\xe3\x87\x3d\xf0\x6d\xd5\x80\xb3\x87\x9c\xc7\x8d\x7c\xea\xeb\x3e\x7e\xbd\x48\x1e\xff\xbb\x0b\x1c\x8e\x48\x72\xf0\xf6\x73\x78\x2c\xfc\x86\xbf\xb5\x4c\xf2\xf0\x08\xcf\x6e\x38\x5f\xdb\x0e\xbf\xbf\x37\xcb\x61\xc0\xbf\x45\xa9\x2c\x0c\xba\x54\x00\x6e\x08\x4e\xc0\x70\xdd\x26\x20\x87\x46\xb4\x30\x9c\xcf\xf8\x86\xeb\xac\x07\x0a\xed\x10\x26\x85\x95\xb4\x98\x83\xc6\x72\xf0\xe1\xea\x70\x38\xd5\xc3\x27\xcb\xf9\x4c\x75\xf8\x04\xf3\xcf\x6d\x5d\xeb\x8e\xb9\x59\x18\x93\x6f\x14\xc6\x84\xf9\x19\x34\x86\xe3\xfe\xad\x92\x99\x90\xb9\xa7\xf3\xf9\xe9\x98\xce\xd3\xc1\x31\xe1\x71\x0c\x3e\xaf\x9e\x1b\x23\xa5\xfb\x37\x33\x66\x9c\xd0\x72\x39\xcc\x65\xa5\xe8\x8a\xcc\xaa\x17\xe2\xb1\x30\x2b\x7e\x50\x8b\x0c\xb1\xa6\xd3\x09\x9d\xbe\x49\x98\xbe\xae\x7c\x27\x62\x2b\xfe\x0d\x64\xf6\xc9\xe7\x4a\xeb\xce\x69\x0e\xe3\xab\x8f\x79\xc5\x70\x21\x0c\xba\x62\x02\xcb\x5d\x91\x6f\xc2\x2e\x3e\xe4\xbf\x40\x85\x2b\x2a\x0b\xd6\xd1\xed\x15\xb3\x84\xeb\x2f\x7e\xbf\xf8\x6e\xea\xe2\xa3\x56\x94\x5d\x93\x2d\x4a\x83\x1f\x75\x45\x47\xc6\x95\x03\x91\x6d\x2f\x84\xc6\x97\x90\x15\xaf\x75\x59\x72\xc9\xe3\x7e\xf3\xc0\xef\x02\xd9\x24\x5c\xf2\x94\x57\xe0\x21\xd6\x25\x34\xfa\x97\x64\x43\x09\x56\x21\x7c\x11\x7b\x51\xb8\x2e\xa9\xc2\x81\x2a\xd7\x2a\x40\xcd\x45\xee\xbc\xa4\xce\x1e\x2e\xb6\xe4\xad\xf2\x25\xbe\x11\xee\x98\xc0\x85\xbd\xfd\x49\xc8\x25\xf9\x40\x63\x20\xe4\x52\x30\xdd\xa5\x1b\xb4\xf5\xc5\xa3\xa4\xeb\x7e\x27\x5e\x0c\x5d\x8a\x8e\xf7\x1b\x06\xe7\xd2\x1d\xd8\xbc\x14\x7e\x31\xef\xef\xa4\x87\x8b\x5e\xde\xa5\x19\x3f\xec\x40\x6b\x84\xd0\xf3\xc5\xd6\xa5\xf7\x7f\x90\x93\x4b\x2d\xdf\xef\x1a\x2e\x05\x61\x2f\x75\x20\x59\x7d\xcc\x3d\x5c\xda\x89\xca\x77\x67\xb0\xbe\x5c\xcd\x4b\x47\xe4\x09\xe0\xa5\x93\xdd\xaf\xf8\x02\x24\x6e\x14\x76\xfe\xd2\xcb\xc2\x65\x99\xf7\xa7\x97\x65\xba\xb3\x97\x65\x62\xc0\x1c\xcd\xe9\xd3\x5d\x08\xa7\x2f\x20\x93\xd6\xeb\x9a\x7c\x98\xf9\xc9\x0b\xec\x4f\xf8\xc7\x9f\x94\xa0\x4f\xe8\xd5\x4f\xde\x48\x7e\x42\x71\x7d\x42\x6b\x7c\x42\x6b\x7c\xda\x39\x3d\xbc\xe2\x01\x02\xbf\x78\xd4\xfa\x8a\x0d\x22\xf9\xe2\x1b\x85\x97\x55\x00\xe8\xfe\xd7\x2c\x00\xb0\xb5\xff\x1f\x00\x00\xff\xff\x11\x91\x1a\xde\x5b\x35\x00\x00") func keysWordlistSpanishTxtBytes() ([]byte, error) { return bindataRead( @@ -146,7 +146,7 @@ func keysWordlistSpanishTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/wordlist/spanish.txt", size: 13659, mode: os.FileMode(420), modTime: time.Unix(1497960590, 0)} + info := bindataFileInfo{name: "keys/wordlist/spanish.txt", size: 13659, mode: os.FileMode(420), modTime: time.Unix(1511602021, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -204,9 +204,9 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "keys/wordlist/chinese_simplified.txt": keysWordlistChinese_simplifiedTxt, - "keys/wordlist/english.txt": keysWordlistEnglishTxt, - "keys/wordlist/japanese.txt": keysWordlistJapaneseTxt, - "keys/wordlist/spanish.txt": keysWordlistSpanishTxt, + "keys/wordlist/english.txt": keysWordlistEnglishTxt, + "keys/wordlist/japanese.txt": keysWordlistJapaneseTxt, + "keys/wordlist/spanish.txt": keysWordlistSpanishTxt, } // AssetDir returns the file names below a certain @@ -248,14 +248,13 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } - var _bintree = &bintree{nil, map[string]*bintree{ "keys": &bintree{nil, map[string]*bintree{ "wordlist": &bintree{nil, map[string]*bintree{ "chinese_simplified.txt": &bintree{keysWordlistChinese_simplifiedTxt, map[string]*bintree{}}, - "english.txt": &bintree{keysWordlistEnglishTxt, map[string]*bintree{}}, - "japanese.txt": &bintree{keysWordlistJapaneseTxt, map[string]*bintree{}}, - "spanish.txt": &bintree{keysWordlistSpanishTxt, map[string]*bintree{}}, + "english.txt": &bintree{keysWordlistEnglishTxt, map[string]*bintree{}}, + "japanese.txt": &bintree{keysWordlistJapaneseTxt, map[string]*bintree{}}, + "spanish.txt": &bintree{keysWordlistSpanishTxt, map[string]*bintree{}}, }}, }}, }} @@ -306,3 +305,4 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } + From f48baf86fb190f61b8e44baa9d033c6d85658b28 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 27 Dec 2017 14:37:37 -0800 Subject: [PATCH 182/273] Add Address type which is HexBytes --- glide.lock | 30 ++++++++++++++---------------- glide.yaml | 2 +- hd/address.go | 4 ++++ hd/hd_test.go | 10 +--------- keys/keybase.go | 4 +++- pub_key.go | 27 ++++++++++++++++----------- pub_key_test.go | 3 ++- 7 files changed, 41 insertions(+), 39 deletions(-) diff --git a/glide.lock b/glide.lock index c8c922c6a..5032685c2 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 765599cf3dcac232d3d2ece65c3b016d0abe55d0536adfe93d11e0dd29287de4 -updated: 2017-11-13T14:37:54.127163059+01:00 +hash: a21061afc44c148eb6bfeb91478b520661f3d086234383a0208d915b0cb058b8 +updated: 2017-12-27T14:29:49.534901894-08:00 imports: - name: github.com/btcsuite/btcd version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e @@ -9,10 +9,10 @@ imports: version: 66871daeb12123ece012a9628d2798d01195c4b3 subpackages: - base58 -- name: github.com/ethanfrey/hid - version: ea8f4c923d3bc8c9c312b7d38724a294f184258a - name: github.com/ethanfrey/ledger - version: 23a7bb9d74bc83a862fcb4bddde24215b2295ad9 + version: 5e432577be582bd18a3b4a9cd75dae7a317ade36 +- name: github.com/flynn/hid + version: ed06a31c6245d4552e8dbba7e32e5b010b875d65 - name: github.com/go-kit/kit version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c subpackages: @@ -21,14 +21,14 @@ imports: - log/term - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 -- name: github.com/go-playground/locales - version: e4cbcb5d0652150d40ad0646651076b6bd2be4f6 - subpackages: - - currency -- name: github.com/go-playground/universal-translator - version: 71201497bace774495daed26a3874fd339e0b538 - name: github.com/go-stack/stack version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf +- name: github.com/gogo/protobuf + version: 342cbe0a04158f6dcb03ca0079991a51a4248c02 + subpackages: + - gogoproto + - proto + - protoc-gen-gogo/descriptor - name: github.com/golang/snappy version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/howeyc/crc16 @@ -55,17 +55,17 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/ed25519 - version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 + version: 1f52c6f8b8a5c7908aff4497c186af344b428925 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 1c96861c03231361546944d883d99593b2e6b408 + version: 27be46e25124ddf775e23317a83647ce62a93f6b subpackages: - data - data/base58 - name: github.com/tendermint/tmlibs - version: 56e51bc1133bd54a331e0314d5f80fb547460362 + version: 93c05aa8c06ef38f2b15fcdd1d91eafefda2732d subpackages: - common - db @@ -82,8 +82,6 @@ imports: - poly1305 - ripemd160 - salsa20/salsa -- name: gopkg.in/go-playground/validator.v9 - version: 1304298bf10d085adec514b076772a79c9cadb6b testImports: - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 diff --git a/glide.yaml b/glide.yaml index 64b275f10..f9df5c18d 100644 --- a/glide.yaml +++ b/glide.yaml @@ -17,7 +17,7 @@ import: subpackages: - extra25519 - package: github.com/tendermint/tmlibs - version: sdk-develop + version: sdk2 - package: github.com/tendermint/go-wire version: develop subpackages: diff --git a/hd/address.go b/hd/address.go index 5b664b496..f59876739 100644 --- a/hd/address.go +++ b/hd/address.go @@ -1,5 +1,9 @@ package hd +// XXX This package doesn't work with our address scheme, +// XXX and it probably doesn't work for our other pubkey types. +// XXX Fix it up to be more general but compatible. + import ( "crypto/ecdsa" "crypto/hmac" diff --git a/hd/hd_test.go b/hd/hd_test.go index 02d80388c..0ec47f5c3 100644 --- a/hd/hd_test.go +++ b/hd/hd_test.go @@ -2,9 +2,6 @@ package hd import ( "bytes" - //"crypto/hmac" - //"crypto/sha512" - //"encoding/binary" "encoding/hex" "encoding/json" "fmt" @@ -15,11 +12,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/tyler-smith/go-bip39" - //"github.com/btcsuite/btcd/chaincfg" - //"github.com/btcsuite/btcutil/hdkeychain" - //"github.com/mndrix/btcutil" - //"github.com/tyler-smith/go-bip32" - "github.com/tendermint/go-crypto" ) @@ -84,7 +76,7 @@ func TestHDToAddr(t *testing.T) { copy(pubT[:], pub) addr := pubT.Address() fmt.Printf("ADDR \t%X %X\n", addrB, addr) - assert.Equal(t, addr, addrB, fmt.Sprintf("Expected addresses to match %d", i)) + assert.Equal(t, addr, crypto.Address(addrB), fmt.Sprintf("Expected addresses to match %d", i)) } } diff --git a/keys/keybase.go b/keys/keybase.go index 7f53b2979..c68564d5a 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -86,7 +86,9 @@ func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { // List loads the keys from the storage and enforces alphabetical order func (kb dbKeybase) List() ([]Info, error) { var res []Info - for iter := kb.db.Iterator(); iter.Valid(); iter.Next() { + iter := kb.db.Iterator(nil, nil) + defer iter.Close() + for ; iter.Valid(); iter.Next() { key := iter.Key() if isPub(key) { info, err := readInfo(iter.Value()) diff --git a/pub_key.go b/pub_key.go index dfa012969..cda01a9df 100644 --- a/pub_key.go +++ b/pub_key.go @@ -3,16 +3,21 @@ package crypto import ( "bytes" "crypto/sha256" + "fmt" secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" "github.com/tendermint/go-wire" data "github.com/tendermint/go-wire/data" - . "github.com/tendermint/tmlibs/common" + cmn "github.com/tendermint/tmlibs/common" "golang.org/x/crypto/ripemd160" ) +// An address is a []byte, but hex-encoded even in JSON. +// []byte leaves us the option to change the address length. +type Address cmn.HexBytes + func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { if err := wire.ReadBinaryBytes(pubKeyBytes, &pubKey); err != nil { return PubKey{}, err @@ -27,7 +32,7 @@ func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { // +gen wrapper:"PubKey,Impl[PubKeyEd25519,PubKeySecp256k1],ed25519,secp256k1" type PubKeyInner interface { AssertIsPubKeyInner() - Address() []byte + Address() Address Bytes() []byte KeyString() string VerifyBytes(msg []byte, sig Signature) bool @@ -44,17 +49,17 @@ type PubKeyEd25519 [32]byte func (pubKey PubKeyEd25519) AssertIsPubKeyInner() {} -func (pubKey PubKeyEd25519) Address() []byte { +func (pubKey PubKeyEd25519) Address() Address { w, n, err := new(bytes.Buffer), new(int), new(error) wire.WriteBinary(pubKey[:], w, n, err) if *err != nil { - PanicCrisis(*err) + panic(*err) } // append type byte encodedPubkey := append([]byte{TypeEd25519}, w.Bytes()...) hasher := ripemd160.New() hasher.Write(encodedPubkey) // does not error - return hasher.Sum(nil) + return Address(hasher.Sum(nil)) } func (pubKey PubKeyEd25519) Bytes() []byte { @@ -95,13 +100,13 @@ func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte { } func (pubKey PubKeyEd25519) String() string { - return Fmt("PubKeyEd25519{%X}", pubKey[:]) + return fmt.Sprintf("PubKeyEd25519{%X}", pubKey[:]) } // Must return the full bytes in hex. // Used for map keying, etc. func (pubKey PubKeyEd25519) KeyString() string { - return Fmt("%X", pubKey[:]) + return fmt.Sprintf("%X", pubKey[:]) } func (pubKey PubKeyEd25519) Equals(other PubKey) bool { @@ -124,14 +129,14 @@ type PubKeySecp256k1 [33]byte func (pubKey PubKeySecp256k1) AssertIsPubKeyInner() {} // Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) -func (pubKey PubKeySecp256k1) Address() []byte { +func (pubKey PubKeySecp256k1) Address() Address { hasherSHA256 := sha256.New() hasherSHA256.Write(pubKey[:]) // does not error sha := hasherSHA256.Sum(nil) hasherRIPEMD160 := ripemd160.New() hasherRIPEMD160.Write(sha) // does not error - return hasherRIPEMD160.Sum(nil) + return Address(hasherRIPEMD160.Sum(nil)) } func (pubKey PubKeySecp256k1) Bytes() []byte { @@ -168,13 +173,13 @@ func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error { } func (pubKey PubKeySecp256k1) String() string { - return Fmt("PubKeySecp256k1{%X}", pubKey[:]) + return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:]) } // Must return the full bytes in hex. // Used for map keying, etc. func (pubKey PubKeySecp256k1) KeyString() string { - return Fmt("%X", pubKey[:]) + return fmt.Sprintf("%X", pubKey[:]) } func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { diff --git a/pub_key_test.go b/pub_key_test.go index 097c5ea3b..95c82534d 100644 --- a/pub_key_test.go +++ b/pub_key_test.go @@ -27,7 +27,8 @@ func TestPubKeySecp256k1Address(t *testing.T) { for _, d := range secpDataTable { privB, _ := hex.DecodeString(d.priv) pubB, _ := hex.DecodeString(d.pub) - addrB, _, _ := base58.CheckDecode(d.addr) + addrBbz, _, _ := base58.CheckDecode(d.addr) + addrB := Address(addrBbz) var priv PrivKeySecp256k1 copy(priv[:], privB) From 87f2005fa88af1311c4cbc34f3593461e85809bc Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 29 Dec 2017 22:53:27 -0500 Subject: [PATCH 183/273] hd: comments and some cleanup --- hd/address.go | 144 +++++++++++++++++++++++++++++++++----------------- hd/hd_test.go | 2 +- 2 files changed, 97 insertions(+), 49 deletions(-) diff --git a/hd/address.go b/hd/address.go index f59876739..9511ffad2 100644 --- a/hd/address.go +++ b/hd/address.go @@ -21,19 +21,30 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcutil/base58" - "github.com/tendermint/go-crypto" "golang.org/x/crypto/ripemd160" ) -func ComputeAddress(pubKeyHex string, chainHex string, path string, index int32) string { +/* + + This file implements BIP32 HD wallets. + Note it only works for SECP256k1 keys. + It also includes some Bitcoin specific utility functions. + +*/ + +// ComputeBTCAddress returns the BTC address using the pubKeyHex and chainCodeHex +// for the given path and index. +func ComputeBTCAddress(pubKeyHex string, chainCodeHex string, path string, index int32) string { pubKeyBytes := DerivePublicKeyForPath( HexDecode(pubKeyHex), - HexDecode(chainHex), + HexDecode(chainCodeHex), fmt.Sprintf("%v/%v", path, index), ) - return AddrFromPubKeyBytes(pubKeyBytes) + return BTCAddrFromPubKeyBytes(pubKeyBytes) } +// ComputePrivateKey returns the private key using the master mprivHex and chainCodeHex +// for the given path and index. func ComputePrivateKey(mprivHex string, chainHex string, path string, index int32) string { privKeyBytes := DerivePrivateKeyForPath( HexDecode(mprivHex), @@ -43,12 +54,14 @@ func ComputePrivateKey(mprivHex string, chainHex string, path string, index int3 return HexEncode(privKeyBytes) } -func ComputeAddressForPrivKey(privKey string) string { +// ComputeBTCAddressForPrivKey returns the Bitcoin address for the given privKey. +func ComputeBTCAddressForPrivKey(privKey string) string { pubKeyBytes := PubKeyBytesFromPrivKeyBytes(HexDecode(privKey), true) - return AddrFromPubKeyBytes(pubKeyBytes) + return BTCAddrFromPubKeyBytes(pubKeyBytes) } -func SignMessage(privKey string, message string, compress bool) string { +// SignBTCMessage signs a "Bitcoin Signed Message". +func SignBTCMessage(privKey string, message string, compress bool) string { prefixBytes := []byte("Bitcoin Signed Message:\n") messageBytes := []byte(message) bytes := []byte{} @@ -67,25 +80,28 @@ func SignMessage(privKey string, message string, compress bool) string { PublicKey: ecdsaPubKey, D: new(big.Int).SetBytes(privKeyBytes), } - sigbytes, err := btcec.SignCompact(btcec.S256(), ecdsaPrivKey, crypto.Sha256(crypto.Sha256(bytes)), compress) + sigbytes, err := btcec.SignCompact(btcec.S256(), ecdsaPrivKey, CalcHash256(bytes), compress) if err != nil { panic(err) } return base64.StdEncoding.EncodeToString(sigbytes) } -// returns MPK, Chain, and master secret in hex. -func ComputeMastersFromSeed(seed string) (string, string, string, string) { - secret, chain := I64([]byte("Bitcoin seed"), []byte(seed)) +// ComputeMastersFromSeed returns the master public key, master secret, and chain code in hex. +func ComputeMastersFromSeed(seed string) (string, string, string) { + key, data := []byte("Bitcoin seed"), []byte(seed) + secret, chain := I64(key, data) pubKeyBytes := PubKeyBytesFromPrivKeyBytes(secret, true) - return HexEncode(pubKeyBytes), HexEncode(secret), HexEncode(chain), HexEncode(secret) + return HexEncode(pubKeyBytes), HexEncode(secret), HexEncode(chain) } +// ComputeWIF returns the privKey in Wallet Import Format. func ComputeWIF(privKey string, compress bool) string { return WIFFromPrivKeyBytes(HexDecode(privKey), compress) } -func ComputeTxId(rawTxHex string) string { +// ComputeBTCTxId returns the bitcoin transaction ID. +func ComputeBTCTxId(rawTxHex string) string { return HexEncode(ReverseBytes(CalcHash256(HexDecode(rawTxHex)))) } @@ -103,7 +119,11 @@ func printKeyInfo(privKeyBytes []byte, pubKeyBytes []byte, chain []byte) { } */ -func DerivePrivateKeyForPath(privKeyBytes []byte, chain []byte, path string) []byte { +//------------------------------------------------------------------- + +// DerivePrivateKeyForPath derives the private key by following the path from privKeyBytes, +// using the given chainCode. +func DerivePrivateKeyForPath(privKeyBytes []byte, chainCode []byte, path string) []byte { data := privKeyBytes parts := strings.Split(path, "/") for _, part := range parts { @@ -119,13 +139,15 @@ func DerivePrivateKeyForPath(privKeyBytes []byte, chain []byte, path string) []b if i < 0 { panic(errors.New("index too large.")) } - data, chain = DerivePrivateKey(data, chain, uint32(i), prime) + data, chainCode = DerivePrivateKey(data, chainCode, uint32(i), prime) //printKeyInfo(data, nil, chain) } return data } -func DerivePublicKeyForPath(pubKeyBytes []byte, chain []byte, path string) []byte { +// DerivePublicKeyForPath derives the public key by following the path from pubKeyBytes +// using the given chainCode. +func DerivePublicKeyForPath(pubKeyBytes []byte, chainCode []byte, path string) []byte { data := pubKeyBytes parts := strings.Split(path, "/") for _, part := range parts { @@ -140,36 +162,42 @@ func DerivePublicKeyForPath(pubKeyBytes []byte, chain []byte, path string) []byt if i < 0 { panic(errors.New("index too large.")) } - data, chain = DerivePublicKey(data, chain, uint32(i)) - //printKeyInfo(nil, data, chain) + data, chainCode = DerivePublicKey(data, chainCode, uint32(i)) + //printKeyInfo(nil, data, chainCode) } return data } -func DerivePrivateKey(privKeyBytes []byte, chain []byte, i uint32, prime bool) ([]byte, []byte) { +// DerivePrivateKey derives the private key with index and chainCode. +// If prime is true, the derivation is 'hardened'. +// It returns the new private key and new chain code. +func DerivePrivateKey(privKeyBytes []byte, chainCode []byte, index uint32, prime bool) ([]byte, []byte) { var data []byte if prime { - i = i | 0x80000000 + index = index | 0x80000000 data = append([]byte{byte(0)}, privKeyBytes...) } else { public := PubKeyBytesFromPrivKeyBytes(privKeyBytes, true) data = public } - data = append(data, uint32ToBytes(i)...) - data2, chain2 := I64(chain, data) + data = append(data, uint32ToBytes(index)...) + data2, chainCode2 := I64(chainCode, data) x := addScalars(privKeyBytes, data2) - return x, chain2 + return x, chainCode2 } -func DerivePublicKey(pubKeyBytes []byte, chain []byte, i uint32) ([]byte, []byte) { +// DerivePublicKey derives the public key with index and chainCode. +// It returns the new public key and new chain code. +func DerivePublicKey(pubKeyBytes []byte, chainCode []byte, index uint32) ([]byte, []byte) { data := []byte{} data = append(data, pubKeyBytes...) - data = append(data, uint32ToBytes(i)...) - data2, chain2 := I64(chain, data) + data = append(data, uint32ToBytes(index)...) + data2, chainCode2 := I64(chainCode, data) data2p := PubKeyBytesFromPrivKeyBytes(data2, true) - return addPoints(pubKeyBytes, data2p), chain2 + return addPoints(pubKeyBytes, data2p), chainCode2 } +// eliptic curve pubkey addition func addPoints(a []byte, b []byte) []byte { ap, err := btcec.ParsePubKey(a, btcec.S256()) if err != nil { @@ -188,6 +216,7 @@ func addPoints(a []byte, b []byte) []byte { return sum.SerializeCompressed() } +// modular big endian addition func addScalars(a []byte, b []byte) []byte { aInt := new(big.Int).SetBytes(a) bInt := new(big.Int).SetBytes(b) @@ -204,15 +233,21 @@ func uint32ToBytes(i uint32) []byte { return b[:] } +//------------------------------------------------------------------- + +// HexEncode encodes b in hex. func HexEncode(b []byte) string { return hex.EncodeToString(b) } +// HexDecode hex decodes the str. If str is not valid hex +// it will return an empty byte slice. func HexDecode(str string) []byte { b, _ := hex.DecodeString(str) return b } +// I64 returns the two halfs of the SHA512 HMAC of key and data. func I64(key []byte, data []byte) ([]byte, []byte) { mac := hmac.New(sha512.New, key) mac.Write(data) @@ -220,27 +255,36 @@ func I64(key []byte, data []byte) ([]byte, []byte) { return I[:32], I[32:] } -// This returns a Bitcoin-like address. -func AddrFromPubKeyBytes(pubKeyBytes []byte) string { - prefix := byte(0x00) // TODO Make const or configurable +//------------------------------------------------------------------- + +const ( + btcPrefixPubKeyHash = byte(0x00) + btcPrefixPrivKey = byte(0x80) +) + +// BTCAddrFromPubKeyBytes returns a B58 encoded Bitcoin mainnet address. +func BTCAddrFromPubKeyBytes(pubKeyBytes []byte) string { + versionPrefix := btcPrefixPubKeyHash // TODO Make const or configurable h160 := CalcHash160(pubKeyBytes) - h160 = append([]byte{prefix}, h160...) + h160 = append([]byte{versionPrefix}, h160...) checksum := CalcHash256(h160) b := append(h160, checksum[:4]...) return base58.Encode(b) } -func AddrBytesFromPubKeyBytes(pubKeyBytes []byte) (addrBytes []byte, checksum []byte) { - prefix := byte(0x00) // TODO Make const or configurable +// BTCAddrBytesFromPubKeyBytes returns a hex Bitcoin mainnet address and its checksum. +func BTCAddrBytesFromPubKeyBytes(pubKeyBytes []byte) (addrBytes []byte, checksum []byte) { + versionPrefix := btcPrefixPubKeyHash // TODO Make const or configurable h160 := CalcHash160(pubKeyBytes) - _h160 := append([]byte{prefix}, h160...) + _h160 := append([]byte{versionPrefix}, h160...) checksum = CalcHash256(_h160)[:4] return h160, checksum } +// WIFFromPrivKeyBytes returns the privKeyBytes in Wallet Import Format. func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string { - prefix := byte(0x80) // TODO Make const or configurable - bytes := append([]byte{prefix}, privKeyBytes...) + versionPrefix := btcPrefixPrivKey // TODO Make const or configurable + bytes := append([]byte{versionPrefix}, privKeyBytes...) if compress { bytes = append(bytes, byte(1)) } @@ -249,6 +293,7 @@ func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string { return base58.Encode(bytes) } +// PubKeyBytesFromPrivKeyBytes returns the optionally compressed public key bytes. func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyBytes []byte) { x, y := btcec.S256().ScalarBaseMult(privKeyBytes) pub := &btcec.PublicKey{ @@ -263,27 +308,30 @@ func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyByte return pub.SerializeUncompressed() } -// Calculate the hash of hasher over buf. -func CalcHash(buf []byte, hasher hash.Hash) []byte { - hasher.Write(buf) +//-------------------------------------------------------------- + +// CalcHash returns the hash of data using hasher. +func CalcHash(data []byte, hasher hash.Hash) []byte { + hasher.Write(data) return hasher.Sum(nil) } -// calculate hash160 which is ripemd160(sha256(data)) -func CalcHash160(buf []byte) []byte { - return CalcHash(CalcHash(buf, sha256.New()), ripemd160.New()) +// CalcHash160 returns the ripemd160(sha256(data)). +func CalcHash160(data []byte) []byte { + return CalcHash(CalcHash(data, sha256.New()), ripemd160.New()) } -// calculate hash256 which is sha256(sha256(data)) -func CalcHash256(buf []byte) []byte { - return CalcHash(CalcHash(buf, sha256.New()), sha256.New()) +// CalcHash256 returns the sha256(sha256(data)). +func CalcHash256(data []byte) []byte { + return CalcHash(CalcHash(data, sha256.New()), sha256.New()) } -// calculate sha512(data) -func CalcSha512(buf []byte) []byte { - return CalcHash(buf, sha512.New()) +// CalcSha512 returns the sha512(data). +func CalcSha512(data []byte) []byte { + return CalcHash(data, sha512.New()) } +// ReverseBytes returns the buf in the opposite order func ReverseBytes(buf []byte) []byte { var res []byte if len(buf) == 0 { diff --git a/hd/hd_test.go b/hd/hd_test.go index 0ec47f5c3..c9e540ad5 100644 --- a/hd/hd_test.go +++ b/hd/hd_test.go @@ -112,7 +112,7 @@ func ifExit(err error, n int) { func gocrypto(seed []byte) ([]byte, []byte, []byte) { - _, priv, ch, _ := ComputeMastersFromSeed(string(seed)) + _, priv, ch := ComputeMastersFromSeed(string(seed)) privBytes := DerivePrivateKeyForPath( HexDecode(priv), From 7c77f6b2da6e51c1a4f07544cf616fa4a1d6bc81 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 30 Dec 2017 11:39:59 -0500 Subject: [PATCH 184/273] move hd into keys/hd --- {hd => keys/hd}/address.go | 0 {hd => keys/hd}/address_test.go | 0 {hd => keys/hd}/hd_test.go | 0 {hd => keys/hd}/test.json | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {hd => keys/hd}/address.go (100%) rename {hd => keys/hd}/address_test.go (100%) rename {hd => keys/hd}/hd_test.go (100%) rename {hd => keys/hd}/test.json (100%) diff --git a/hd/address.go b/keys/hd/address.go similarity index 100% rename from hd/address.go rename to keys/hd/address.go diff --git a/hd/address_test.go b/keys/hd/address_test.go similarity index 100% rename from hd/address_test.go rename to keys/hd/address_test.go diff --git a/hd/hd_test.go b/keys/hd/hd_test.go similarity index 100% rename from hd/hd_test.go rename to keys/hd/hd_test.go diff --git a/hd/test.json b/keys/hd/test.json similarity index 100% rename from hd/test.json rename to keys/hd/test.json From 1f8e66fdb3c34c697b8cadf469775a61ad9513af Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 21 Dec 2017 19:43:33 -0500 Subject: [PATCH 185/273] nano: update comments --- nano/keys.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nano/keys.go b/nano/keys.go index a6d3ea8e4..b50efd7ec 100644 --- a/nano/keys.go +++ b/nano/keys.go @@ -33,21 +33,21 @@ func getLedger() (*ledger.Ledger, error) { return device, err } -func signLedger(device *ledger.Ledger, msg []byte) (pk crypto.PubKey, sig crypto.Signature, err error) { +func signLedger(device *ledger.Ledger, msg []byte) (pub crypto.PubKey, sig crypto.Signature, err error) { var resp []byte packets := generateSignRequests(msg) for _, pack := range packets { resp, err = device.Exchange(pack, Timeout) if err != nil { - return pk, sig, err + return pub, sig, err } } // the last call is the result we want and needs to be parsed key, bsig, err := parseDigest(resp) if err != nil { - return pk, sig, err + return pub, sig, err } var b [32]byte @@ -64,9 +64,9 @@ type PrivKeyLedgerEd25519 struct { CachedPubKey crypto.PubKey } -// NewPrivKeyLedgerEd25519Ed25519 will generate a new key and store the +// NewPrivKeyLedgerEd25519 will generate a new key and store the // public key for later use. -func NewPrivKeyLedgerEd25519Ed25519() (crypto.PrivKey, error) { +func NewPrivKeyLedgerEd25519() (crypto.PrivKey, error) { var pk PrivKeyLedgerEd25519 // getPubKey will cache the pubkey for later use, // this allows us to return an error early if the ledger @@ -94,13 +94,13 @@ func (pk *PrivKeyLedgerEd25519) ValidateKey() error { // AssertIsPrivKeyInner fulfils PrivKey Interface func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} -// Bytes fulfils pk Interface - stores the cached pubkey so we can verify +// Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify // the same key when we reconnect to a ledger func (pk *PrivKeyLedgerEd25519) Bytes() []byte { return wire.BinaryBytes(pk.Wrap()) } -// Sign calls the ledger and stores the pk for future use +// Sign calls the ledger and stores the PubKey for future use // // XXX/TODO: panics if there is an error communicating with the ledger. // From f3f49c23620505f50eb0e0398cb9b1837046e201 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 30 Dec 2017 16:46:58 -0500 Subject: [PATCH 186/273] keys/words --- keys/keybase.go | 9 +++++---- keys/keybase_test.go | 15 ++++++++------- keys/{ => words}/ecc.go | 2 +- keys/{ => words}/ecc_test.go | 2 +- keys/{ => words}/wordcodec.go | 4 ++-- keys/{ => words}/wordcodec_test.go | 2 +- keys/{ => words}/wordcodecbench_test.go | 2 +- keys/{ => words}/wordlist/chinese_simplified.txt | 0 keys/{ => words}/wordlist/english.txt | 0 keys/{ => words}/wordlist/japanese.txt | 0 keys/{ => words}/wordlist/spanish.txt | 0 keys/{ => words}/wordlist/wordlist.go | 0 12 files changed, 19 insertions(+), 17 deletions(-) rename keys/{ => words}/ecc.go (99%) rename keys/{ => words}/ecc_test.go (98%) rename keys/{ => words}/wordcodec.go (98%) rename keys/{ => words}/wordcodec_test.go (99%) rename keys/{ => words}/wordcodecbench_test.go (98%) rename keys/{ => words}/wordlist/chinese_simplified.txt (100%) rename keys/{ => words}/wordlist/english.txt (100%) rename keys/{ => words}/wordlist/japanese.txt (100%) rename keys/{ => words}/wordlist/spanish.txt (100%) rename keys/{ => words}/wordlist/wordlist.go (100%) diff --git a/keys/keybase.go b/keys/keybase.go index c68564d5a..b5f7a3c5e 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -8,6 +8,7 @@ import ( crypto "github.com/tendermint/go-crypto" dbm "github.com/tendermint/tmlibs/db" + "github.com/tendermint/go-crypto/keys/words" "github.com/tendermint/go-crypto/nano" ) @@ -19,10 +20,10 @@ import ( // a full-featured key manager type dbKeybase struct { db dbm.DB - codec Codec + codec words.Codec } -func New(db dbm.DB, codec Codec) dbKeybase { +func New(db dbm.DB, codec words.Codec) dbKeybase { return dbKeybase{ db: db, codec: codec, @@ -214,7 +215,7 @@ func generate(algo string, secret []byte) (crypto.PrivKey, error) { case crypto.NameSecp256k1: return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap(), nil case nano.NameLedgerEd25519: - return nano.NewPrivKeyLedgerEd25519Ed25519() + return nano.NewPrivKeyLedgerEd25519() default: err := errors.Errorf("Cannot generate keys for algorithm: %s", algo) return crypto.PrivKey{}, err @@ -228,7 +229,7 @@ func generateByType(typ byte, secret []byte) (crypto.PrivKey, error) { case crypto.TypeSecp256k1: return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap(), nil case nano.TypeLedgerEd25519: - return nano.NewPrivKeyLedgerEd25519Ed25519() + return nano.NewPrivKeyLedgerEd25519() default: err := errors.Errorf("Cannot generate keys for algorithm: %X", typ) return crypto.PrivKey{}, err diff --git a/keys/keybase_test.go b/keys/keybase_test.go index 72476a02e..5b4d11303 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -13,6 +13,7 @@ import ( crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto/keys" + "github.com/tendermint/go-crypto/keys/words" "github.com/tendermint/go-crypto/nano" ) @@ -23,7 +24,7 @@ func TestKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) algo := crypto.NameEd25519 @@ -91,7 +92,7 @@ func TestSignVerify(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) algo := crypto.NameSecp256k1 @@ -165,7 +166,7 @@ func TestSignWithLedger(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) n := "nano-s" p := "hard2hack" @@ -219,7 +220,7 @@ func TestImportUnencrypted(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) key := crypto.GenPrivKeyEd25519FromSecret(cmn.RandBytes(16)).Wrap() @@ -245,7 +246,7 @@ func TestAdvancedKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) algo := crypto.NameSecp256k1 @@ -288,7 +289,7 @@ func TestSeedPhrase(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) algo := crypto.NameEd25519 @@ -319,7 +320,7 @@ func ExampleNew() { // Select the encryption and storage for your cryptostore cstore := keys.New( dbm.NewMemDB(), - keys.MustLoadCodec("english"), + words.MustLoadCodec("english"), ) ed := crypto.NameEd25519 sec := crypto.NameSecp256k1 diff --git a/keys/ecc.go b/keys/words/ecc.go similarity index 99% rename from keys/ecc.go rename to keys/words/ecc.go index c1ac258fe..c511ad6e4 100644 --- a/keys/ecc.go +++ b/keys/words/ecc.go @@ -1,4 +1,4 @@ -package keys +package words import ( "encoding/binary" diff --git a/keys/ecc_test.go b/keys/words/ecc_test.go similarity index 98% rename from keys/ecc_test.go rename to keys/words/ecc_test.go index 6d3e3bec8..9e1772b9f 100644 --- a/keys/ecc_test.go +++ b/keys/words/ecc_test.go @@ -1,4 +1,4 @@ -package keys +package words import ( "testing" diff --git a/keys/wordcodec.go b/keys/words/wordcodec.go similarity index 98% rename from keys/wordcodec.go rename to keys/words/wordcodec.go index c551e54ce..fbf32160f 100644 --- a/keys/wordcodec.go +++ b/keys/words/wordcodec.go @@ -1,4 +1,4 @@ -package keys +package words import ( "math/big" @@ -6,7 +6,7 @@ import ( "github.com/pkg/errors" - "github.com/tendermint/go-crypto/keys/wordlist" + "github.com/tendermint/go-crypto/keys/words/wordlist" ) const BankSize = 2048 diff --git a/keys/wordcodec_test.go b/keys/words/wordcodec_test.go similarity index 99% rename from keys/wordcodec_test.go rename to keys/words/wordcodec_test.go index f79ebcad0..367e3799a 100644 --- a/keys/wordcodec_test.go +++ b/keys/words/wordcodec_test.go @@ -1,4 +1,4 @@ -package keys +package words import ( "testing" diff --git a/keys/wordcodecbench_test.go b/keys/words/wordcodecbench_test.go similarity index 98% rename from keys/wordcodecbench_test.go rename to keys/words/wordcodecbench_test.go index e100a443a..04417a936 100644 --- a/keys/wordcodecbench_test.go +++ b/keys/words/wordcodecbench_test.go @@ -1,4 +1,4 @@ -package keys +package words import ( "testing" diff --git a/keys/wordlist/chinese_simplified.txt b/keys/words/wordlist/chinese_simplified.txt similarity index 100% rename from keys/wordlist/chinese_simplified.txt rename to keys/words/wordlist/chinese_simplified.txt diff --git a/keys/wordlist/english.txt b/keys/words/wordlist/english.txt similarity index 100% rename from keys/wordlist/english.txt rename to keys/words/wordlist/english.txt diff --git a/keys/wordlist/japanese.txt b/keys/words/wordlist/japanese.txt similarity index 100% rename from keys/wordlist/japanese.txt rename to keys/words/wordlist/japanese.txt diff --git a/keys/wordlist/spanish.txt b/keys/words/wordlist/spanish.txt similarity index 100% rename from keys/wordlist/spanish.txt rename to keys/words/wordlist/spanish.txt diff --git a/keys/wordlist/wordlist.go b/keys/words/wordlist/wordlist.go similarity index 100% rename from keys/wordlist/wordlist.go rename to keys/words/wordlist/wordlist.go From bd30cb4de9dbc28273e1c864509c795e7c8576ef Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 30 Dec 2017 17:02:18 -0500 Subject: [PATCH 187/273] keys/keybase.go: comments and fixes --- keys/keybase.go | 146 +++++++++++++++++++++---------------------- keys/keybase_test.go | 14 ++--- keys/types.go | 4 +- 3 files changed, 81 insertions(+), 83 deletions(-) diff --git a/keys/keybase.go b/keys/keybase.go index b5f7a3c5e..c72518748 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -32,59 +32,61 @@ func New(db dbm.DB, codec words.Codec) dbKeybase { var _ Keybase = dbKeybase{} -// Create adds a new key to the storage engine, returning error if -// another key already stored under this name -// -// algo must be a supported go-crypto algorithm: ed25519, secp256k1 -func (kb dbKeybase) Create(name, passphrase, algo string) (Info, string, error) { - // 128-bits are the all the randomness we can make use of +// Create generates a new key and persists it storage, encrypted using the passphrase. +// It returns the generated seedphrase (mnemonic) and the key Info. +// It returns an error if it fails to generate a key for the given algo type, +// or if another key is already stored under the same name. +func (kb dbKeybase) Create(name, passphrase, algo string) (string, Info, error) { + // NOTE: secret is SHA256 hashed by secp256k1 and ed25519. + // 16 byte secret corresponds to 12 BIP39 words. + // XXX: Ledgers use 24 words now - should we ? secret := crypto.CRandBytes(16) key, err := generate(algo, secret) if err != nil { - return Info{}, "", err + return "", Info{}, err } + // encrypt and persist the key public := kb.writeKey(key, name, passphrase) - // we append the type byte to the serialized secret to help with recovery - // ie [secret] = [secret] + [type] - typ := key.Bytes()[0] - secret = append(secret, typ) - - seed, err := kb.codec.BytesToWords(secret) - phrase := strings.Join(seed, " ") - return public, phrase, err + // return the mnemonic phrase + words, err := kb.codec.BytesToWords(secret) + seedphrase := strings.Join(words, " ") + return seedphrase, public, err } -// Recover takes a seed phrase and tries to recover the private key. -// -// If the seed phrase is valid, it will create the private key and store -// it under name, protected by passphrase. -// -// Result similar to New(), except it doesn't return the seed again... -func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { - words := strings.Split(strings.TrimSpace(seedphrase), " ") - secret, err := kb.codec.WordsToBytes(words) +// Recover converts a seedphrase to a private key and persists it, encrypted with the given passphrase. +// Functions like Create, but seedphrase is input not output. +func (kb dbKeybase) Recover(name, passphrase, algo string, seedphrase string) (Info, error) { + + key, err := kb.SeedToPrivKey(algo, seedphrase) if err != nil { return Info{}, err } - // secret is comprised of the actual secret with the type appended - // ie [secret] = [secret] + [type] - l := len(secret) - secret, typ := secret[:l-1], secret[l-1] + // Valid seedphrase. Encrypt key and persist to disk. + public := kb.writeKey(key, name, passphrase) + return public, nil +} - key, err := generateByType(typ, secret) +// SeedToPrivKey returns the private key corresponding to a seedphrase +// without persisting the private key. +// TODO: enable the keybase to just hold these in memory so we can sign without persisting (?) +func (kb dbKeybase) SeedToPrivKey(algo, seedphrase string) (crypto.PrivKey, error) { + words := strings.Split(strings.TrimSpace(seedphrase), " ") + secret, err := kb.codec.WordsToBytes(words) if err != nil { - return Info{}, err + return crypto.PrivKey{}, err } - // d00d, it worked! create the bugger.... - public := kb.writeKey(key, name, passphrase) - return public, err + key, err := generate(algo, secret) + if err != nil { + return crypto.PrivKey{}, err + } + return key, nil } -// List loads the keys from the storage and enforces alphabetical order +// List returns the keys from storage in alphabetical order. func (kb dbKeybase) List() ([]Info, error) { var res []Info iter := kb.db.Iterator(nil, nil) @@ -102,20 +104,19 @@ func (kb dbKeybase) List() ([]Info, error) { return res, nil } -// Get returns the public information about one key +// Get returns the public information about one key. func (kb dbKeybase) Get(name string) (Info, error) { bs := kb.db.Get(pubName(name)) return readInfo(bs) } -// Sign will modify the Signable in order to attach a valid signature with -// this public key -// -// If no key for this name, or the passphrase doesn't match, returns an error +// Sign signs the msg with the named key. +// It returns an error if the key doesn't exist or the decryption fails. +// TODO: what if leddger fails ? func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pk crypto.PubKey, err error) { var key crypto.PrivKey - bs := kb.db.Get(privName(name)) - key, err = unarmorDecryptPrivKey(string(bs), passphrase) + armorStr := kb.db.Get(privName(name)) + key, err = unarmorDecryptPrivKey(string(armorStr), passphrase) if err != nil { return } @@ -125,15 +126,15 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signat return } -// Export decodes the private key with the current password, encodes -// it with a secure one-time password and generates a sequence that can be -// Imported by another dbKeybase +// Export decodes the private key with the current password, encrypts +// it with a secure one-time password and generates an armored private key +// that can be Imported by another dbKeybase. // // This is designed to copy from one device to another, or provide backups // during version updates. func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { - bs := kb.db.Get(privName(name)) - key, err := unarmorDecryptPrivKey(string(bs), oldpass) + armorStr := kb.db.Get(privName(name)) + key, err := unarmorDecryptPrivKey(string(armorStr), oldpass) if err != nil { return nil, err } @@ -141,11 +142,11 @@ func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { if transferpass == "" { return key.Bytes(), nil } - res := encryptArmorPrivKey(key, transferpass) - return []byte(res), nil + armorBytes := encryptArmorPrivKey(key, transferpass) + return []byte(armorBytes), nil } -// Import accepts bytes generated by Export along with the same transferpass +// Import accepts bytes generated by Export along with the same transferpass. // If they are valid, it stores the password under the given name with the // new passphrase. func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err error) { @@ -164,7 +165,7 @@ func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err } // Delete removes key forever, but we must present the -// proper passphrase before deleting it (for security) +// proper passphrase before deleting it (for security). func (kb dbKeybase) Delete(name, passphrase string) error { // verify we have the proper password before deleting bs := kb.db.Get(privName(name)) @@ -177,10 +178,10 @@ func (kb dbKeybase) Delete(name, passphrase string) error { return nil } -// Update changes the passphrase with which a already stored key is encoded. +// Update changes the passphrase with which an already stored key is encrypted. // -// oldpass must be the current passphrase used for encoding, newpass will be -// the only valid passphrase from this time forward +// oldpass must be the current passphrase used for encryption, newpass will be +// the only valid passphrase from this time forward. func (kb dbKeybase) Update(name, oldpass, newpass string) error { bs := kb.db.Get(privName(name)) key, err := unarmorDecryptPrivKey(string(bs), oldpass) @@ -188,26 +189,37 @@ func (kb dbKeybase) Update(name, oldpass, newpass string) error { return err } - // we must delete first, as Putting over an existing name returns an error - kb.db.DeleteSync(pubName(name)) - kb.db.DeleteSync(privName(name)) - kb.writeKey(key, name, newpass) + // Generate the public bytes and the encrypted privkey + public := info(name, key) + private := encryptArmorPrivKey(key, newpass) + + // We must delete first, as Putting over an existing name returns an error. + // Must be done atomically with the write or we could lose the key. + batch := kb.db.NewBatch() + batch.Delete(pubName(name)) + batch.Delete(privName(name)) + batch.Set(pubName(name), public.bytes()) + batch.Set(privName(name), []byte(private)) + batch.Write() + return nil } +//--------------------------------------------------------------------------------------- + func (kb dbKeybase) writeKey(priv crypto.PrivKey, name, passphrase string) Info { - // generate the public bytes + // Generate the public bytes and the encrypted privkey public := info(name, priv) - // generate the encrypted privkey private := encryptArmorPrivKey(priv, passphrase) - // write them both + // Write them both kb.db.SetSync(pubName(name), public.bytes()) kb.db.SetSync(privName(name), []byte(private)) return public } +// TODO: use a `type TypeKeyAlgo string` (?) func generate(algo string, secret []byte) (crypto.PrivKey, error) { switch algo { case crypto.NameEd25519: @@ -222,20 +234,6 @@ func generate(algo string, secret []byte) (crypto.PrivKey, error) { } } -func generateByType(typ byte, secret []byte) (crypto.PrivKey, error) { - switch typ { - case crypto.TypeEd25519: - return crypto.GenPrivKeyEd25519FromSecret(secret).Wrap(), nil - case crypto.TypeSecp256k1: - return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap(), nil - case nano.TypeLedgerEd25519: - return nano.NewPrivKeyLedgerEd25519() - default: - err := errors.Errorf("Cannot generate keys for algorithm: %X", typ) - return crypto.PrivKey{}, err - } -} - func pubName(name string) []byte { return []byte(fmt.Sprintf("%s.pub", name)) } diff --git a/keys/keybase_test.go b/keys/keybase_test.go index 5b4d11303..12e5205b0 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -39,7 +39,7 @@ func TestKeyManagement(t *testing.T) { // create some keys _, err = cstore.Get(n1) assert.NotNil(err) - i, _, err := cstore.Create(n1, p1, algo) + _, i, err := cstore.Create(n1, p1, algo) require.Equal(n1, i.Name) require.Nil(err) _, _, err = cstore.Create(n2, p2, algo) @@ -100,10 +100,10 @@ func TestSignVerify(t *testing.T) { p1, p2 := "1234", "foobar" // create two users and get their info - i1, _, err := cstore.Create(n1, p1, algo) + _, i1, err := cstore.Create(n1, p1, algo) require.Nil(err) - i2, _, err := cstore.Create(n2, p2, algo) + _, i2, err := cstore.Create(n2, p2, algo) require.Nil(err) // let's try to sign some messages @@ -172,7 +172,7 @@ func TestSignWithLedger(t *testing.T) { p := "hard2hack" // create a nano user - c, _, err := cstore.Create(n, p, nano.NameLedgerEd25519) + _, c, err := cstore.Create(n, p, nano.NameLedgerEd25519) require.Nil(err, "%+v", err) assert.Equal(c.Name, n) _, ok := c.PubKey.Unwrap().(nano.PubKeyLedgerEd25519) @@ -297,7 +297,7 @@ func TestSeedPhrase(t *testing.T) { p1, p2 := "1234", "foobar" // make sure key works with initial password - info, seed, err := cstore.Create(n1, p1, algo) + seed, info, err := cstore.Create(n1, p1, algo) require.Nil(err, "%+v", err) assert.Equal(n1, info.Name) assert.NotEmpty(seed) @@ -309,7 +309,7 @@ func TestSeedPhrase(t *testing.T) { require.NotNil(err) // let us re-create it from the seed-phrase - newInfo, err := cstore.Recover(n2, p2, seed) + newInfo, err := cstore.Recover(n2, p2, algo, seed) require.Nil(err, "%+v", err) assert.Equal(n2, newInfo.Name) assert.Equal(info.Address(), newInfo.Address()) @@ -326,7 +326,7 @@ func ExampleNew() { sec := crypto.NameSecp256k1 // Add keys and see they return in alphabetical order - bob, _, err := cstore.Create("Bob", "friend", ed) + _, bob, err := cstore.Create("Bob", "friend", ed) if err != nil { // this should never happen fmt.Println(err) diff --git a/keys/types.go b/keys/types.go index 541234b37..fdb729e0a 100644 --- a/keys/types.go +++ b/keys/types.go @@ -38,9 +38,9 @@ type Keybase interface { // Sign some bytes Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) // Create a new keypair - Create(name, passphrase, algo string) (_ Info, seedphrase string, _ error) + Create(name, passphrase, algo string) (seedphrase string, _ Info, _ error) // Recover takes a seedphrase and loads in the key - Recover(name, passphrase, seedphrase string) (Info, error) + Recover(name, passphrase, algo, seedphrase string) (Info, error) List() ([]Info, error) Get(name string) (Info, error) Update(name, oldpass, newpass string) error From 8c61bb27b74414fb0fc06cad5deb99fc2df3232e Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 30 Dec 2017 17:25:43 -0500 Subject: [PATCH 188/273] fix nano test --- nano/keys_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nano/keys_test.go b/nano/keys_test.go index 2e5142e30..fda096e29 100644 --- a/nano/keys_test.go +++ b/nano/keys_test.go @@ -83,7 +83,7 @@ func TestRealLedger(t *testing.T) { } msg := []byte("kuhehfeohg") - priv, err := NewPrivKeyLedgerEd25519Ed25519() + priv, err := NewPrivKeyLedgerEd25519() require.Nil(err, "%+v", err) pub := priv.PubKey() sig := priv.Sign(msg) @@ -123,7 +123,7 @@ func TestRealLedgerErrorHandling(t *testing.T) { // first, try to generate a key, must return an error // (no panic) - _, err := NewPrivKeyLedgerEd25519Ed25519() + _, err := NewPrivKeyLedgerEd25519() require.Error(err) led := PrivKeyLedgerEd25519{} // empty From d058d0098f63b783abe55dbafdd912a15f3e08a2 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 30 Dec 2017 17:25:55 -0500 Subject: [PATCH 189/273] keys/bcrypt --- {bcrypt => keys/bcrypt}/base64.go | 0 {bcrypt => keys/bcrypt}/bcrypt.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {bcrypt => keys/bcrypt}/base64.go (100%) rename {bcrypt => keys/bcrypt}/bcrypt.go (100%) diff --git a/bcrypt/base64.go b/keys/bcrypt/base64.go similarity index 100% rename from bcrypt/base64.go rename to keys/bcrypt/base64.go diff --git a/bcrypt/bcrypt.go b/keys/bcrypt/bcrypt.go similarity index 100% rename from bcrypt/bcrypt.go rename to keys/bcrypt/bcrypt.go From b31d37b480d06f817919858e34cbec3501145e5a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 30 Dec 2017 18:25:42 -0500 Subject: [PATCH 190/273] update circle.yml --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index a37187dd9..af63a0594 100644 --- a/circle.yml +++ b/circle.yml @@ -18,4 +18,4 @@ dependencies: test: override: - "go version" - - "cd $PROJECT_PATH && make all" + - "cd $PROJECT_PATH && make get_tools && make all" From 793d7717dc0f3d25c0f7b102db564b9d6b994e6f Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 2 Jan 2018 16:25:01 -0500 Subject: [PATCH 191/273] no metalinter for now --- Makefile | 11 ++++++----- keys/mintkey.go | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 6f23f8ef7..c4a4fe30b 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,11 @@ GOTOOLS = \ github.com/Masterminds/glide \ - github.com/jteeuwen/go-bindata/go-bindata \ - gopkg.in/alecthomas/gometalinter.v2 \ -GOTOOLS_CHECK = glide go-bindata gometalinter.v2 + github.com/jteeuwen/go-bindata/go-bindata + # gopkg.in/alecthomas/gometalinter.v2 \ + # +GOTOOLS_CHECK = glide go-bindata #gometalinter.v2 -all: check get_vendor_deps build test install metalinter +all: check get_vendor_deps build test install check: check_tools @@ -34,7 +35,7 @@ check_tools: get_tools: @echo "--> Installing tools" go get -u -v $(GOTOOLS) - @gometalinter.v2 --install + #@gometalinter.v2 --install update_tools: @echo "--> Updating tools" diff --git a/keys/mintkey.go b/keys/mintkey.go index c948848be..d2724d658 100644 --- a/keys/mintkey.go +++ b/keys/mintkey.go @@ -7,7 +7,7 @@ import ( cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/bcrypt" + "github.com/tendermint/go-crypto/keys/bcrypt" ) const ( From 156416fe27625bdc103aa43aeb6e909e5b9dd4df Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 2 Jan 2018 16:39:43 -0500 Subject: [PATCH 192/273] fix wordlist paths --- Makefile | 2 +- keys/words/wordcodec.go | 2 +- keys/words/wordlist/wordlist.go | 84 +++++++++++++++++---------------- 3 files changed, 45 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index c4a4fe30b..19d797f1d 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ check: check_tools wordlist: # Generating wordlist.go... - go-bindata -ignore ".*\.go" -o keys/wordlist/wordlist.go -pkg "wordlist" keys/wordlist/... + go-bindata -ignore ".*\.go" -o keys/words/wordlist/wordlist.go -pkg "wordlist" keys/words/wordlist/... build: wordlist # Nothing else to build! diff --git a/keys/words/wordcodec.go b/keys/words/wordcodec.go index fbf32160f..27032ce32 100644 --- a/keys/words/wordcodec.go +++ b/keys/words/wordcodec.go @@ -61,7 +61,7 @@ func MustLoadCodec(bank string) *WordCodec { // loadBank opens a wordlist file and returns all words inside func loadBank(bank string) ([]string, error) { - filename := "keys/wordlist/" + bank + ".txt" + filename := "keys/words/wordlist/" + bank + ".txt" words, err := wordlist.Asset(filename) if err != nil { return nil, err diff --git a/keys/words/wordlist/wordlist.go b/keys/words/wordlist/wordlist.go index dd531b6dd..4efff82cb 100644 --- a/keys/words/wordlist/wordlist.go +++ b/keys/words/wordlist/wordlist.go @@ -1,9 +1,9 @@ // Code generated by go-bindata. // sources: -// keys/wordlist/chinese_simplified.txt -// keys/wordlist/english.txt -// keys/wordlist/japanese.txt -// keys/wordlist/spanish.txt +// keys/words/wordlist/chinese_simplified.txt +// keys/words/wordlist/english.txt +// keys/words/wordlist/japanese.txt +// keys/words/wordlist/spanish.txt // DO NOT EDIT! package wordlist @@ -71,82 +71,82 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _keysWordlistChinese_simplifiedTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x1c\x97\x55\x76\xeb\x30\x14\x45\xff\xf7\xa8\xc3\xcc\x49\xc3\x69\x98\xda\x86\xd9\x0e\x4c\xc6\xf7\x4a\x9a\xc5\x5b\x7e\x7f\x5d\x5d\x6d\x6c\x45\x07\xf6\x31\xdd\x04\xc1\x3d\x82\xb6\x77\x48\x7f\x45\x70\x2f\x12\x78\x29\xb4\x9f\x45\x6a\x05\x02\xcf\xc3\x7e\x3a\x04\xf7\x0d\x32\x5b\x12\xdc\x3d\x82\x7b\x8e\xe0\xfe\x83\xf4\x5e\x68\xa6\x4a\xe0\xcf\xb1\x8b\x28\x81\xdf\x44\x5b\x57\x74\x30\xc7\x34\x56\x04\xfe\x1f\xa6\x31\x44\x32\x7b\x82\x57\x1f\xe9\xef\x09\xbc\x12\x92\xf6\x90\xfd\x01\xc9\xa4\x90\xdd\x03\xcd\x54\x08\x9e\x5d\xa4\xbc\x23\xb8\xfb\x48\xb9\x8a\x3c\xce\x48\x6e\x85\x54\x0a\xc8\x6d\x4e\xf0\x18\x62\xe3\x2f\x82\x7b\x1e\xfb\x49\x23\x9b\x0a\x76\x77\x26\xf0\x96\x98\x65\x11\x37\x98\x60\x23\x05\xb4\xf9\x40\x2a\x25\x64\xd6\x45\xb6\x5d\xec\xb8\x80\x6c\x16\xe8\xe9\x0b\xcd\x46\xd0\x7d\x15\x79\xb7\x30\x7e\x19\x29\x46\x09\xee\x59\x82\x47\xf8\x99\x3d\xcc\x20\x82\xd9\x64\x71\xf1\x15\xe2\x2d\x90\xed\x15\xd3\xb8\x20\xb9\x1e\x2e\x5d\x40\x16\x31\x74\x7f\x46\x0a\x4d\xdc\x6f\x1b\x9b\xfe\x21\xf0\x0a\x98\x4a\x0a\x7b\xb9\x21\xfb\x32\x26\xbb\xc6\x94\xf6\xc8\xf6\x1b\xc9\x8d\x70\xe9\x32\xee\xff\x7b\xcf\x08\x5e\x75\x24\x73\x45\xfb\x1e\xf2\xaa\x13\xbc\x3e\x98\xd8\x83\xc0\x2f\x11\xdc\xbb\x68\xff\x0f\x29\xf9\x68\x2e\x87\x46\x96\xc8\xfc\x85\x78\x0d\xe4\x19\x41\xb6\x71\xa4\x92\xc1\x7e\xda\x48\x6f\x84\x69\x1c\x90\xe4\x95\xc0\xeb\x61\x12\x57\x24\x5b\x44\x66\x4d\x64\xb6\x46\x1b\x1f\xa4\xd7\x43\x5b\x73\x5c\x6c\x8a\x99\xbd\x09\x1e\x59\x02\x2f\x8f\x3c\x4e\xc8\x6b\x82\xe9\xdd\x91\xe4\x0a\x3b\x5e\xe1\x5a\x67\x74\x74\x23\xb8\x97\x90\xe4\x09\xa9\x24\x70\xe9\x22\xda\xdc\x63\xbc\x0f\x92\x4a\xa2\x5f\x7b\x74\x33\x45\x3e\x71\xa4\x5c\x24\x78\x8d\xd0\x76\x09\xd3\xcf\x23\xa5\x21\x52\xce\x10\x3c\x32\x48\x66\x8d\xee\x1a\x68\xa6\x49\xf0\x4a\x61\xcf\x2b\x74\xdf\xc0\xfc\xfd\x21\x95\x2a\x2e\x5a\x47\xaa\x2f\x74\x33\x43\xca\x6d\x74\x30\x46\xca\x3f\xe8\x71\x8c\xf1\xeb\xd8\xe5\x14\xd7\xda\xa2\x89\x32\xe2\x7b\x68\x3f\x83\x24\xff\xd0\xd6\x08\x73\xf2\x91\x54\x0f\x79\x67\xd0\x78\x12\x1b\x49\xa2\xfd\x08\xe6\x37\x4f\xe0\x4f\xd1\xf8\x09\xb9\x1d\x71\x91\x2e\xf2\xb8\xa2\xe5\x0a\xa6\x77\xc6\x4d\xda\x48\xb2\x8b\x59\xe5\x91\xc3\x17\x81\xd7\x40\xbf\xfb\x68\xb3\x83\x3d\x8c\x91\x6a\x1b\x37\x58\x13\xbc\x8a\x48\x72\x8e\xdc\xef\x68\x33\x8d\x46\x7c\xf4\x6f\x8c\xd4\xa3\xc8\xb3\x8c\x9e\x7d\xec\xf6\x8d\x94\x73\x98\xed\x18\x93\x0d\xef\xee\x8a\xfb\xfa\xa0\x87\x18\x36\x12\x45\x66\x67\x64\xe8\x61\x2f\x09\xec\xfb\x81\x5e\xa2\xd8\xdb\x0e\xe3\x2d\x91\x50\x7b\xbd\x37\x72\x38\x60\xfc\x21\x5a\x9a\x63\x86\x73\xec\x3b\x8e\xec\x53\x18\x3f\x81\x5d\x46\xb1\xdb\x31\x92\xf9\x45\xe6\x0f\x34\x9b\xc7\x2e\x6b\x68\x7f\x88\x8e\x1e\xd8\x6d\xe8\xc7\x0a\x92\xea\xa3\x85\x34\x92\x1e\x11\x3c\x06\x48\xc1\x43\x9e\x1e\xda\x78\x23\xa9\x13\x76\xfe\xc1\x4e\x7e\x91\xc7\x11\x89\x76\x91\x4f\x12\xcd\x84\xdf\x43\x06\xe9\x7d\x23\x99\x0e\x81\x1f\x7a\xad\x89\x16\xb7\xc8\x2c\x81\x6b\x0f\x91\x62\xe8\x8d\x0e\x36\x7b\x44\x92\x59\x5c\x6b\x85\x14\x4f\x04\x9f\x01\x7a\xf4\x91\x42\x0b\x17\x19\x61\x3a\x6f\xec\x32\x81\x89\x6f\x70\x93\x14\xc1\x3d\x8e\x86\x1e\x28\x4f\x09\xee\x7d\x64\xf7\x44\x3a\x2b\xa4\x94\x47\x3e\x2d\x82\x7b\x13\x97\xae\x22\x93\x6f\x02\x2f\x8b\x5e\x4a\xb8\xf6\x15\x3d\x3e\xd0\xc8\x00\xed\xef\xd0\xef\x28\x81\x17\xea\xa2\x85\x8d\x36\x08\xfc\x08\x76\x3b\x43\x92\x1b\x24\x79\x40\x07\x71\xb4\x71\xc5\xee\xa2\x68\xe3\x81\xde\x93\x98\x77\x09\x49\x15\x71\xe9\x34\xf6\xf5\x87\xf6\xce\x48\xf1\x0b\x37\x2d\x21\x99\x34\x9a\xad\x63\x3a\x2f\xf4\xab\x83\x8b\x0c\xb1\xb9\x03\x72\x0f\xbd\x9d\x45\xfa\x1e\xd6\xfb\xc5\xbe\x16\x04\xef\x3c\xa6\x3f\x44\x72\x63\x24\x19\x7a\x21\x8d\xee\xca\x98\xde\x16\x9b\x3e\x61\xdf\x6f\xec\x65\x8f\x59\xee\x30\x33\x0f\xbb\xdd\x22\xd3\x3d\x9a\x9b\xa3\xcd\x16\xb2\x2d\x60\x0e\x3e\x92\xfc\xc5\x2c\x7c\xa4\x58\x42\x2a\x45\xcc\x78\x8b\x66\x8b\x98\x65\x15\x79\x8e\x08\x3e\x63\xdc\xfa\x0f\x9b\x8b\x61\x77\x03\xcc\xe1\x84\x7e\x9d\x31\x6b\x0f\x49\xc6\x91\xd4\x85\xc0\xcf\xe1\x7a\x29\xf4\xbe\x26\x78\x8e\x90\xfe\x10\xbb\xbd\xa3\x9b\x39\xe6\x3d\x43\x1e\x1f\xcc\xf0\x84\xdd\xee\x71\xfd\x08\xba\xbd\x60\x46\x0d\xcc\x57\x01\xcd\x67\xd1\xef\x16\xf2\xce\x23\xe5\x5f\x82\x7b\x03\xb3\xbe\x62\x97\x31\xec\x35\x87\xf1\xd3\xd8\x69\x12\x79\x1d\x30\xdb\x16\xc1\xab\x84\x16\xa2\xb8\xe1\x89\xe0\xd9\x22\x78\x2c\x90\x7b\x1c\x99\x15\x91\xed\x03\x49\x7c\x70\x63\x1f\xd7\x49\x22\x5f\x29\xdc\xe0\x1b\xf7\x53\xc0\x7e\xbe\xd1\xe6\x06\xbd\x1d\x70\xdd\x37\xf6\x53\xc5\x0c\x3f\x48\x31\x8e\x54\x57\xc8\xb2\x81\x39\x8f\xd0\x5c\x04\x99\xa5\x91\x62\x0e\xc9\x7d\xe3\x06\x35\x4c\x3f\x8a\x64\xc2\x67\x8d\x90\x7a\x11\xe3\x2d\xd0\xc6\x0e\x9b\xf9\x43\xca\x47\x34\x11\xde\xc3\x89\xe0\x1d\xe6\xd8\x04\x79\x47\x70\xc9\x3b\x52\x4a\x21\xf7\x18\x92\xcc\x13\xbc\xbe\x70\x9d\x19\x7a\xcd\xa0\xdf\x09\xc4\xeb\x63\x96\x7b\x64\xf6\x83\xa4\x53\x98\xe3\x1b\x89\x3c\x91\xf2\x0d\x53\x4a\xa3\xad\x32\xc6\x3f\x23\x99\x1a\x2e\x92\x45\x47\x69\x24\xd5\x41\x36\x6d\x24\xd2\x41\x77\x3d\x02\xef\x88\x7c\x7e\xd1\xaf\x0c\xda\xdc\xe1\x3a\x13\x74\x38\x47\x0f\x43\xe4\x3b\xd4\xc7\x13\x53\xca\xa3\x85\xf0\xff\x9f\x48\xd2\x47\xdb\x75\xcc\x6b\x8b\x9e\x43\x5f\xc7\x30\xd9\x34\xb2\xcc\x23\xc5\x33\xc1\xbd\x8e\xc9\x5d\xb1\xb1\x23\x52\x8a\x11\x78\x7f\xd8\x5d\x0a\x17\x89\x21\x87\x6f\xa4\x9f\x42\x0a\x49\x4c\xf4\x97\xe0\x55\xc6\xee\xe3\xa8\x3f\x46\x4a\x1f\xe4\x10\xc1\x24\x97\x48\x39\x86\xf1\x26\x18\x3f\x85\x3c\xbf\x90\x4a\xf8\x19\x73\x5c\x3d\xec\xdb\x50\xa7\x73\xdc\xa2\x89\x78\x5f\xe8\xf5\x88\x6c\xdb\xc8\xfb\x86\xeb\x96\x31\xad\x24\x36\x5f\x46\x66\x07\x64\xdf\x40\x37\x61\x7e\x1d\x71\xc9\x22\x32\x3f\xe1\xfc\x04\x5a\x5a\xa1\xed\x37\x76\x9f\xc1\xbc\x7e\x30\xf3\x6f\x6c\xd6\x43\xaa\x13\x24\xec\xfc\xca\x2f\xc1\x33\x8a\xf6\x7b\xc8\x2e\x85\x66\x1f\xd8\xca\x1c\x37\x7e\xe0\xda\x47\x82\xfb\x1b\x53\x89\x63\xf3\x07\x74\xbf\x44\x72\x1f\xa4\x9a\x43\x07\x25\xa4\xbc\xc7\x56\x5e\x68\x7f\x85\xdc\xb7\xd8\xd7\x16\x33\x0a\x3b\xbb\x8b\xdc\xc3\x1c\x3a\xa3\xa7\x15\xf6\xd3\x47\x36\x2d\x74\x50\x41\x4b\x35\x82\x77\x0f\x3d\x9e\xd0\x30\x4f\xf7\x51\xa4\xbc\x40\x9b\x2f\x24\x5d\x46\x47\x55\xd4\xbb\xa2\x91\x12\xba\x99\xa0\xe3\x0c\x76\x15\x41\xa6\xbf\xc8\x20\x8d\x6e\x16\x48\xcf\x43\xca\x57\xdc\xe1\x89\x9e\x26\xd8\x65\x8a\xc0\x4f\x62\xcf\x0f\xcc\x79\x89\xc9\x1c\x90\xdb\x02\xf3\x3b\x42\x5b\x6b\xb4\x3f\x40\xb6\x27\x8c\xbf\xc1\xbe\x7c\xb4\x5f\xc4\xee\xc2\x0c\x19\x22\xc9\x24\x92\xbc\xa0\x5e\x05\xc9\xcc\xd0\x5c\x98\x4f\x77\xec\xf5\x84\x0e\x2b\x18\x3f\x8e\xdc\xc2\x8c\x38\xa3\x83\x0f\xa6\xb1\xc7\x75\x8a\x38\xbf\x8a\xc9\xed\xb0\xe7\x21\x92\xf6\xb1\x85\x38\xc6\x5f\x22\xc9\x33\xc1\xf3\x49\xf0\xea\x20\x83\x2e\xda\x3b\x62\xdf\x75\x82\xcf\x16\xfd\x4a\x22\xc3\x90\x5d\x7e\x91\xd9\x10\x17\x89\x62\xfe\x1a\xd8\xcc\x03\x29\x8e\x90\xf2\x09\x7b\x9e\x20\x95\x38\xb2\x2b\xa0\xed\x39\x36\x5a\xc0\x2e\xb3\xe8\x21\x8b\x69\xf8\x48\x6e\x88\xdc\xce\xd8\xdb\x10\x1b\xe6\xde\x20\x86\x9b\x7e\xa3\xd3\x08\x52\xb9\x23\xb9\x35\x52\x4c\xe3\xda\x27\x02\xaf\x86\x64\x06\x48\xa6\x87\xe6\x5a\xd8\x48\x1c\xcd\x7d\x21\x83\x32\x66\xd3\x44\xca\x33\xe4\x9d\x40\x8b\x13\xb4\xff\x83\xbd\x55\x31\x61\x8e\xd6\x26\x68\xef\x8d\xf9\x0d\xcf\x37\xc5\xfc\x76\x30\xdb\x08\xf6\xb3\xc7\xd5\x0e\x48\x76\x87\xec\x5f\xc8\x7d\x80\xec\x13\xd8\x62\x16\x49\x1d\xd1\xec\x07\x93\xff\x23\xf0\x67\xb8\x4e\x05\xd7\xfe\x20\xdb\x29\xa6\xb4\x43\xca\x05\xec\xee\x86\xbd\x26\x91\xf7\x16\xbb\x5d\xa3\xa5\x25\x72\x0b\xf5\xb8\xc3\xbe\xce\x68\xf6\x8d\x54\x16\x18\xef\x07\xd3\xcb\x11\xbc\x07\x04\xcf\x36\x6e\x7c\xc5\x8c\x23\xd8\xd7\x0b\x89\xd4\xd0\xcc\x07\xf3\x13\x45\x06\x15\xcc\x31\x8b\x7e\x15\x30\x5f\x73\x64\x3b\xc1\x4e\xa2\x48\xea\x86\x8d\xf7\x31\xfe\x00\xfd\xae\x20\x83\x16\x92\x8d\xa1\x97\x3c\x41\xf8\xce\xc5\x32\x76\x97\x45\x3e\x17\x5c\x27\x43\xe0\x17\x31\xaf\x16\xa6\x57\x41\xca\x79\xf4\x9c\xc7\x35\x3a\xd8\xfc\x02\x99\xf5\x91\x4c\x15\xb3\xf4\x71\x93\x2a\x2e\x52\xc1\x0d\x46\xe8\xed\x86\xee\x8a\x98\xe1\x06\xd3\xdd\x62\xfc\x0c\x36\xda\x45\x0f\xe1\x9d\x54\x09\xbc\x2a\x52\xff\x41\x5b\x13\xec\x2d\x7c\xe6\x2f\x12\xed\x63\xe2\x19\x64\xb6\x45\x76\x43\x4c\x7c\x89\xfd\x24\x91\x49\xe8\xaf\x39\x52\xdc\xa3\xe7\x23\x92\xf1\xd1\xfc\x1f\xfa\x89\x20\x9b\x06\x5a\xf9\xc6\x34\x42\xde\x0d\xef\x2b\x89\x8e\xee\xe8\x68\x8c\x7e\x4d\x09\xde\x17\xa4\xb2\xc4\x34\x8e\xe8\xfd\x4e\xf0\x48\x62\xcb\x7d\xa4\x7a\x42\x5b\x4b\x74\x35\x46\x1f\x4d\xec\x79\x89\x16\x87\xb8\x49\xc8\x01\x3e\xba\xfb\x45\x3b\x5b\xcc\xea\x44\xf0\xe8\x20\x8b\x0c\x3a\x2b\xa2\xd1\x1d\x9a\x5d\xe3\xea\x61\x0f\x6f\xd0\xc2\x1c\x97\xac\x21\xdb\x0c\x9a\xff\x20\x5e\x19\xe3\xdd\x91\x82\x8f\x79\x7a\xb8\x5e\xc8\xf0\x2d\x5c\x2d\x64\xc3\x36\xf2\x15\xb2\xed\x1c\x69\x1c\xb0\xbb\x1d\x76\xbb\x41\x13\xa1\x0e\xc6\xb8\x4e\x02\x5b\xba\x61\x0b\x57\xdc\xb1\x8f\x39\x6e\xd1\xe6\x0c\xd9\xac\xb1\x89\x03\x66\xfc\x8b\x8d\xcd\x91\x66\x02\xf7\xee\xa0\xcf\x06\x26\xe4\xe9\x7b\x05\x3b\x8e\xa0\x7f\x13\x74\xb2\x47\x4b\x05\x74\x53\x40\x8f\x1d\x24\xd3\x45\x1b\x3e\x76\x5f\xc7\xf4\xde\xd8\xed\x0a\xed\x74\x31\xc7\x1a\xc1\xe3\x80\x49\xc7\x31\xc3\x1e\xc1\xa3\x84\x0e\x22\xd8\xe2\x0e\xd9\x46\x71\xc7\x28\xf6\x7c\xc1\xd5\x86\x98\xe4\x0c\xbb\xf3\x31\xe5\x0d\xc1\x73\x87\x5b\x84\xec\x14\x6e\x86\x5f\xa4\x3c\x27\xb8\xef\x91\xe1\x03\x2d\x87\xec\xb0\x47\xf3\x49\xe4\xb9\xc0\xf6\xf2\xe8\x31\x8b\x44\xd3\x98\xf5\x07\xcd\x2e\x31\x9b\x06\xc1\xa3\x82\xdd\x47\x71\x63\x0f\x13\x1f\x62\x9e\x6b\xe4\x1d\xc5\x26\xee\x48\xb3\x8f\x0e\xde\xd8\x44\x17\xe9\xed\x91\x67\xd8\x77\x45\x6c\x3c\xf4\xfb\x10\xb3\x28\x13\x3c\xf6\xe8\xb0\x4e\x10\x66\x7e\xb8\x49\x92\x13\x34\xf2\x85\x99\x46\x91\x48\x11\x33\x6f\x62\xba\x69\x82\x4f\x1c\x37\xe8\x60\xc7\x73\xec\x2e\x81\xf9\xf8\xd8\x58\x16\x7b\xbb\x20\xfb\x27\x76\x3c\x45\xb6\x2f\x34\xfb\x87\x4e\xb3\xc8\xbd\x40\xf0\x9c\xa1\xf5\x22\xf2\x1d\xc3\x84\x3d\xb6\xed\xa3\xfb\x09\x32\x6f\x61\x06\x53\xb4\x10\x72\x5a\xb8\x3b\xb6\x68\xff\x17\xd9\xfe\x20\x5e\x0a\xf3\x6c\x62\xb2\x3d\xec\x72\x81\xb6\x47\xb8\xde\x0d\xd7\x88\x60\x77\x2d\x24\x64\xdf\x43\x12\xcd\xd5\xb1\xd3\x18\x36\xfe\x8d\x54\x9f\xc8\xaa\x8d\x76\x76\xc8\x2a\x8a\xf1\x3f\x68\xe7\x8a\x94\xba\x98\xde\x10\x3b\x1e\xe3\xee\x63\x64\xd3\x41\xfc\x2b\x52\x3c\x60\xe3\x57\xe4\x90\x27\x78\x8c\x09\xee\x67\x5c\x27\x85\x1b\xbf\xd1\x52\x16\xa9\x46\x30\xd1\x1d\x72\x8c\xa2\xa5\x1f\x74\x30\xc4\x46\x2a\x48\xf8\x9d\x97\xb2\xd8\xcb\x05\x7b\x3b\x21\xf5\x39\xb2\x99\x62\x77\x6f\x24\xbd\xc3\xc6\xc7\xb8\xc9\x00\xfd\x7b\x63\xfc\x22\x52\xbc\xe1\x5e\xe1\x1e\x1d\x62\x6b\x77\x74\xdb\x44\xf7\x77\x64\xdb\xc2\xe6\x5b\xc8\x6d\x80\x89\x65\x91\xe3\x1a\x79\x1e\x70\xbd\x70\xef\xae\x90\x79\x19\x3d\x7e\x70\xfd\x23\x3a\x48\xa1\xa5\x09\xea\x57\x71\x5f\x69\xdc\x7c\x83\x5e\xea\xd8\xcc\x0f\x1a\x89\x60\x2f\x57\xc4\xab\x23\x33\x8f\xe0\x99\xc3\x44\x2f\x98\x55\x09\x17\x69\x60\xa2\x1b\xec\xa5\x87\xbc\x6a\x48\xf9\x0f\xf7\xac\xa3\xb5\x0d\xa6\xd7\xc6\x4e\xa3\xb8\xce\x1a\xf1\x6e\x48\x63\x87\xbc\xbe\xb0\xe5\x02\xc6\xdb\x21\x91\x21\xe6\xd4\xc4\xf4\x9a\xe8\xea\x07\xf3\xb7\xc0\x2c\xa3\x48\xee\x07\x19\xc5\x90\xe1\x10\xfd\xfe\x41\xaf\x0b\xe4\x91\x44\xea\x19\xcc\xef\x10\x93\x0a\x7b\xe2\x17\x3d\xbd\xb0\x89\x2a\x32\x9d\x61\x26\x27\xf4\x6f\x89\x8b\x16\x09\xde\x4b\x64\xb7\x42\xbf\x26\xc8\xcb\xc7\x76\xaa\x68\xb3\x8f\x6d\x86\xcc\xb5\xc1\x78\x27\xe4\xf9\xc0\xcd\x8f\x04\xcf\x3b\x9a\x6b\xe3\x42\x9e\x7b\x7c\xd0\x6e\x0b\x5b\xbc\x61\xea\x0b\x64\xfc\x8d\x78\x39\xcc\xa6\x8a\x46\xaf\x68\xe6\x86\xdd\x7e\x90\x71\x03\x99\xa7\x71\x91\x32\x1a\x66\x73\x26\x82\xb6\x42\x6f\x85\x9d\x37\x46\xf7\x3b\x5c\x34\x4d\xe0\xbf\xd0\x5d\x0d\x3d\xcd\x71\x91\x08\x7a\x6e\xa1\xd5\x14\x26\xba\x47\x5e\x61\xa7\x35\xb1\x91\x16\x32\x2b\xa3\xf9\x35\xf2\xe9\xe0\xea\x7d\x4c\x61\x8b\x19\xff\x11\x78\x19\xcc\x23\x8a\xf4\x33\xb8\x5e\xc8\x88\x2f\x82\xf0\x3d\x73\x2f\xcc\x2e\xec\xc3\x0b\xae\x1d\x32\x5b\xc8\x1c\xe1\xc6\x7a\x21\xa3\x14\xae\x97\xc0\x7e\x4a\xe8\xa9\x87\xc9\xdc\xd1\xf9\x13\x17\xfd\x60\xf7\x79\xa4\xb2\xc2\xa5\x4b\x98\x42\x98\xe3\x2d\xcc\x79\x87\x44\xcb\x48\xf2\x8e\x5b\xa4\x30\xe7\x09\x66\xb9\xc0\x26\x62\x68\xc8\x3e\xe1\x99\x0f\x29\xe4\x13\x7a\xae\x8d\xc6\x73\xc8\x38\xdc\xc4\x2d\x34\x91\x41\xfb\x07\xb4\xf7\xc1\x78\x33\xcc\xb1\x85\x44\xde\xc8\xbe\x8b\x69\xf5\xd0\x79\x17\xfb\xdf\x87\x79\xec\x79\x83\x99\x86\xb9\xda\x43\x0f\x21\xc3\x44\x31\x93\x12\xee\x67\x85\xe9\x55\xd1\xe2\x17\xf2\x1c\xa2\xdd\x33\x92\x3d\x62\xcf\x3b\x74\x9b\xc3\xa5\x73\xd8\x5d\x91\xc0\x1b\x23\xa1\x96\xc6\x61\xee\x86\xdd\x93\x41\xf6\x6d\x5c\xcb\x47\xcb\x1b\x4c\x6c\x8b\x6e\xf3\x48\xea\x0f\x1d\xcf\x91\x45\x1a\xbb\x59\x60\xfc\x27\x9a\xef\x21\x95\x33\x81\xdf\x46\x2f\x5b\x5c\x74\x83\xbc\x2b\x68\x6c\x85\x56\xd3\xd8\xfd\x0d\x7b\xf9\xc6\x6c\xc3\x5d\xd0\xc0\x6e\x27\x98\xc6\x0d\xa9\x3c\x90\x5e\xa8\x97\x50\xbb\x15\xec\x39\xec\xe3\x3c\xa6\xe4\x23\xb7\x15\x36\x12\x72\xc7\x02\x5b\x0c\xf7\xff\x06\x7d\xbc\x71\x8d\x2d\x92\x0e\xf7\x92\x8f\x6b\x24\xd1\xaf\x50\x3b\x6b\x24\x3b\x47\xd2\x03\xcc\xe4\x80\x7b\x7d\xd0\xcc\x0f\x26\xf6\xc4\x79\x3e\xc6\xf3\x30\x8b\x28\xe2\x0d\x31\xbd\x1e\x26\x9b\xc1\x3c\xeb\x48\x3a\x82\x19\xf4\xd0\x76\x01\x59\x77\xd1\x6b\x16\xb3\xa9\x21\xed\x33\x5a\xae\x21\xc7\x3b\xda\x0f\xb3\x2a\x81\x1d\xb7\xb0\xad\x32\xb2\xac\x62\xcf\x77\x6c\xb2\x82\xcc\xcf\xc8\xd7\x02\x8d\xef\x08\x1e\x6d\x82\x67\x07\x8d\x4e\x90\x42\x04\xe3\x1d\xd0\x6c\x09\xfb\x5e\x63\x23\x27\xe4\xf5\x83\x4d\x4f\x09\xbc\x0f\xa6\x16\x32\xd5\x05\x9b\xc8\x62\x96\x11\x6c\x65\x45\xf0\x49\x60\x5e\x55\x6c\x26\xf4\x44\x0b\x69\xde\x30\xde\x05\xd9\xdd\xd1\x43\x0b\x2d\xc4\xd0\xf3\x0f\xf6\xec\xe1\x5a\x3f\xe8\xf0\x0f\x93\x49\x61\xe2\x3b\xf4\x3c\xc7\xac\x7c\x64\xd2\xc1\xbe\x76\x48\x3e\x8d\xc4\xcb\xa8\xdf\x45\x4a\x6d\x6c\xad\x83\xcd\x9d\xb0\xb1\x1d\x32\x18\xa3\xc3\x03\xb6\x38\xc6\x26\x3f\x04\x7e\xa8\xd3\x24\xb2\x7f\x63\x5f\x4b\x24\xb5\xc7\x9e\xc7\x98\x8e\x8f\xf3\x4b\x48\x36\x87\xab\xf9\x48\x3e\xdc\x48\x71\x5c\x37\xcc\xfe\x15\x2e\xbe\x41\x4e\x7b\xe4\x1e\x45\xef\x3b\x82\x67\x19\xfb\x5a\x11\x78\x6b\x74\xf7\x85\xd6\x17\xd8\xd2\x2f\x92\xf1\xd0\xcb\x0f\x66\xd9\x46\xcb\x67\x74\xf4\x83\x44\xc3\xae\xdf\x62\x63\x63\xe4\xd8\xc3\x34\xda\xe8\x69\x8c\x19\x8c\x31\xbf\xe1\x8e\x09\xcf\x3c\xc3\xb5\x23\x04\xcf\x2a\x7a\x48\x63\x33\x45\x4c\x98\xdb\xfe\x17\x26\x76\x47\xea\x47\xcc\xf4\x86\xf1\x43\x56\xcf\xa3\xb7\x31\xb2\x6f\x22\x95\x70\xa3\xdd\xd0\xe1\x19\xa9\x66\x90\x77\x0d\x37\xe9\xa3\xa7\x1f\xcc\xaa\x88\x7c\xc2\x67\x5d\xb0\xf5\x01\x9a\x6f\xa2\xe7\x6f\xb4\x94\xc1\x7d\xf5\xb1\xef\x1e\x32\xdd\xe2\x1a\xa1\x9f\x7e\xb1\x9d\x2e\xf2\xdc\xa1\xd5\x35\x1a\x9e\xf5\xf1\x44\xfc\x1b\xb2\xcf\x61\x7e\x5a\x98\x70\x1b\x3e\x13\xb8\xee\x15\xd3\xac\xa2\xfb\x32\xb2\xfd\x45\x96\x15\x5c\x3f\x8d\xa9\x7e\xa3\x91\x1f\x64\x3f\xc3\x54\xce\xc8\xfb\x07\x2d\x97\xb1\xa9\x3e\xf6\x33\x40\x66\x0f\x6c\x72\x8f\x79\xb6\x31\xe5\x11\x66\x7d\x43\xa7\x5b\xf4\x7b\x80\xf9\x7d\xa0\xc7\x21\x12\xfb\xc3\xf8\x27\xe4\x93\xc2\xc5\x16\x48\x76\x8d\x3c\xee\xe8\x25\x85\x8e\xc2\x5c\x9b\x63\xb2\x1d\xec\x79\x8b\x99\x3d\xd1\x90\xa3\x6b\x23\x8c\xf7\xc0\xbc\x26\x68\xbe\x88\x84\xfc\xdd\xcc\x61\x27\x4d\x64\x18\x47\xf2\x33\xcc\xab\x8b\x49\x2c\xd0\x57\x9f\xe0\x59\x44\x26\x2b\xf4\xef\x88\x79\x0e\x90\x65\x1d\xc9\xe4\x70\xf3\x03\x81\xff\x41\xe6\x4d\x5c\x7d\x80\xfb\x7b\x12\xdc\x5f\xd8\xdb\x0a\x17\x7a\xbd\x10\xfe\xfe\x8d\x66\x7f\x91\xe6\x00\x3b\xc9\x63\x62\x1b\xf4\x30\x46\x1e\x5f\xd8\xdd\x1d\x79\x86\xfb\xef\x80\x4e\x92\xc8\xfc\x8a\x9e\xa3\x98\xe8\x1b\x9b\x19\xe2\xb2\x67\x6c\x3e\xe4\xbd\x27\x1a\xfe\xcd\x2e\x8a\xa6\x63\x48\x98\xe9\x1d\x0f\x19\x36\x90\x5d\x02\x39\xe4\xb0\xb7\x38\x7a\x1f\xa3\x85\x2a\xc1\xfd\x81\xcd\x86\x3a\x0d\xfd\x1e\xb2\x55\xc8\x7c\x0f\x34\x73\xc6\x8c\xa2\xe8\x64\x81\x0d\x33\x3c\xd5\xc0\x5e\x66\xe8\xbd\x81\xd4\x37\xe8\xd7\x1f\x6e\xd2\x42\xe6\x0d\x5c\x3d\x49\xe0\x1f\xb1\x9d\x12\x26\xdc\x8a\x8b\x07\xc1\xa3\x8c\x29\x17\x31\x8d\x13\x3a\x2e\xe0\xa2\x17\x24\x19\xc5\x75\x53\xd8\x6f\x8f\xc0\xaf\xe3\x36\x65\x5c\xa3\x82\x76\xea\xe8\x7e\x8b\x24\x9f\xb8\x6e\x05\x33\x29\x62\x2f\xbf\x68\x7e\x85\x7c\x46\xd8\x58\x1c\xf3\xbc\x63\xb2\x17\x34\x37\x41\x8a\x5d\xe4\xb6\x44\xa6\x27\x24\x99\x40\x07\x7d\xec\x76\x87\xdd\x75\x31\x93\x25\x66\x3e\x47\x87\x3b\xdc\xf8\x82\xdc\xc6\x98\xe1\x1a\x8d\x1d\x31\xd1\x02\xee\x9d\x20\x78\x2e\x30\xf3\x15\xb2\xf3\xd1\x71\x0c\x57\xf7\x90\xfe\x14\x8d\x56\xd0\xe8\x1e\x17\xaf\x62\xaf\x53\x34\xf7\x87\x2d\xd6\xb0\xc9\x37\xf6\x7c\x46\x87\x0d\xd4\x3f\x63\x0a\x3d\x5c\xbb\x81\x7d\xa7\x90\x85\x8f\x8c\x7f\xd1\xda\x0c\x89\xad\x30\x9b\x37\xae\xf5\x40\xb3\x7b\xcc\xf9\x17\x33\x8a\xe1\xfe\x6f\xa6\x32\x52\xc9\xe1\x3a\x57\x82\x67\x05\x69\xc6\x30\xcd\x16\xa6\x7e\x45\xd6\x29\x34\xd7\xc5\xa6\x63\x68\xf5\x8e\x7c\x8a\xd8\xce\x1b\xdb\x1f\xe3\x62\x3e\x36\x7e\x47\x6e\x6b\xb4\x30\x43\xa2\x57\xe4\x19\x47\x97\x2f\x24\x77\x24\x78\x9c\x70\xb1\x3a\x52\xc9\x12\xf8\x51\x4c\x3c\x86\x19\x35\x31\xcb\x21\xc1\xa3\x80\xcd\xec\x09\x9e\x67\x4c\xbd\x8f\x5e\x92\x04\xf7\x0e\xda\x8d\x61\xd2\x73\x74\x1d\xe6\xd7\x09\xfb\xb9\xa1\xdd\x90\x2f\x0b\x98\xe5\x12\x1b\x4f\x61\x77\x0b\xcc\x7e\x89\xbd\x97\x31\xf5\x1b\x76\x7f\x40\xaa\x29\x64\xfb\xc6\x9c\x72\xe8\xb9\x87\x7d\x67\xd1\xc4\x0c\xf3\xfb\x8d\xeb\x76\xd0\x48\x0d\x73\x6c\x13\x3c\xc2\x2d\xfe\x83\x8d\xad\x31\x87\x22\xfa\x55\x46\xaf\x31\x4c\xaa\x83\xe9\xa6\x08\xde\x0b\x34\xf6\x87\x96\xda\x04\xde\x2f\xc6\x1b\xe1\x52\x35\x4c\x3e\x86\x6b\x44\xd1\x5b\x04\x8d\xae\x30\xd9\x23\xae\x7f\xc7\x64\xfe\xb0\x97\x32\x2e\x92\xc2\x94\xd6\xb8\xce\x05\x33\x1f\x60\x96\x35\xf4\xd2\xc1\x1e\x0b\xc8\xeb\x81\xbc\x9e\x68\x2c\x8b\xbb\x6f\xb0\xd7\x3c\x92\x9e\xa1\x9d\x15\xe6\x7f\x1e\x65\x30\xcb\x90\x63\x2e\x98\xd7\x11\x9d\xec\x30\xb1\x12\x1a\x66\xde\x34\x8f\x5b\x1f\x30\x9b\x1e\x72\x1a\x23\xa9\x1a\x12\xee\xd9\xdd\x07\xbb\xab\xa2\x97\x3b\x7a\x0a\xf9\xfd\x85\xfd\x0c\x31\xe3\x24\xa6\x99\xc2\x9e\x6f\xe8\xb3\x8c\x59\x7d\x90\xd4\x08\xf9\x5d\x63\xe3\x51\x6c\x6e\x87\xc9\x4e\x90\x72\x0f\xdb\x8d\x20\xf3\x39\xee\x3e\x45\x8e\x1b\xcc\x3b\x87\xa4\x37\x04\xf7\x23\x32\x6e\x63\xfc\x36\x2e\x79\xc1\x7e\x17\x31\xbd\x14\xae\x31\x46\xbc\x0e\x66\xf3\x40\x52\x3e\x36\xdc\x9b\xd5\x04\x76\xb2\xc1\x6c\xf2\x68\xbe\x86\xc4\xbb\x68\xeb\x80\xab\xbd\x71\xf7\x21\xfa\x4c\xa1\xc7\x0c\xa6\x9f\xc5\x34\xcb\xe8\xcd\x47\xa7\x35\xcc\xba\x85\x19\x0f\x70\xc3\x35\x2e\xf2\x44\xb3\x1b\x82\xf7\x0a\x49\x67\xd1\x82\x87\x99\xb4\xd0\xd1\x0b\x13\xab\xa1\x83\x1d\x1a\x9b\xe2\x16\x65\x24\x37\xc0\x1e\x7e\xb0\xef\x17\x92\x8f\xe3\xee\x1f\xb4\xb5\x40\x2a\x61\x46\xf6\x31\x21\xa7\x0f\xf3\xd8\x77\x0e\x0d\xef\x63\xbe\x45\x2b\x7f\xb8\x9f\x18\xf6\xfd\x8d\xe4\xc3\x1c\x9b\x12\x3c\xf7\xd8\x5a\x1e\xe3\xd7\x70\xbd\x37\xc1\x3d\x64\xb0\x0b\xb2\x4c\xa1\xf9\x21\xb2\x4d\x63\xdf\x55\x5c\xe7\x0b\xd7\xfb\x42\x42\xee\xab\x27\x90\x73\x1a\xc9\xfe\x20\x91\x31\x52\x4a\x22\xb5\x3f\xdc\xfa\x8a\x6d\xee\x90\xcc\x0d\x6d\xce\x31\x5f\x3f\xd8\x4b\x1e\x99\x67\x09\x5e\x3d\xf4\x92\x46\x9f\xbf\x68\x2f\x3c\x67\x1a\x57\xeb\xa0\xe3\x38\x9a\xbd\x12\xf8\x0d\xec\xa7\x41\xf0\x69\x11\x78\x65\x6c\xb2\x81\xfb\xce\xa3\xd3\x03\x76\x91\x42\xc7\x29\x34\x96\x40\xca\x0d\xb4\xf6\x8d\xfb\x69\x21\xf9\x36\xda\xf2\xd0\xe3\x1d\xd9\xcc\x90\x4a\x05\xd9\x0c\xd1\xfb\x08\x39\x64\x30\xcd\x37\xb2\xe8\xa0\xf1\x3e\x81\xbf\xc7\xe4\x47\xd8\x78\x04\xbb\xaf\xa0\xb9\x1e\xae\x9f\x45\xc7\x55\x24\xe4\xcc\x76\x0f\x3b\xde\x63\x7a\x2d\xf4\xde\xc2\x26\xca\xd8\x4b\x13\xbd\x16\x30\x8d\x3e\xda\x7b\xe0\xda\x49\x6c\xac\x80\xd4\xd7\x48\x29\x8b\x89\xc7\x31\xde\x1f\xba\x4b\xa2\xed\x15\xc1\xf3\x07\xd3\x4a\x63\x92\x5b\xa4\xfc\xc0\xd5\xb2\x68\x65\x83\x2d\x94\x30\x7f\x4f\x5c\xf2\x86\x44\x6f\xc8\xb3\x8e\x6b\xcc\xd1\x68\x78\xa7\x7b\x64\x50\xc5\x3d\x7d\xcc\xe7\x89\xf1\xae\x48\xb9\x83\xc9\x1f\x70\x91\x2d\xe6\x55\xc1\xf8\x7d\x74\xda\x45\x73\x55\x6c\x6a\x85\x6d\xfc\x21\x3b\x0f\xf7\x33\xc3\xac\x53\x48\xea\x8a\x7e\xef\x90\x54\x01\x09\x77\x5a\xfa\x8e\xf1\x93\xc8\x20\xd4\xb8\x87\x49\xec\xb1\xaf\x3d\xfa\x37\x45\x3b\x79\x4c\x7b\x81\xbc\xc7\xb8\xc6\x06\xd7\x58\x10\xdc\x97\x68\xeb\x0f\xd7\xf0\x91\xef\x04\x5a\xe9\xa3\xd9\x2a\x2e\x16\x21\xf0\x36\xb8\xe4\x0e\xfb\xc9\x60\x33\x35\x6c\x22\x85\x4b\x5e\x71\xad\x23\xf2\x59\xe2\x92\x5d\xdc\xf8\x85\x79\xbf\xd0\xeb\x0a\x29\xde\x09\xfc\x16\xae\x13\x6a\x73\x88\xc6\xd7\xe8\x60\x83\x2c\xbb\xd8\x58\x17\x2d\x66\x71\xd3\x36\xfa\x8c\xa1\xed\x14\xfa\xe7\x21\x95\x37\x2e\x5e\xc2\xc4\x6f\xe8\x21\x8a\x54\x2f\xb8\xf9\x1e\x5b\x59\xe2\x7a\x49\x5c\x6c\x8b\xfd\x44\x31\xe9\x2f\xb4\x56\x43\x96\x3e\xf6\x72\x46\xb6\x67\x4c\x7c\x81\x44\x3c\xe4\x5e\x41\x9b\x55\x5c\x3d\x8e\xb6\x56\xb8\x54\x1a\x5b\x9d\xe2\xc2\xad\xd2\x0b\x39\xf6\x83\xe6\x0b\x48\x2c\x89\x4d\x3e\x90\xc5\x1c\x2d\x67\xb1\xe7\x19\x9a\x4f\xa1\x9b\x1f\x6c\x75\x8c\x8d\x7b\x04\xf7\x09\x7a\x59\x23\xe1\x99\xda\x31\xe4\xfb\x17\x2d\x8c\xb1\xcb\x0c\xf6\xfc\x83\xfe\x67\x98\x33\x7a\x08\x7f\x2e\x20\xa9\xb0\xd7\x3c\x64\xd9\xc7\xee\xc3\xec\xb8\x22\xb9\x70\x5f\xff\x61\xc3\x9d\xd6\x2e\x63\x43\x26\xef\x65\x70\x3f\x55\x82\x47\x03\xf5\x7e\x08\xee\x3d\xa4\x38\x41\x73\x0f\x5c\xeb\x86\xd4\x56\x48\x66\x8b\x5b\xbf\x31\x61\x5e\xc4\x86\x68\xb5\x8d\xab\xd7\xd0\xd2\x0d\x37\x49\x23\x0f\x1f\x1d\x26\xd0\xf8\x08\x8d\xaf\x08\x5e\x27\x02\x3f\x8d\x4d\x86\x8c\x36\x40\xaf\x33\x24\x5b\xc5\x7c\x2f\x91\xd1\x18\x3d\x3d\xb1\xd5\x03\xe6\xb5\xc6\xf5\x8b\x68\xf1\x1b\x1b\x2f\x61\xf3\x45\xd4\x0f\x39\x7c\x8d\x16\x93\xe8\xa3\x8d\x19\x15\x71\xfd\x6f\x5c\xec\x82\xad\x24\x30\xcd\x1d\x7a\x0b\xf7\x4d\xd8\x0b\x39\xcc\xf1\x07\x13\x6f\x23\xdb\x0f\x3a\x9e\xa2\x99\x0c\x6e\x7d\x42\x7e\x63\xd8\xe9\x17\xf2\xee\x60\xb6\x1b\xb4\x58\xc1\xc6\x46\x68\xad\x8a\x76\x6a\xd8\xf7\x0a\xdd\x7e\xb0\xa5\x23\x5a\xcd\xa1\x95\x24\x2e\x79\x40\x0e\x65\x4c\xf3\x17\xa9\x47\xb0\x61\xa6\x8e\x2e\xe8\xf1\x17\xd3\x3d\x60\xbe\x92\x48\x79\x84\x6b\x47\xb1\xa5\x03\xfa\x75\xc4\xbe\x9b\xb8\xda\x1a\xd3\x0a\x77\xd2\x00\xb9\xdd\x70\xf3\x0f\x66\x7e\x27\xb8\xb7\x31\xa5\x04\xea\x85\x5e\xdd\xe3\x22\x3e\xf2\xda\x20\xfb\x70\xdb\x7d\x90\xc5\x0a\x9b\x4d\x23\x95\x6f\xdc\x70\x81\x46\x56\x98\xe1\x16\xdd\xa4\xf9\x17\x00\x00\xff\xff\xbf\x1b\x72\xe3\x00\x20\x00\x00") +var _keysWordsWordlistChinese_simplifiedTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x1c\x97\x55\x76\xeb\x30\x14\x45\xff\xf7\xa8\xc3\xcc\x49\xc3\x69\x98\xda\x86\xd9\x0e\x4c\xc6\xf7\x4a\x9a\xc5\x5b\x7e\x7f\x5d\x5d\x6d\x6c\x45\x07\xf6\x31\xdd\x04\xc1\x3d\x82\xb6\x77\x48\x7f\x45\x70\x2f\x12\x78\x29\xb4\x9f\x45\x6a\x05\x02\xcf\xc3\x7e\x3a\x04\xf7\x0d\x32\x5b\x12\xdc\x3d\x82\x7b\x8e\xe0\xfe\x83\xf4\x5e\x68\xa6\x4a\xe0\xcf\xb1\x8b\x28\x81\xdf\x44\x5b\x57\x74\x30\xc7\x34\x56\x04\xfe\x1f\xa6\x31\x44\x32\x7b\x82\x57\x1f\xe9\xef\x09\xbc\x12\x92\xf6\x90\xfd\x01\xc9\xa4\x90\xdd\x03\xcd\x54\x08\x9e\x5d\xa4\xbc\x23\xb8\xfb\x48\xb9\x8a\x3c\xce\x48\x6e\x85\x54\x0a\xc8\x6d\x4e\xf0\x18\x62\xe3\x2f\x82\x7b\x1e\xfb\x49\x23\x9b\x0a\x76\x77\x26\xf0\x96\x98\x65\x11\x37\x98\x60\x23\x05\xb4\xf9\x40\x2a\x25\x64\xd6\x45\xb6\x5d\xec\xb8\x80\x6c\x16\xe8\xe9\x0b\xcd\x46\xd0\x7d\x15\x79\xb7\x30\x7e\x19\x29\x46\x09\xee\x59\x82\x47\xf8\x99\x3d\xcc\x20\x82\xd9\x64\x71\xf1\x15\xe2\x2d\x90\xed\x15\xd3\xb8\x20\xb9\x1e\x2e\x5d\x40\x16\x31\x74\x7f\x46\x0a\x4d\xdc\x6f\x1b\x9b\xfe\x21\xf0\x0a\x98\x4a\x0a\x7b\xb9\x21\xfb\x32\x26\xbb\xc6\x94\xf6\xc8\xf6\x1b\xc9\x8d\x70\xe9\x32\xee\xff\x7b\xcf\x08\x5e\x75\x24\x73\x45\xfb\x1e\xf2\xaa\x13\xbc\x3e\x98\xd8\x83\xc0\x2f\x11\xdc\xbb\x68\xff\x0f\x29\xf9\x68\x2e\x87\x46\x96\xc8\xfc\x85\x78\x0d\xe4\x19\x41\xb6\x71\xa4\x92\xc1\x7e\xda\x48\x6f\x84\x69\x1c\x90\xe4\x95\xc0\xeb\x61\x12\x57\x24\x5b\x44\x66\x4d\x64\xb6\x46\x1b\x1f\xa4\xd7\x43\x5b\x73\x5c\x6c\x8a\x99\xbd\x09\x1e\x59\x02\x2f\x8f\x3c\x4e\xc8\x6b\x82\xe9\xdd\x91\xe4\x0a\x3b\x5e\xe1\x5a\x67\x74\x74\x23\xb8\x97\x90\xe4\x09\xa9\x24\x70\xe9\x22\xda\xdc\x63\xbc\x0f\x92\x4a\xa2\x5f\x7b\x74\x33\x45\x3e\x71\xa4\x5c\x24\x78\x8d\xd0\x76\x09\xd3\xcf\x23\xa5\x21\x52\xce\x10\x3c\x32\x48\x66\x8d\xee\x1a\x68\xa6\x49\xf0\x4a\x61\xcf\x2b\x74\xdf\xc0\xfc\xfd\x21\x95\x2a\x2e\x5a\x47\xaa\x2f\x74\x33\x43\xca\x6d\x74\x30\x46\xca\x3f\xe8\x71\x8c\xf1\xeb\xd8\xe5\x14\xd7\xda\xa2\x89\x32\xe2\x7b\x68\x3f\x83\x24\xff\xd0\xd6\x08\x73\xf2\x91\x54\x0f\x79\x67\xd0\x78\x12\x1b\x49\xa2\xfd\x08\xe6\x37\x4f\xe0\x4f\xd1\xf8\x09\xb9\x1d\x71\x91\x2e\xf2\xb8\xa2\xe5\x0a\xa6\x77\xc6\x4d\xda\x48\xb2\x8b\x59\xe5\x91\xc3\x17\x81\xd7\x40\xbf\xfb\x68\xb3\x83\x3d\x8c\x91\x6a\x1b\x37\x58\x13\xbc\x8a\x48\x72\x8e\xdc\xef\x68\x33\x8d\x46\x7c\xf4\x6f\x8c\xd4\xa3\xc8\xb3\x8c\x9e\x7d\xec\xf6\x8d\x94\x73\x98\xed\x18\x93\x0d\xef\xee\x8a\xfb\xfa\xa0\x87\x18\x36\x12\x45\x66\x67\x64\xe8\x61\x2f\x09\xec\xfb\x81\x5e\xa2\xd8\xdb\x0e\xe3\x2d\x91\x50\x7b\xbd\x37\x72\x38\x60\xfc\x21\x5a\x9a\x63\x86\x73\xec\x3b\x8e\xec\x53\x18\x3f\x81\x5d\x46\xb1\xdb\x31\x92\xf9\x45\xe6\x0f\x34\x9b\xc7\x2e\x6b\x68\x7f\x88\x8e\x1e\xd8\x6d\xe8\xc7\x0a\x92\xea\xa3\x85\x34\x92\x1e\x11\x3c\x06\x48\xc1\x43\x9e\x1e\xda\x78\x23\xa9\x13\x76\xfe\xc1\x4e\x7e\x91\xc7\x11\x89\x76\x91\x4f\x12\xcd\x84\xdf\x43\x06\xe9\x7d\x23\x99\x0e\x81\x1f\x7a\xad\x89\x16\xb7\xc8\x2c\x81\x6b\x0f\x91\x62\xe8\x8d\x0e\x36\x7b\x44\x92\x59\x5c\x6b\x85\x14\x4f\x04\x9f\x01\x7a\xf4\x91\x42\x0b\x17\x19\x61\x3a\x6f\xec\x32\x81\x89\x6f\x70\x93\x14\xc1\x3d\x8e\x86\x1e\x28\x4f\x09\xee\x7d\x64\xf7\x44\x3a\x2b\xa4\x94\x47\x3e\x2d\x82\x7b\x13\x97\xae\x22\x93\x6f\x02\x2f\x8b\x5e\x4a\xb8\xf6\x15\x3d\x3e\xd0\xc8\x00\xed\xef\xd0\xef\x28\x81\x17\xea\xa2\x85\x8d\x36\x08\xfc\x08\x76\x3b\x43\x92\x1b\x24\x79\x40\x07\x71\xb4\x71\xc5\xee\xa2\x68\xe3\x81\xde\x93\x98\x77\x09\x49\x15\x71\xe9\x34\xf6\xf5\x87\xf6\xce\x48\xf1\x0b\x37\x2d\x21\x99\x34\x9a\xad\x63\x3a\x2f\xf4\xab\x83\x8b\x0c\xb1\xb9\x03\x72\x0f\xbd\x9d\x45\xfa\x1e\xd6\xfb\xc5\xbe\x16\x04\xef\x3c\xa6\x3f\x44\x72\x63\x24\x19\x7a\x21\x8d\xee\xca\x98\xde\x16\x9b\x3e\x61\xdf\x6f\xec\x65\x8f\x59\xee\x30\x33\x0f\xbb\xdd\x22\xd3\x3d\x9a\x9b\xa3\xcd\x16\xb2\x2d\x60\x0e\x3e\x92\xfc\xc5\x2c\x7c\xa4\x58\x42\x2a\x45\xcc\x78\x8b\x66\x8b\x98\x65\x15\x79\x8e\x08\x3e\x63\xdc\xfa\x0f\x9b\x8b\x61\x77\x03\xcc\xe1\x84\x7e\x9d\x31\x6b\x0f\x49\xc6\x91\xd4\x85\xc0\xcf\xe1\x7a\x29\xf4\xbe\x26\x78\x8e\x90\xfe\x10\xbb\xbd\xa3\x9b\x39\xe6\x3d\x43\x1e\x1f\xcc\xf0\x84\xdd\xee\x71\xfd\x08\xba\xbd\x60\x46\x0d\xcc\x57\x01\xcd\x67\xd1\xef\x16\xf2\xce\x23\xe5\x5f\x82\x7b\x03\xb3\xbe\x62\x97\x31\xec\x35\x87\xf1\xd3\xd8\x69\x12\x79\x1d\x30\xdb\x16\xc1\xab\x84\x16\xa2\xb8\xe1\x89\xe0\xd9\x22\x78\x2c\x90\x7b\x1c\x99\x15\x91\xed\x03\x49\x7c\x70\x63\x1f\xd7\x49\x22\x5f\x29\xdc\xe0\x1b\xf7\x53\xc0\x7e\xbe\xd1\xe6\x06\xbd\x1d\x70\xdd\x37\xf6\x53\xc5\x0c\x3f\x48\x31\x8e\x54\x57\xc8\xb2\x81\x39\x8f\xd0\x5c\x04\x99\xa5\x91\x62\x0e\xc9\x7d\xe3\x06\x35\x4c\x3f\x8a\x64\xc2\x67\x8d\x90\x7a\x11\xe3\x2d\xd0\xc6\x0e\x9b\xf9\x43\xca\x47\x34\x11\xde\xc3\x89\xe0\x1d\xe6\xd8\x04\x79\x47\x70\xc9\x3b\x52\x4a\x21\xf7\x18\x92\xcc\x13\xbc\xbe\x70\x9d\x19\x7a\xcd\xa0\xdf\x09\xc4\xeb\x63\x96\x7b\x64\xf6\x83\xa4\x53\x98\xe3\x1b\x89\x3c\x91\xf2\x0d\x53\x4a\xa3\xad\x32\xc6\x3f\x23\x99\x1a\x2e\x92\x45\x47\x69\x24\xd5\x41\x36\x6d\x24\xd2\x41\x77\x3d\x02\xef\x88\x7c\x7e\xd1\xaf\x0c\xda\xdc\xe1\x3a\x13\x74\x38\x47\x0f\x43\xe4\x3b\xd4\xc7\x13\x53\xca\xa3\x85\xf0\xff\x9f\x48\xd2\x47\xdb\x75\xcc\x6b\x8b\x9e\x43\x5f\xc7\x30\xd9\x34\xb2\xcc\x23\xc5\x33\xc1\xbd\x8e\xc9\x5d\xb1\xb1\x23\x52\x8a\x11\x78\x7f\xd8\x5d\x0a\x17\x89\x21\x87\x6f\xa4\x9f\x42\x0a\x49\x4c\xf4\x97\xe0\x55\xc6\xee\xe3\xa8\x3f\x46\x4a\x1f\xe4\x10\xc1\x24\x97\x48\x39\x86\xf1\x26\x18\x3f\x85\x3c\xbf\x90\x4a\xf8\x19\x73\x5c\x3d\xec\xdb\x50\xa7\x73\xdc\xa2\x89\x78\x5f\xe8\xf5\x88\x6c\xdb\xc8\xfb\x86\xeb\x96\x31\xad\x24\x36\x5f\x46\x66\x07\x64\xdf\x40\x37\x61\x7e\x1d\x71\xc9\x22\x32\x3f\xe1\xfc\x04\x5a\x5a\xa1\xed\x37\x76\x9f\xc1\xbc\x7e\x30\xf3\x6f\x6c\xd6\x43\xaa\x13\x24\xec\xfc\xca\x2f\xc1\x33\x8a\xf6\x7b\xc8\x2e\x85\x66\x1f\xd8\xca\x1c\x37\x7e\xe0\xda\x47\x82\xfb\x1b\x53\x89\x63\xf3\x07\x74\xbf\x44\x72\x1f\xa4\x9a\x43\x07\x25\xa4\xbc\xc7\x56\x5e\x68\x7f\x85\xdc\xb7\xd8\xd7\x16\x33\x0a\x3b\xbb\x8b\xdc\xc3\x1c\x3a\xa3\xa7\x15\xf6\xd3\x47\x36\x2d\x74\x50\x41\x4b\x35\x82\x77\x0f\x3d\x9e\xd0\x30\x4f\xf7\x51\xa4\xbc\x40\x9b\x2f\x24\x5d\x46\x47\x55\xd4\xbb\xa2\x91\x12\xba\x99\xa0\xe3\x0c\x76\x15\x41\xa6\xbf\xc8\x20\x8d\x6e\x16\x48\xcf\x43\xca\x57\xdc\xe1\x89\x9e\x26\xd8\x65\x8a\xc0\x4f\x62\xcf\x0f\xcc\x79\x89\xc9\x1c\x90\xdb\x02\xf3\x3b\x42\x5b\x6b\xb4\x3f\x40\xb6\x27\x8c\xbf\xc1\xbe\x7c\xb4\x5f\xc4\xee\xc2\x0c\x19\x22\xc9\x24\x92\xbc\xa0\x5e\x05\xc9\xcc\xd0\x5c\x98\x4f\x77\xec\xf5\x84\x0e\x2b\x18\x3f\x8e\xdc\xc2\x8c\x38\xa3\x83\x0f\xa6\xb1\xc7\x75\x8a\x38\xbf\x8a\xc9\xed\xb0\xe7\x21\x92\xf6\xb1\x85\x38\xc6\x5f\x22\xc9\x33\xc1\xf3\x49\xf0\xea\x20\x83\x2e\xda\x3b\x62\xdf\x75\x82\xcf\x16\xfd\x4a\x22\xc3\x90\x5d\x7e\x91\xd9\x10\x17\x89\x62\xfe\x1a\xd8\xcc\x03\x29\x8e\x90\xf2\x09\x7b\x9e\x20\x95\x38\xb2\x2b\xa0\xed\x39\x36\x5a\xc0\x2e\xb3\xe8\x21\x8b\x69\xf8\x48\x6e\x88\xdc\xce\xd8\xdb\x10\x1b\xe6\xde\x20\x86\x9b\x7e\xa3\xd3\x08\x52\xb9\x23\xb9\x35\x52\x4c\xe3\xda\x27\x02\xaf\x86\x64\x06\x48\xa6\x87\xe6\x5a\xd8\x48\x1c\xcd\x7d\x21\x83\x32\x66\xd3\x44\xca\x33\xe4\x9d\x40\x8b\x13\xb4\xff\x83\xbd\x55\x31\x61\x8e\xd6\x26\x68\xef\x8d\xf9\x0d\xcf\x37\xc5\xfc\x76\x30\xdb\x08\xf6\xb3\xc7\xd5\x0e\x48\x76\x87\xec\x5f\xc8\x7d\x80\xec\x13\xd8\x62\x16\x49\x1d\xd1\xec\x07\x93\xff\x23\xf0\x67\xb8\x4e\x05\xd7\xfe\x20\xdb\x29\xa6\xb4\x43\xca\x05\xec\xee\x86\xbd\x26\x91\xf7\x16\xbb\x5d\xa3\xa5\x25\x72\x0b\xf5\xb8\xc3\xbe\xce\x68\xf6\x8d\x54\x16\x18\xef\x07\xd3\xcb\x11\xbc\x07\x04\xcf\x36\x6e\x7c\xc5\x8c\x23\xd8\xd7\x0b\x89\xd4\xd0\xcc\x07\xf3\x13\x45\x06\x15\xcc\x31\x8b\x7e\x15\x30\x5f\x73\x64\x3b\xc1\x4e\xa2\x48\xea\x86\x8d\xf7\x31\xfe\x00\xfd\xae\x20\x83\x16\x92\x8d\xa1\x97\x3c\x41\xf8\xce\xc5\x32\x76\x97\x45\x3e\x17\x5c\x27\x43\xe0\x17\x31\xaf\x16\xa6\x57\x41\xca\x79\xf4\x9c\xc7\x35\x3a\xd8\xfc\x02\x99\xf5\x91\x4c\x15\xb3\xf4\x71\x93\x2a\x2e\x52\xc1\x0d\x46\xe8\xed\x86\xee\x8a\x98\xe1\x06\xd3\xdd\x62\xfc\x0c\x36\xda\x45\x0f\xe1\x9d\x54\x09\xbc\x2a\x52\xff\x41\x5b\x13\xec\x2d\x7c\xe6\x2f\x12\xed\x63\xe2\x19\x64\xb6\x45\x76\x43\x4c\x7c\x89\xfd\x24\x91\x49\xe8\xaf\x39\x52\xdc\xa3\xe7\x23\x92\xf1\xd1\xfc\x1f\xfa\x89\x20\x9b\x06\x5a\xf9\xc6\x34\x42\xde\x0d\xef\x2b\x89\x8e\xee\xe8\x68\x8c\x7e\x4d\x09\xde\x17\xa4\xb2\xc4\x34\x8e\xe8\xfd\x4e\xf0\x48\x62\xcb\x7d\xa4\x7a\x42\x5b\x4b\x74\x35\x46\x1f\x4d\xec\x79\x89\x16\x87\xb8\x49\xc8\x01\x3e\xba\xfb\x45\x3b\x5b\xcc\xea\x44\xf0\xe8\x20\x8b\x0c\x3a\x2b\xa2\xd1\x1d\x9a\x5d\xe3\xea\x61\x0f\x6f\xd0\xc2\x1c\x97\xac\x21\xdb\x0c\x9a\xff\x20\x5e\x19\xe3\xdd\x91\x82\x8f\x79\x7a\xb8\x5e\xc8\xf0\x2d\x5c\x2d\x64\xc3\x36\xf2\x15\xb2\xed\x1c\x69\x1c\xb0\xbb\x1d\x76\xbb\x41\x13\xa1\x0e\xc6\xb8\x4e\x02\x5b\xba\x61\x0b\x57\xdc\xb1\x8f\x39\x6e\xd1\xe6\x0c\xd9\xac\xb1\x89\x03\x66\xfc\x8b\x8d\xcd\x91\x66\x02\xf7\xee\xa0\xcf\x06\x26\xe4\xe9\x7b\x05\x3b\x8e\xa0\x7f\x13\x74\xb2\x47\x4b\x05\x74\x53\x40\x8f\x1d\x24\xd3\x45\x1b\x3e\x76\x5f\xc7\xf4\xde\xd8\xed\x0a\xed\x74\x31\xc7\x1a\xc1\xe3\x80\x49\xc7\x31\xc3\x1e\xc1\xa3\x84\x0e\x22\xd8\xe2\x0e\xd9\x46\x71\xc7\x28\xf6\x7c\xc1\xd5\x86\x98\xe4\x0c\xbb\xf3\x31\xe5\x0d\xc1\x73\x87\x5b\x84\xec\x14\x6e\x86\x5f\xa4\x3c\x27\xb8\xef\x91\xe1\x03\x2d\x87\xec\xb0\x47\xf3\x49\xe4\xb9\xc0\xf6\xf2\xe8\x31\x8b\x44\xd3\x98\xf5\x07\xcd\x2e\x31\x9b\x06\xc1\xa3\x82\xdd\x47\x71\x63\x0f\x13\x1f\x62\x9e\x6b\xe4\x1d\xc5\x26\xee\x48\xb3\x8f\x0e\xde\xd8\x44\x17\xe9\xed\x91\x67\xd8\x77\x45\x6c\x3c\xf4\xfb\x10\xb3\x28\x13\x3c\xf6\xe8\xb0\x4e\x10\x66\x7e\xb8\x49\x92\x13\x34\xf2\x85\x99\x46\x91\x48\x11\x33\x6f\x62\xba\x69\x82\x4f\x1c\x37\xe8\x60\xc7\x73\xec\x2e\x81\xf9\xf8\xd8\x58\x16\x7b\xbb\x20\xfb\x27\x76\x3c\x45\xb6\x2f\x34\xfb\x87\x4e\xb3\xc8\xbd\x40\xf0\x9c\xa1\xf5\x22\xf2\x1d\xc3\x84\x3d\xb6\xed\xa3\xfb\x09\x32\x6f\x61\x06\x53\xb4\x10\x72\x5a\xb8\x3b\xb6\x68\xff\x17\xd9\xfe\x20\x5e\x0a\xf3\x6c\x62\xb2\x3d\xec\x72\x81\xb6\x47\xb8\xde\x0d\xd7\x88\x60\x77\x2d\x24\x64\xdf\x43\x12\xcd\xd5\xb1\xd3\x18\x36\xfe\x8d\x54\x9f\xc8\xaa\x8d\x76\x76\xc8\x2a\x8a\xf1\x3f\x68\xe7\x8a\x94\xba\x98\xde\x10\x3b\x1e\xe3\xee\x63\x64\xd3\x41\xfc\x2b\x52\x3c\x60\xe3\x57\xe4\x90\x27\x78\x8c\x09\xee\x67\x5c\x27\x85\x1b\xbf\xd1\x52\x16\xa9\x46\x30\xd1\x1d\x72\x8c\xa2\xa5\x1f\x74\x30\xc4\x46\x2a\x48\xf8\x9d\x97\xb2\xd8\xcb\x05\x7b\x3b\x21\xf5\x39\xb2\x99\x62\x77\x6f\x24\xbd\xc3\xc6\xc7\xb8\xc9\x00\xfd\x7b\x63\xfc\x22\x52\xbc\xe1\x5e\xe1\x1e\x1d\x62\x6b\x77\x74\xdb\x44\xf7\x77\x64\xdb\xc2\xe6\x5b\xc8\x6d\x80\x89\x65\x91\xe3\x1a\x79\x1e\x70\xbd\x70\xef\xae\x90\x79\x19\x3d\x7e\x70\xfd\x23\x3a\x48\xa1\xa5\x09\xea\x57\x71\x5f\x69\xdc\x7c\x83\x5e\xea\xd8\xcc\x0f\x1a\x89\x60\x2f\x57\xc4\xab\x23\x33\x8f\xe0\x99\xc3\x44\x2f\x98\x55\x09\x17\x69\x60\xa2\x1b\xec\xa5\x87\xbc\x6a\x48\xf9\x0f\xf7\xac\xa3\xb5\x0d\xa6\xd7\xc6\x4e\xa3\xb8\xce\x1a\xf1\x6e\x48\x63\x87\xbc\xbe\xb0\xe5\x02\xc6\xdb\x21\x91\x21\xe6\xd4\xc4\xf4\x9a\xe8\xea\x07\xf3\xb7\xc0\x2c\xa3\x48\xee\x07\x19\xc5\x90\xe1\x10\xfd\xfe\x41\xaf\x0b\xe4\x91\x44\xea\x19\xcc\xef\x10\x93\x0a\x7b\xe2\x17\x3d\xbd\xb0\x89\x2a\x32\x9d\x61\x26\x27\xf4\x6f\x89\x8b\x16\x09\xde\x4b\x64\xb7\x42\xbf\x26\xc8\xcb\xc7\x76\xaa\x68\xb3\x8f\x6d\x86\xcc\xb5\xc1\x78\x27\xe4\xf9\xc0\xcd\x8f\x04\xcf\x3b\x9a\x6b\xe3\x42\x9e\x7b\x7c\xd0\x6e\x0b\x5b\xbc\x61\xea\x0b\x64\xfc\x8d\x78\x39\xcc\xa6\x8a\x46\xaf\x68\xe6\x86\xdd\x7e\x90\x71\x03\x99\xa7\x71\x91\x32\x1a\x66\x73\x26\x82\xb6\x42\x6f\x85\x9d\x37\x46\xf7\x3b\x5c\x34\x4d\xe0\xbf\xd0\x5d\x0d\x3d\xcd\x71\x91\x08\x7a\x6e\xa1\xd5\x14\x26\xba\x47\x5e\x61\xa7\x35\xb1\x91\x16\x32\x2b\xa3\xf9\x35\xf2\xe9\xe0\xea\x7d\x4c\x61\x8b\x19\xff\x11\x78\x19\xcc\x23\x8a\xf4\x33\xb8\x5e\xc8\x88\x2f\x82\xf0\x3d\x73\x2f\xcc\x2e\xec\xc3\x0b\xae\x1d\x32\x5b\xc8\x1c\xe1\xc6\x7a\x21\xa3\x14\xae\x97\xc0\x7e\x4a\xe8\xa9\x87\xc9\xdc\xd1\xf9\x13\x17\xfd\x60\xf7\x79\xa4\xb2\xc2\xa5\x4b\x98\x42\x98\xe3\x2d\xcc\x79\x87\x44\xcb\x48\xf2\x8e\x5b\xa4\x30\xe7\x09\x66\xb9\xc0\x26\x62\x68\xc8\x3e\xe1\x99\x0f\x29\xe4\x13\x7a\xae\x8d\xc6\x73\xc8\x38\xdc\xc4\x2d\x34\x91\x41\xfb\x07\xb4\xf7\xc1\x78\x33\xcc\xb1\x85\x44\xde\xc8\xbe\x8b\x69\xf5\xd0\x79\x17\xfb\xdf\x87\x79\xec\x79\x83\x99\x86\xb9\xda\x43\x0f\x21\xc3\x44\x31\x93\x12\xee\x67\x85\xe9\x55\xd1\xe2\x17\xf2\x1c\xa2\xdd\x33\x92\x3d\x62\xcf\x3b\x74\x9b\xc3\xa5\x73\xd8\x5d\x91\xc0\x1b\x23\xa1\x96\xc6\x61\xee\x86\xdd\x93\x41\xf6\x6d\x5c\xcb\x47\xcb\x1b\x4c\x6c\x8b\x6e\xf3\x48\xea\x0f\x1d\xcf\x91\x45\x1a\xbb\x59\x60\xfc\x27\x9a\xef\x21\x95\x33\x81\xdf\x46\x2f\x5b\x5c\x74\x83\xbc\x2b\x68\x6c\x85\x56\xd3\xd8\xfd\x0d\x7b\xf9\xc6\x6c\xc3\x5d\xd0\xc0\x6e\x27\x98\xc6\x0d\xa9\x3c\x90\x5e\xa8\x97\x50\xbb\x15\xec\x39\xec\xe3\x3c\xa6\xe4\x23\xb7\x15\x36\x12\x72\xc7\x02\x5b\x0c\xf7\xff\x06\x7d\xbc\x71\x8d\x2d\x92\x0e\xf7\x92\x8f\x6b\x24\xd1\xaf\x50\x3b\x6b\x24\x3b\x47\xd2\x03\xcc\xe4\x80\x7b\x7d\xd0\xcc\x0f\x26\xf6\xc4\x79\x3e\xc6\xf3\x30\x8b\x28\xe2\x0d\x31\xbd\x1e\x26\x9b\xc1\x3c\xeb\x48\x3a\x82\x19\xf4\xd0\x76\x01\x59\x77\xd1\x6b\x16\xb3\xa9\x21\xed\x33\x5a\xae\x21\xc7\x3b\xda\x0f\xb3\x2a\x81\x1d\xb7\xb0\xad\x32\xb2\xac\x62\xcf\x77\x6c\xb2\x82\xcc\xcf\xc8\xd7\x02\x8d\xef\x08\x1e\x6d\x82\x67\x07\x8d\x4e\x90\x42\x04\xe3\x1d\xd0\x6c\x09\xfb\x5e\x63\x23\x27\xe4\xf5\x83\x4d\x4f\x09\xbc\x0f\xa6\x16\x32\xd5\x05\x9b\xc8\x62\x96\x11\x6c\x65\x45\xf0\x49\x60\x5e\x55\x6c\x26\xf4\x44\x0b\x69\xde\x30\xde\x05\xd9\xdd\xd1\x43\x0b\x2d\xc4\xd0\xf3\x0f\xf6\xec\xe1\x5a\x3f\xe8\xf0\x0f\x93\x49\x61\xe2\x3b\xf4\x3c\xc7\xac\x7c\x64\xd2\xc1\xbe\x76\x48\x3e\x8d\xc4\xcb\xa8\xdf\x45\x4a\x6d\x6c\xad\x83\xcd\x9d\xb0\xb1\x1d\x32\x18\xa3\xc3\x03\xb6\x38\xc6\x26\x3f\x04\x7e\xa8\xd3\x24\xb2\x7f\x63\x5f\x4b\x24\xb5\xc7\x9e\xc7\x98\x8e\x8f\xf3\x4b\x48\x36\x87\xab\xf9\x48\x3e\xdc\x48\x71\x5c\x37\xcc\xfe\x15\x2e\xbe\x41\x4e\x7b\xe4\x1e\x45\xef\x3b\x82\x67\x19\xfb\x5a\x11\x78\x6b\x74\xf7\x85\xd6\x17\xd8\xd2\x2f\x92\xf1\xd0\xcb\x0f\x66\xd9\x46\xcb\x67\x74\xf4\x83\x44\xc3\xae\xdf\x62\x63\x63\xe4\xd8\xc3\x34\xda\xe8\x69\x8c\x19\x8c\x31\xbf\xe1\x8e\x09\xcf\x3c\xc3\xb5\x23\x04\xcf\x2a\x7a\x48\x63\x33\x45\x4c\x98\xdb\xfe\x17\x26\x76\x47\xea\x47\xcc\xf4\x86\xf1\x43\x56\xcf\xa3\xb7\x31\xb2\x6f\x22\x95\x70\xa3\xdd\xd0\xe1\x19\xa9\x66\x90\x77\x0d\x37\xe9\xa3\xa7\x1f\xcc\xaa\x88\x7c\xc2\x67\x5d\xb0\xf5\x01\x9a\x6f\xa2\xe7\x6f\xb4\x94\xc1\x7d\xf5\xb1\xef\x1e\x32\xdd\xe2\x1a\xa1\x9f\x7e\xb1\x9d\x2e\xf2\xdc\xa1\xd5\x35\x1a\x9e\xf5\xf1\x44\xfc\x1b\xb2\xcf\x61\x7e\x5a\x98\x70\x1b\x3e\x13\xb8\xee\x15\xd3\xac\xa2\xfb\x32\xb2\xfd\x45\x96\x15\x5c\x3f\x8d\xa9\x7e\xa3\x91\x1f\x64\x3f\xc3\x54\xce\xc8\xfb\x07\x2d\x97\xb1\xa9\x3e\xf6\x33\x40\x66\x0f\x6c\x72\x8f\x79\xb6\x31\xe5\x11\x66\x7d\x43\xa7\x5b\xf4\x7b\x80\xf9\x7d\xa0\xc7\x21\x12\xfb\xc3\xf8\x27\xe4\x93\xc2\xc5\x16\x48\x76\x8d\x3c\xee\xe8\x25\x85\x8e\xc2\x5c\x9b\x63\xb2\x1d\xec\x79\x8b\x99\x3d\xd1\x90\xa3\x6b\x23\x8c\xf7\xc0\xbc\x26\x68\xbe\x88\x84\xfc\xdd\xcc\x61\x27\x4d\x64\x18\x47\xf2\x33\xcc\xab\x8b\x49\x2c\xd0\x57\x9f\xe0\x59\x44\x26\x2b\xf4\xef\x88\x79\x0e\x90\x65\x1d\xc9\xe4\x70\xf3\x03\x81\xff\x41\xe6\x4d\x5c\x7d\x80\xfb\x7b\x12\xdc\x5f\xd8\xdb\x0a\x17\x7a\xbd\x10\xfe\xfe\x8d\x66\x7f\x91\xe6\x00\x3b\xc9\x63\x62\x1b\xf4\x30\x46\x1e\x5f\xd8\xdd\x1d\x79\x86\xfb\xef\x80\x4e\x92\xc8\xfc\x8a\x9e\xa3\x98\xe8\x1b\x9b\x19\xe2\xb2\x67\x6c\x3e\xe4\xbd\x27\x1a\xfe\xcd\x2e\x8a\xa6\x63\x48\x98\xe9\x1d\x0f\x19\x36\x90\x5d\x02\x39\xe4\xb0\xb7\x38\x7a\x1f\xa3\x85\x2a\xc1\xfd\x81\xcd\x86\x3a\x0d\xfd\x1e\xb2\x55\xc8\x7c\x0f\x34\x73\xc6\x8c\xa2\xe8\x64\x81\x0d\x33\x3c\xd5\xc0\x5e\x66\xe8\xbd\x81\xd4\x37\xe8\xd7\x1f\x6e\xd2\x42\xe6\x0d\x5c\x3d\x49\xe0\x1f\xb1\x9d\x12\x26\xdc\x8a\x8b\x07\xc1\xa3\x8c\x29\x17\x31\x8d\x13\x3a\x2e\xe0\xa2\x17\x24\x19\xc5\x75\x53\xd8\x6f\x8f\xc0\xaf\xe3\x36\x65\x5c\xa3\x82\x76\xea\xe8\x7e\x8b\x24\x9f\xb8\x6e\x05\x33\x29\x62\x2f\xbf\x68\x7e\x85\x7c\x46\xd8\x58\x1c\xf3\xbc\x63\xb2\x17\x34\x37\x41\x8a\x5d\xe4\xb6\x44\xa6\x27\x24\x99\x40\x07\x7d\xec\x76\x87\xdd\x75\x31\x93\x25\x66\x3e\x47\x87\x3b\xdc\xf8\x82\xdc\xc6\x98\xe1\x1a\x8d\x1d\x31\xd1\x02\xee\x9d\x20\x78\x2e\x30\xf3\x15\xb2\xf3\xd1\x71\x0c\x57\xf7\x90\xfe\x14\x8d\x56\xd0\xe8\x1e\x17\xaf\x62\xaf\x53\x34\xf7\x87\x2d\xd6\xb0\xc9\x37\xf6\x7c\x46\x87\x0d\xd4\x3f\x63\x0a\x3d\x5c\xbb\x81\x7d\xa7\x90\x85\x8f\x8c\x7f\xd1\xda\x0c\x89\xad\x30\x9b\x37\xae\xf5\x40\xb3\x7b\xcc\xf9\x17\x33\x8a\xe1\xfe\x6f\xa6\x32\x52\xc9\xe1\x3a\x57\x82\x67\x05\x69\xc6\x30\xcd\x16\xa6\x7e\x45\xd6\x29\x34\xd7\xc5\xa6\x63\x68\xf5\x8e\x7c\x8a\xd8\xce\x1b\xdb\x1f\xe3\x62\x3e\x36\x7e\x47\x6e\x6b\xb4\x30\x43\xa2\x57\xe4\x19\x47\x97\x2f\x24\x77\x24\x78\x9c\x70\xb1\x3a\x52\xc9\x12\xf8\x51\x4c\x3c\x86\x19\x35\x31\xcb\x21\xc1\xa3\x80\xcd\xec\x09\x9e\x67\x4c\xbd\x8f\x5e\x92\x04\xf7\x0e\xda\x8d\x61\xd2\x73\x74\x1d\xe6\xd7\x09\xfb\xb9\xa1\xdd\x90\x2f\x0b\x98\xe5\x12\x1b\x4f\x61\x77\x0b\xcc\x7e\x89\xbd\x97\x31\xf5\x1b\x76\x7f\x40\xaa\x29\x64\xfb\xc6\x9c\x72\xe8\xb9\x87\x7d\x67\xd1\xc4\x0c\xf3\xfb\x8d\xeb\x76\xd0\x48\x0d\x73\x6c\x13\x3c\xc2\x2d\xfe\x83\x8d\xad\x31\x87\x22\xfa\x55\x46\xaf\x31\x4c\xaa\x83\xe9\xa6\x08\xde\x0b\x34\xf6\x87\x96\xda\x04\xde\x2f\xc6\x1b\xe1\x52\x35\x4c\x3e\x86\x6b\x44\xd1\x5b\x04\x8d\xae\x30\xd9\x23\xae\x7f\xc7\x64\xfe\xb0\x97\x32\x2e\x92\xc2\x94\xd6\xb8\xce\x05\x33\x1f\x60\x96\x35\xf4\xd2\xc1\x1e\x0b\xc8\xeb\x81\xbc\x9e\x68\x2c\x8b\xbb\x6f\xb0\xd7\x3c\x92\x9e\xa1\x9d\x15\xe6\x7f\x1e\x65\x30\xcb\x90\x63\x2e\x98\xd7\x11\x9d\xec\x30\xb1\x12\x1a\x66\xde\x34\x8f\x5b\x1f\x30\x9b\x1e\x72\x1a\x23\xa9\x1a\x12\xee\xd9\xdd\x07\xbb\xab\xa2\x97\x3b\x7a\x0a\xf9\xfd\x85\xfd\x0c\x31\xe3\x24\xa6\x99\xc2\x9e\x6f\xe8\xb3\x8c\x59\x7d\x90\xd4\x08\xf9\x5d\x63\xe3\x51\x6c\x6e\x87\xc9\x4e\x90\x72\x0f\xdb\x8d\x20\xf3\x39\xee\x3e\x45\x8e\x1b\xcc\x3b\x87\xa4\x37\x04\xf7\x23\x32\x6e\x63\xfc\x36\x2e\x79\xc1\x7e\x17\x31\xbd\x14\xae\x31\x46\xbc\x0e\x66\xf3\x40\x52\x3e\x36\xdc\x9b\xd5\x04\x76\xb2\xc1\x6c\xf2\x68\xbe\x86\xc4\xbb\x68\xeb\x80\xab\xbd\x71\xf7\x21\xfa\x4c\xa1\xc7\x0c\xa6\x9f\xc5\x34\xcb\xe8\xcd\x47\xa7\x35\xcc\xba\x85\x19\x0f\x70\xc3\x35\x2e\xf2\x44\xb3\x1b\x82\xf7\x0a\x49\x67\xd1\x82\x87\x99\xb4\xd0\xd1\x0b\x13\xab\xa1\x83\x1d\x1a\x9b\xe2\x16\x65\x24\x37\xc0\x1e\x7e\xb0\xef\x17\x92\x8f\xe3\xee\x1f\xb4\xb5\x40\x2a\x61\x46\xf6\x31\x21\xa7\x0f\xf3\xd8\x77\x0e\x0d\xef\x63\xbe\x45\x2b\x7f\xb8\x9f\x18\xf6\xfd\x8d\xe4\xc3\x1c\x9b\x12\x3c\xf7\xd8\x5a\x1e\xe3\xd7\x70\xbd\x37\xc1\x3d\x64\xb0\x0b\xb2\x4c\xa1\xf9\x21\xb2\x4d\x63\xdf\x55\x5c\xe7\x0b\xd7\xfb\x42\x42\xee\xab\x27\x90\x73\x1a\xc9\xfe\x20\x91\x31\x52\x4a\x22\xb5\x3f\xdc\xfa\x8a\x6d\xee\x90\xcc\x0d\x6d\xce\x31\x5f\x3f\xd8\x4b\x1e\x99\x67\x09\x5e\x3d\xf4\x92\x46\x9f\xbf\x68\x2f\x3c\x67\x1a\x57\xeb\xa0\xe3\x38\x9a\xbd\x12\xf8\x0d\xec\xa7\x41\xf0\x69\x11\x78\x65\x6c\xb2\x81\xfb\xce\xa3\xd3\x03\x76\x91\x42\xc7\x29\x34\x96\x40\xca\x0d\xb4\xf6\x8d\xfb\x69\x21\xf9\x36\xda\xf2\xd0\xe3\x1d\xd9\xcc\x90\x4a\x05\xd9\x0c\xd1\xfb\x08\x39\x64\x30\xcd\x37\xb2\xe8\xa0\xf1\x3e\x81\xbf\xc7\xe4\x47\xd8\x78\x04\xbb\xaf\xa0\xb9\x1e\xae\x9f\x45\xc7\x55\x24\xe4\xcc\x76\x0f\x3b\xde\x63\x7a\x2d\xf4\xde\xc2\x26\xca\xd8\x4b\x13\xbd\x16\x30\x8d\x3e\xda\x7b\xe0\xda\x49\x6c\xac\x80\xd4\xd7\x48\x29\x8b\x89\xc7\x31\xde\x1f\xba\x4b\xa2\xed\x15\xc1\xf3\x07\xd3\x4a\x63\x92\x5b\xa4\xfc\xc0\xd5\xb2\x68\x65\x83\x2d\x94\x30\x7f\x4f\x5c\xf2\x86\x44\x6f\xc8\xb3\x8e\x6b\xcc\xd1\x68\x78\xa7\x7b\x64\x50\xc5\x3d\x7d\xcc\xe7\x89\xf1\xae\x48\xb9\x83\xc9\x1f\x70\x91\x2d\xe6\x55\xc1\xf8\x7d\x74\xda\x45\x73\x55\x6c\x6a\x85\x6d\xfc\x21\x3b\x0f\xf7\x33\xc3\xac\x53\x48\xea\x8a\x7e\xef\x90\x54\x01\x09\x77\x5a\xfa\x8e\xf1\x93\xc8\x20\xd4\xb8\x87\x49\xec\xb1\xaf\x3d\xfa\x37\x45\x3b\x79\x4c\x7b\x81\xbc\xc7\xb8\xc6\x06\xd7\x58\x10\xdc\x97\x68\xeb\x0f\xd7\xf0\x91\xef\x04\x5a\xe9\xa3\xd9\x2a\x2e\x16\x21\xf0\x36\xb8\xe4\x0e\xfb\xc9\x60\x33\x35\x6c\x22\x85\x4b\x5e\x71\xad\x23\xf2\x59\xe2\x92\x5d\xdc\xf8\x85\x79\xbf\xd0\xeb\x0a\x29\xde\x09\xfc\x16\xae\x13\x6a\x73\x88\xc6\xd7\xe8\x60\x83\x2c\xbb\xd8\x58\x17\x2d\x66\x71\xd3\x36\xfa\x8c\xa1\xed\x14\xfa\xe7\x21\x95\x37\x2e\x5e\xc2\xc4\x6f\xe8\x21\x8a\x54\x2f\xb8\xf9\x1e\x5b\x59\xe2\x7a\x49\x5c\x6c\x8b\xfd\x44\x31\xe9\x2f\xb4\x56\x43\x96\x3e\xf6\x72\x46\xb6\x67\x4c\x7c\x81\x44\x3c\xe4\x5e\x41\x9b\x55\x5c\x3d\x8e\xb6\x56\xb8\x54\x1a\x5b\x9d\xe2\xc2\xad\xd2\x0b\x39\xf6\x83\xe6\x0b\x48\x2c\x89\x4d\x3e\x90\xc5\x1c\x2d\x67\xb1\xe7\x19\x9a\x4f\xa1\x9b\x1f\x6c\x75\x8c\x8d\x7b\x04\xf7\x09\x7a\x59\x23\xe1\x99\xda\x31\xe4\xfb\x17\x2d\x8c\xb1\xcb\x0c\xf6\xfc\x83\xfe\x67\x98\x33\x7a\x08\x7f\x2e\x20\xa9\xb0\xd7\x3c\x64\xd9\xc7\xee\xc3\xec\xb8\x22\xb9\x70\x5f\xff\x61\xc3\x9d\xd6\x2e\x63\x43\x26\xef\x65\x70\x3f\x55\x82\x47\x03\xf5\x7e\x08\xee\x3d\xa4\x38\x41\x73\x0f\x5c\xeb\x86\xd4\x56\x48\x66\x8b\x5b\xbf\x31\x61\x5e\xc4\x86\x68\xb5\x8d\xab\xd7\xd0\xd2\x0d\x37\x49\x23\x0f\x1f\x1d\x26\xd0\xf8\x08\x8d\xaf\x08\x5e\x27\x02\x3f\x8d\x4d\x86\x8c\x36\x40\xaf\x33\x24\x5b\xc5\x7c\x2f\x91\xd1\x18\x3d\x3d\xb1\xd5\x03\xe6\xb5\xc6\xf5\x8b\x68\xf1\x1b\x1b\x2f\x61\xf3\x45\xd4\x0f\x39\x7c\x8d\x16\x93\xe8\xa3\x8d\x19\x15\x71\xfd\x6f\x5c\xec\x82\xad\x24\x30\xcd\x1d\x7a\x0b\xf7\x4d\xd8\x0b\x39\xcc\xf1\x07\x13\x6f\x23\xdb\x0f\x3a\x9e\xa2\x99\x0c\x6e\x7d\x42\x7e\x63\xd8\xe9\x17\xf2\xee\x60\xb6\x1b\xb4\x58\xc1\xc6\x46\x68\xad\x8a\x76\x6a\xd8\xf7\x0a\xdd\x7e\xb0\xa5\x23\x5a\xcd\xa1\x95\x24\x2e\x79\x40\x0e\x65\x4c\xf3\x17\xa9\x47\xb0\x61\xa6\x8e\x2e\xe8\xf1\x17\xd3\x3d\x60\xbe\x92\x48\x79\x84\x6b\x47\xb1\xa5\x03\xfa\x75\xc4\xbe\x9b\xb8\xda\x1a\xd3\x0a\x77\xd2\x00\xb9\xdd\x70\xf3\x0f\x66\x7e\x27\xb8\xb7\x31\xa5\x04\xea\x85\x5e\xdd\xe3\x22\x3e\xf2\xda\x20\xfb\x70\xdb\x7d\x90\xc5\x0a\x9b\x4d\x23\x95\x6f\xdc\x70\x81\x46\x56\x98\xe1\x16\xdd\xa4\xf9\x17\x00\x00\xff\xff\xbf\x1b\x72\xe3\x00\x20\x00\x00") -func keysWordlistChinese_simplifiedTxtBytes() ([]byte, error) { +func keysWordsWordlistChinese_simplifiedTxtBytes() ([]byte, error) { return bindataRead( - _keysWordlistChinese_simplifiedTxt, - "keys/wordlist/chinese_simplified.txt", + _keysWordsWordlistChinese_simplifiedTxt, + "keys/words/wordlist/chinese_simplified.txt", ) } -func keysWordlistChinese_simplifiedTxt() (*asset, error) { - bytes, err := keysWordlistChinese_simplifiedTxtBytes() +func keysWordsWordlistChinese_simplifiedTxt() (*asset, error) { + bytes, err := keysWordsWordlistChinese_simplifiedTxtBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "keys/wordlist/chinese_simplified.txt", size: 8192, mode: os.FileMode(420), modTime: time.Unix(1511602021, 0)} + info := bindataFileInfo{name: "keys/words/wordlist/chinese_simplified.txt", size: 8192, mode: os.FileMode(420), modTime: time.Unix(1514928181, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _keysWordlistEnglishTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\x5b\xdd\xbe\xbc\x2a\x08\xbd\xf7\x2d\xc9\xa8\xd8\xa3\xe2\x41\x9d\x76\xfb\xe9\xcf\x6f\xad\xfe\x17\x83\xe5\x07\x2a\x22\x2c\xcc\x91\x4d\xda\xee\x2d\xc9\x66\xc5\xe6\x93\x64\x2b\x9a\x64\xf3\x35\x41\xbf\x78\x1e\xda\xf0\x32\x3c\x36\x24\x33\x24\xf3\x7d\xc5\x9e\x64\x5b\x43\x93\xe4\xac\x63\x20\xb1\x9d\x95\x73\xf6\xf5\xa6\x6f\xf1\x65\x0a\x56\xd9\xf6\x24\xd9\xd7\x98\x96\x93\xe4\xff\x96\x05\x72\xc3\xd9\x18\xf5\xa7\x61\x2c\x79\x7a\x80\xc6\xcb\x75\x2e\x29\x49\x76\xe9\x33\xc9\xbe\xe3\x67\x99\x8f\x6f\xf9\xfe\xb3\x06\x5e\xab\x81\xae\x02\xfa\x95\x96\x15\xa9\x21\xd1\xf0\x0d\x3d\x1e\x87\x58\x20\x71\x0c\xfd\x08\xc1\x78\x4e\xb1\x96\xe4\x54\xfc\x30\xe6\x33\x54\x93\x5c\x2a\x7b\x12\xab\x89\x2d\x2c\xba\xc7\x4c\x62\x03\xd2\x29\x12\x35\x49\xd9\x16\x68\xf6\xcb\x4b\x92\xa2\x28\x2f\xa6\x2d\x49\xc1\x7b\xd1\x07\xd4\xef\x24\xa5\x3a\x06\x58\xbc\xa1\x71\xbf\x24\x49\x09\x95\x1d\x15\x86\x27\x29\x53\x23\x49\xb9\xe5\x19\x49\xaa\x4c\x5d\x81\xf4\xcf\xda\x99\xa4\xfa\x4b\x29\xcf\xba\x86\xee\x49\x9a\x94\x07\x1c\x5b\xbe\x20\xa8\x96\x8d\x23\x6f\x27\xf8\xb4\x13\x63\x6c\x67\x3c\x49\x9a\x55\x88\xae\x7d\x98\xd5\x7c\x51\x2a\xad\x51\xa0\xcd\xe7\xc5\x06\xe3\x66\x32\xb5\x35\x41\x6a\xff\x2d\xd4\xfa\x35\x85\x42\xb4\x27\x49\x17\xcc\xae\x7b\xf1\x13\x6f\x5d\x25\x90\x80\x6b\xef\x41\x35\xe9\x61\x25\x49\xe4\x0b\x84\xeb\x1b\x2a\x20\xe0\x19\x27\x38\x42\x6a\x51\x31\x81\xa8\x18\x77\xd4\x27\x49\xf8\x6a\xc8\x09\x0c\x1f\xa9\x62\x66\x11\xf6\xe5\x1b\xe4\x87\xbe\x63\xea\x41\x15\x89\x69\xac\x30\x6f\x8f\x4f\x92\x81\x5f\x57\x94\x8c\x21\x5c\xfc\x31\x94\x94\xf5\xc6\x58\x55\x93\x8c\x79\x55\x49\x32\xaf\xa2\x53\x93\x4c\xaf\x49\xe6\x94\xfc\x41\xa2\x18\xc0\x9c\x36\xd7\x8e\xb2\x7f\x0a\xbe\xfe\x29\xe3\xda\xa1\x57\xeb\xa4\x92\x71\x15\xd6\xa4\xd8\xd7\x74\x90\x55\x5b\x92\xaf\x06\x55\xe8\xeb\x59\x76\x47\x0a\xd5\xba\xe5\xa3\xa0\x41\xfa\x24\xb9\x75\x38\x86\x73\x1f\xab\x24\xb9\x3f\xb7\x40\x11\x7f\x6d\xa4\x4d\xb6\x27\x6d\x92\x2f\x2d\x1e\x78\xf0\x96\x36\xd9\x4f\x4d\x9b\x9c\x69\x93\x42\x85\xde\xa0\x6f\x0d\x15\x4b\x49\x9b\xd4\xcd\x3d\x6d\xd2\xa4\x09\x92\xa6\x68\xc9\x9f\x16\x54\x0a\xea\xf6\x06\xa1\xa2\xfa\x00\x83\x61\x19\xf4\xa3\x33\x6d\x32\x67\xd1\xb4\xa9\xe4\x0b\xb4\x81\xac\xf9\xa4\x4d\xb3\x60\xe3\x6e\x9a\x31\xdc\x4d\xf5\x48\x9b\x1e\x1e\x78\x3e\xc1\x52\x2f\xf9\xe2\xe5\xb2\xb6\xa7\x4d\x0b\xf7\xf7\xa6\x50\xf7\x4d\xcb\x4c\x9b\x36\xf2\x6c\x7a\x18\xde\x06\xc8\x0c\x01\xef\x09\x75\xdf\x74\xde\xaa\xe0\xf4\x38\x58\x58\x7e\x32\xc6\x62\x78\xfe\xe0\x81\xb9\xaf\xc6\x6d\x16\x78\x89\x79\xa5\xcd\xde\xe6\x05\x6b\xb7\x15\xd9\x15\xb4\x92\x36\x4e\xaa\x08\x3a\x2b\x2a\x28\x87\x81\xd8\x0a\x79\x15\x77\xd2\x31\xbc\x22\xe5\x04\xcb\x22\x01\xc3\x35\xae\xb4\x39\x16\x64\x73\x99\x69\xf3\xfd\x49\x9b\x5b\x49\x9b\xd7\x2d\x6d\xd8\xbc\x9b\xb7\x35\xd2\xe6\xfe\x01\x41\x37\x1e\x3b\x46\xe3\x81\xbd\xba\x39\xf5\x75\x83\x39\xdb\x7c\x42\xc9\xb6\x77\xcb\x6d\xfe\x9b\x36\x7f\xd2\x16\x92\x39\xc8\xe0\xc2\x84\x60\x60\x21\xa8\x1f\x14\x28\xcc\x02\xa8\xfe\xe1\xc5\x30\xc7\x30\x6a\x41\x18\x16\x21\xec\xbc\xd0\x9c\xdd\x85\x0d\x94\x7b\xce\x5e\x0c\x0f\x1f\x08\x34\xbc\xb1\xb1\xa3\xfb\x78\xf7\xf8\x16\x7e\xa3\x88\x73\x5c\x1b\x6c\xfc\xb6\x76\x4c\x70\xed\x27\xc6\xb3\x8e\x43\x8a\xa7\x6d\x59\xd9\xd3\xb6\xca\x06\xf2\x01\x29\x2c\x6e\x3b\x9b\xb4\x0f\x98\xad\xd8\xd1\xd1\x8a\xf3\x7d\x83\x20\x20\x97\x35\xac\x51\xe0\x6b\x80\xf3\xbb\x50\xeb\x21\xfd\xfb\x4b\x59\xb6\x0d\x9b\x24\xcb\x66\x0d\xb4\xe0\x39\xcf\x35\x52\x7e\xf3\x3f\x20\xa5\x80\xd4\x94\xa5\x6a\x08\x92\x9e\xb2\xa0\x41\x13\x14\xb5\xac\x4c\xf6\x07\xb4\x39\x4b\x1c\x2d\xdb\x57\xc0\xaa\x3d\xcc\xeb\xff\x3a\xe8\x36\xd9\xae\x4f\x61\xb7\x81\xdf\xc6\x2a\xb1\x83\x9c\x0e\xda\x75\x22\x09\x70\x0d\x3c\x0e\x34\x1e\x17\x88\x35\x54\x19\x93\xfc\xc6\x22\x3b\x54\x99\x52\xfc\x44\x9a\x51\x6d\xea\xe9\x6c\x3e\xdf\x8a\x0b\x4b\xf5\x6e\xa4\x2c\x8b\xc6\x24\x63\x91\xb3\x5a\xc1\xfa\x65\x2d\x8a\xfa\x5a\x61\xbd\xb3\xb6\x01\x49\x68\x9b\x8b\xb9\xa1\xe8\x47\xe3\x1d\xf6\x05\x3f\x94\x2f\x29\x1f\xd0\xda\xc9\xed\xa2\xcd\xcc\x97\xf8\x00\xed\x10\x78\xbe\x24\xde\xcc\x41\x3a\x53\xbe\x54\x3a\x68\x46\x5b\x55\xe6\xeb\x01\xc2\xe9\x5e\xd8\x9d\xf9\xb2\x0c\xf5\x81\xab\x46\x11\xf4\x20\x5f\x56\x9b\xa2\x86\xc3\x8d\xe6\xcb\x9d\x6d\xc3\x9b\xe5\x94\xaf\x95\xe1\x57\xf2\xb5\x1a\x18\xaf\x68\x29\xdb\x09\xf9\x5a\x6b\xf0\x5b\x29\x5b\x60\x53\x67\x9b\xf6\x07\xde\x00\x18\xd9\xbe\x56\x52\x2e\xf0\xad\xb9\x60\x60\x45\xc2\x8e\x07\xe9\x0d\x82\x27\xd8\xa2\x5c\x34\x3e\xa0\x5f\xcc\xaa\x60\x2f\xe4\x42\x47\x97\x8b\x1d\x07\x68\xdd\x40\x39\x98\x62\xe0\xe4\xac\x84\x35\x29\x1c\x6a\xf1\x79\x81\xae\x1d\xf4\x06\xd3\x85\x36\x0b\x3a\x55\xd6\xa0\xc0\xca\xe2\xfa\xb9\xbc\x14\xc2\xf0\xec\x6d\x21\xdd\x35\x65\x3f\x0e\x45\x82\x61\x3b\xd6\xc2\x4b\x81\xc3\xc9\x0e\x53\x9d\xbd\xc0\x03\x64\xaf\x9b\x35\x54\xab\x24\x07\xf0\x42\xf6\x8a\xb1\x79\xa5\x30\xbc\x76\x38\xd3\xec\x0d\xab\x8a\x74\x5f\x64\xd3\x0e\x8b\x8a\xf4\x24\xa0\xc9\xde\xda\xcb\xbf\x0d\x83\x79\xc9\xde\x66\x38\x7a\x6f\x5f\x83\x39\xc9\xb0\x40\xd9\x99\xd5\x3b\x6b\x74\x30\x0e\x68\x0c\xac\x74\x76\x2c\x86\x47\xbc\x7c\x38\xa5\x39\x39\x88\xc5\x59\xae\x36\xb1\xf4\xbe\xe0\xc3\xb3\xaf\x18\x4c\x06\xa7\x47\x81\xfb\xe3\x53\x53\x86\xc1\x02\xc5\xfe\xcf\x21\xc7\x04\xad\x20\x8d\x19\xd8\x20\x21\x94\x63\xc8\x5d\x40\xff\x9e\x94\x43\x59\x49\xe1\x3b\x73\xa8\x82\x87\xde\x29\xc3\xa4\x61\xa3\x85\x41\x4c\x61\xa3\x83\x02\x2e\xe4\x70\x3c\xc3\x76\xe6\x78\x47\x19\x7e\xef\x29\xc7\xca\x86\x79\xc5\x52\x52\xc3\x50\x63\x55\xee\xee\x58\x8d\x35\x17\xc7\x81\x8e\x9f\xc1\xed\xbe\x36\x4d\x79\x95\xb9\x20\x8d\xd5\xf1\x7b\x8d\x7b\x5e\x61\x8e\x8d\xb6\x22\xa8\x4c\xeb\xdf\x0e\x5b\x81\xbd\xb9\xc6\xc5\xad\xb5\x06\xcc\x77\x5e\x90\x01\x3d\xd3\x2e\x7b\xda\xa5\xc2\x50\xed\x30\x49\x3b\x1d\xf2\xfe\x82\xae\x5d\x68\x91\x77\x88\x63\xe7\xc6\x67\xe6\xdd\xd2\x2e\x4f\xda\xb1\x93\x77\xdd\x64\x2a\x92\xb0\x91\x76\xcd\x70\x5d\xbb\x66\xad\x1b\xea\x2a\xa0\x33\x92\x02\x2d\xda\x15\x8b\xc9\xea\x10\xe5\xc0\x03\x6b\x1d\xda\xf8\x72\xbc\xb5\x0e\x30\x27\x60\xdd\xb5\xb0\xa7\x62\x5f\x56\xac\x70\x2d\xbb\x56\x63\xf5\x66\x1c\x41\x23\x76\xda\xb5\xa1\x26\x31\xdd\xae\x5d\x59\xb1\xfb\x30\xbe\xce\x0b\x14\x28\x60\x57\x82\xb0\x5d\x47\x0e\xdb\xf8\xa0\x6c\x32\xec\x6c\x48\x3e\x20\x1d\x86\x69\xd7\x31\xc3\xd1\x64\x8a\xa1\xa7\x09\xc5\xdb\xf5\xab\xc5\x3b\x52\xd8\x8f\x5d\xbf\x50\xa9\xdd\xe4\x84\x0a\xed\x1c\x93\xc1\x50\xec\x48\xe3\x49\x3b\xab\x99\x0e\x45\x89\xce\xb4\xdb\x71\x60\x3a\x76\xd2\x88\xef\x76\x36\xd8\x90\xdd\x8a\xd6\x2a\x69\x37\x62\x9e\xdd\x9a\x0f\x59\x78\xa0\xc2\xef\x86\x61\xda\x78\xa1\xfc\x6e\xe3\x55\xe9\xdd\xc6\x2b\x4a\xc3\x2a\xd9\xa8\x36\x06\xd2\xd7\x87\xef\x36\x3a\x45\x68\x63\xbe\x4b\x0b\x49\x82\xcf\x97\x2b\x63\x5f\x0f\xe6\xfe\xfd\x3d\x69\x77\x86\x28\xbb\xe7\x45\xe3\xbd\xfb\x99\x76\x2f\x05\xa4\x5f\xd6\xd2\xee\x55\x98\x34\xae\xa2\xb7\x8f\xa2\x55\x63\x23\x12\x0c\xc4\x17\x94\x78\x07\x7e\xde\xb9\xb7\xf6\x90\xd3\x1b\x12\xcc\x2e\x84\x81\xd2\x1e\x72\xa7\x9d\x3b\xea\x8d\x78\xf6\x30\xd6\x35\x74\x18\xd6\x3e\xa0\x1d\x84\x8c\x20\xf1\x58\xa8\xfc\xa4\x7d\xe5\x4f\xda\x57\xdd\xd2\xbe\xa0\x31\xeb\xd5\x53\x60\xd9\x9d\x66\x6f\xe7\x4a\xdf\x12\x47\xda\x9f\x26\xb0\x57\x2a\x50\x69\x15\xc4\x11\x2a\x51\x1e\xd0\x06\x32\xaf\xa4\x32\x8c\x39\x63\x82\x3c\x49\xf3\xe5\x49\xf3\x0b\xd4\x34\x7b\xf3\xfa\x24\x05\x64\xe1\xe6\xd7\x7d\xc1\x33\x26\x3d\x68\x11\xf5\x3c\x93\x12\xc3\xa8\x11\x99\x68\xd9\xfc\x4e\x5a\x76\x3e\x6b\x9e\x81\x11\x14\x3d\xa5\x4d\xa4\x14\xaf\x16\xed\xd7\xbf\x8c\xaf\x40\xf2\x5a\x0c\x4c\xcb\xd0\xa4\x75\x93\xf8\x20\x01\x62\xd3\x0a\x8c\x85\x5c\x85\x1b\xd4\xea\x74\xbc\x5a\x7b\x71\x94\x76\x47\xb0\xa3\xb5\xcf\x27\x69\x23\x44\xd0\x06\xbc\x8f\x6d\xa0\x80\x39\x63\x20\x75\x58\x44\x6d\x8a\xc9\x34\x0d\xcc\xad\x1d\xd4\x00\x6d\x27\x8c\x80\xb6\x13\x7b\x50\xdb\x45\x6d\xd1\xf6\x03\xfe\xad\x60\x87\x69\xf3\x75\x5e\x49\x5b\x58\x66\x02\xd5\x80\x7f\x0f\x54\x84\x6d\xc0\x56\x7c\x5f\x02\xad\xb8\x4f\x34\x69\xb7\x01\x97\xa3\xff\x01\x63\xe8\x7f\xcb\x7a\x02\x06\xd2\x80\xde\x6a\xb0\x2c\x7c\x70\x46\x11\x90\x43\xac\x3e\x93\x8e\x2c\x68\x3e\x86\x3c\xa0\xca\x11\x8d\x49\xc1\x4f\x0d\x00\x27\x9d\x97\xe5\x91\x14\xda\xcc\x62\xb8\x61\xfd\xfa\x07\x8f\x5e\xbe\x9a\xf4\x97\x72\xf8\x95\x0a\xa7\xa0\xbf\x8c\xe9\xf5\xf7\x1f\xca\xd0\xdf\x4c\x91\xff\xe6\x82\x30\x49\x7f\x19\xda\xeb\xaf\xd2\x46\xea\xaf\x46\x36\x66\x5c\x02\xed\xd2\xdf\xcb\x36\xac\xff\xaf\x91\x19\xc5\xf2\xcb\x0c\x87\x52\xeb\x6f\x87\x85\xd2\x5f\xc6\x6e\xfa\xdb\x29\x8e\xdf\x5e\xb0\x6d\xf4\xb7\x3b\x79\xf5\x78\xc7\xc0\x10\x4d\x7f\x27\x64\xf1\x28\x7e\x40\xb4\xe9\x10\x60\xe4\x74\x60\xc1\x0f\x81\xb9\x7f\xd2\x01\xbb\x7a\x88\xb5\x09\x3a\xaf\x74\x00\x51\x1e\x02\x55\x39\x10\x28\x1c\x52\xa1\xc1\x07\x62\xea\x91\x0e\x69\xf8\x65\x64\xb4\x09\x85\x3e\x10\xa7\x1e\xf2\xfa\x81\x43\xc0\x06\xb6\xe7\x10\xea\xeb\x21\xd3\x10\xcc\x1e\x8c\x35\x0f\xf9\x7a\x40\x2c\x87\x0a\x5d\xcd\xa1\x5b\x2c\x98\xb2\x43\x77\x85\x3b\x06\x74\x38\x54\x77\x10\xbc\x55\x29\xc8\xc0\x0a\x1c\x3a\xa6\x7d\x59\x07\x3b\xf1\x20\xd0\x39\xf4\x4e\x87\xc1\x25\x1c\xf6\x06\xa0\x87\x69\xd9\xd3\x61\x27\xf9\x43\x9a\x87\x95\x0a\x32\x59\x0b\x8b\x7b\x20\xc2\xa1\x4f\x38\x8c\x0e\xe9\xb0\x06\x2b\x77\x18\xdb\x60\x42\x06\x98\x7e\xd8\xc8\xac\xce\x32\xbc\x4f\x22\xf6\xc3\x7e\xd3\x51\xe4\x04\x81\x88\x0a\x1c\xd9\x51\x30\xf9\x82\x29\xa6\xa3\x60\x1e\x85\x3b\xf7\x00\xd6\x3a\x8a\xb3\x14\x88\xeb\x28\xce\x2a\xdc\x5a\x47\x59\xb6\x83\x92\xc3\x93\x0e\x97\x9a\x0e\xcf\x90\xb5\x9f\xe9\x00\x8c\x3a\x1c\x33\x72\x9e\x8e\x1c\x08\xcb\x0e\xf7\x99\xde\xed\x85\x28\x73\xf0\x05\x81\xc9\x81\x20\x1f\x96\x03\xd6\xeb\x70\x98\xb5\xc3\x83\x61\xf3\xe1\x63\x90\x17\x51\xdc\xc1\x63\x84\xc3\x7f\xd3\x11\x72\x52\x4a\xc1\xa9\x84\xfe\xb7\x60\x43\x8e\x50\x8c\x28\x0c\xaa\x74\xc0\x0c\xa2\x10\x23\x0a\x67\x31\x50\xd2\xc1\x38\xe9\x08\x07\x5c\x3d\x62\x41\x44\x80\x1d\xc7\x6a\xf8\xb5\x27\x1d\x2b\x1a\xd5\x0d\x20\xfd\x58\x5c\xf4\x53\x18\x44\x31\xd8\x3e\xa5\xc8\xef\x83\x84\xe0\xfe\xc4\x18\x4e\xe9\xe9\x14\x1e\x10\x9c\x12\xdb\xbf\x14\x31\xd4\x29\x51\x2c\x23\xa1\x9d\x3b\x65\xe0\x87\xda\x13\x75\xa8\x71\xa7\x2c\x36\xf8\xd3\x74\xc2\x14\x49\x41\x6a\x6b\x20\x09\x66\x22\xde\x38\xb5\x2d\x28\xc0\xa9\xe3\x1d\xd4\x85\x09\x9d\x06\xb3\x79\xc2\x5f\x9c\x76\xc2\xa2\x9f\xaf\x82\x9c\x16\x72\x1c\x78\x8d\x92\x4e\x38\x8e\xb3\xc8\x0e\x02\xd5\x3c\x8b\x04\xe9\x18\xe9\x2c\xf0\x7f\x67\xb1\xda\x07\x52\xdf\x48\xbd\x82\x62\x8a\xc5\xd9\xda\xef\x74\x22\x9c\x3e\xa1\x18\xa7\xef\x3b\x14\xeb\xc4\x4a\x9f\x58\xe2\x93\xc1\xc3\xe9\xf0\x5a\x92\x4e\x1f\x5d\x0b\x92\x61\x3d\x9d\xf0\xcf\x2d\x9d\x10\xfe\x19\xb2\x81\x60\x14\x8c\x92\xcf\xe0\x14\x02\x16\xee\x64\xac\x7c\x86\x7c\x01\x03\xce\x50\x74\x15\x0a\x49\x86\xed\x20\x7a\x80\x22\xd7\x33\x17\x20\x7c\x75\xd0\x3b\x9d\xb1\xc0\x68\x41\x79\xce\xc5\xd1\x2d\x4e\x6d\x59\x41\xbe\x4d\x89\x74\xae\x96\xce\xa7\xa6\x4b\x60\xbd\x18\x75\x5d\x52\x8e\x74\x49\xad\x8a\xe7\x4a\x75\xbb\x60\xbc\x2e\xe9\xfd\x49\x17\xa2\x49\xe4\x04\x72\x62\x5c\xa0\x5f\xe8\x30\x82\x2f\x9e\x93\x5c\x72\x7f\xd2\x25\x7f\xac\x82\x08\xff\x52\x29\xf3\x42\x12\x13\xf4\xfb\xa4\x0b\x3e\xf3\xf2\x33\x5d\xaf\x7f\xbc\xb4\x14\x07\xad\xca\x97\x9e\x2e\x6d\xe9\xd2\xf0\x74\xd9\x0e\xe5\xb9\xec\xbc\xd2\x05\x10\x70\xc1\xda\x5d\xd6\xd3\x85\xfd\x7e\xd9\x98\x58\x98\xcb\xb7\x0d\x34\x03\x7b\x5c\x58\x88\xcb\x8b\x82\x18\x50\xe9\xf5\xee\xbf\x0b\x01\xcb\xe5\x8d\x75\x1c\x75\x3a\xde\xa3\x81\xc0\xc5\x5c\x74\x85\x97\x8f\x37\x90\xa6\x5a\x5d\x3e\x15\x8f\x0b\xc5\x30\x5b\xd7\xda\xd2\x05\x3d\xbd\x56\x95\x06\x0a\xcf\x7a\xad\x0a\x06\xab\xed\xa1\x3b\xd2\x13\xc3\xc2\x2a\x5c\x2b\x76\x56\x08\xe6\x40\x0a\x6b\x6c\x14\xea\xb3\x61\x29\x81\x04\x2d\x7b\x4b\xb6\xab\x24\x1e\x2b\x23\x48\x34\xb4\xb2\xb3\x21\xc8\xc1\xcc\xad\x00\x2a\x30\xa5\x21\x33\x02\x74\xab\x46\xdf\x67\xb5\x12\x2f\x5b\xad\xb0\x1f\x56\x3b\x3c\x9c\x55\x7a\x17\xab\xef\xc9\xa5\xd5\xbe\xe0\x1c\x0c\x91\x84\xb5\xd7\xbd\x59\x63\x20\x67\xed\x1f\xfc\xb6\xb6\xeb\x2f\xa8\x11\xcd\x58\x23\x8a\xb3\x06\x24\x15\x4f\xb2\x06\xef\x81\xa4\x58\x66\xea\x51\x93\xb5\x0b\xd6\xde\xda\xa5\x50\x49\x6b\x36\x81\x79\xad\xfd\x28\x2b\xfd\x2c\x36\xad\x2f\x47\x20\x59\x6b\xcd\xb3\x92\x53\x5f\xa0\xff\x2d\x63\x9d\x81\x70\xcb\xda\x78\x1b\x22\x2c\x44\x42\xa7\x69\x0d\x11\x0f\xd8\x4e\xce\x0e\xf8\x02\xda\x67\x6d\x7a\xb2\xf6\x7d\x9f\xbf\xc6\x4e\x5e\x4f\x6f\x01\xc1\x8e\x02\x79\xdb\xf0\xc2\x01\x8c\xb1\x34\xd9\xd4\x9a\x00\x75\x9f\xf4\xf3\x1e\x55\xfd\x08\x76\x4c\xfa\xe1\xef\xef\x2f\xfd\xa8\x14\x38\xce\x1f\x95\x06\x5a\xca\x93\x7e\xf4\xd6\x92\x7e\x7c\x4b\x3f\x08\x90\x7f\x00\x2a\x7e\x7c\x05\x94\x0a\xb0\xe8\x67\x01\x0f\xfe\x2c\x2c\xea\x0f\x62\xef\x9f\xc5\x53\xea\x9f\xd5\xcc\x03\xc9\x27\xf1\x10\xff\x23\xed\x94\x70\x4f\x1f\xec\xe9\x8f\x6a\x4f\x1f\x38\xc7\x85\xf4\x49\x1f\xcb\x9f\xf4\xb1\x1d\xbf\xc6\xf7\x86\xe7\x76\xee\x5e\xd3\x07\x70\xfe\x63\x13\xbf\x8c\xbd\xf2\xc1\x94\x3f\x36\x27\x9f\x6f\x4b\x9f\xa6\x9a\x3e\xcd\x0e\x50\x38\xae\x4f\xf3\x3b\x15\xd9\xf0\xd3\x02\xea\x91\x8a\xec\x00\xa3\x45\xf6\x27\x15\xf9\x68\x2a\x08\xf7\x8a\xb4\x73\x41\xb7\x8a\xf4\xe9\x78\x0f\xbe\x4c\x56\x9d\xd6\x52\x41\xdc\x07\xda\x00\xbc\x8b\x7c\x25\x15\x01\xfb\x1b\x65\xf7\x80\x33\x29\xf2\xb0\xfe\xdf\x93\x8a\x0a\xbb\x51\x39\x40\xa2\x81\x7e\x35\x01\x03\xc3\x7e\x17\x3d\x66\x2a\x7a\xa6\x57\xc1\x8b\x9e\x70\x5c\x45\x6d\xbc\xa5\xd5\xd1\x82\x59\xed\x9c\x17\x92\x91\x8a\x7a\x87\x91\x01\x8a\x65\x39\xcf\xe0\x0a\xe2\xb0\x54\x4c\x22\x15\x40\x8b\xf9\x20\x0d\xc0\x94\x62\x99\x3b\xa4\x40\x28\x05\x6e\xe2\xf5\xf1\xc5\x30\x71\xab\x1b\x08\x06\x8e\x28\xa3\x00\x8e\x14\xfb\x0f\x0e\x9e\x38\xb7\x18\x8f\xba\x10\x73\xa6\x62\x34\x6f\xc5\x85\xa4\xa5\xe2\x1b\x4d\x65\x71\x40\x0e\x02\x85\xe2\xa7\xe5\x54\xbc\x69\x79\x90\x9c\xa9\x38\x64\xe9\x18\x26\x72\x16\xda\x2e\xb8\x66\x3a\x95\xe2\x0f\x9a\xae\xfc\x79\x52\x59\x27\x71\x77\x59\x0c\x98\xcb\x6a\x42\x9a\xaf\x54\xd6\x2f\x76\x52\x79\x02\x08\xb7\x4a\xbe\xe0\x08\xab\xec\xa9\x0a\x3a\xac\x72\x36\x9d\xa9\x8a\x21\xc7\x4a\x62\x6c\x56\xe5\xc7\x23\x55\xac\x70\x95\x5a\x05\xd9\xc8\x6d\xe8\x05\xe1\x33\x76\x45\x95\x76\x3a\x28\x31\x77\x15\x7e\x39\xa9\x02\x80\x5c\x25\xb6\x37\xc9\x17\xe8\x49\x9e\xf1\x76\x1d\x1f\x76\x18\x61\x2f\xb7\xf1\x01\xc1\xe0\x28\x93\xca\x23\x43\x6c\xfc\x30\x32\x9c\x7c\x0b\xfb\x45\xf2\xd6\xf8\xb5\xba\x6a\xaa\xf0\xfb\x55\x65\xf7\x1b\x49\x03\xa1\x06\x54\xf8\xbe\xaa\x40\xe7\x98\xa2\xee\xe0\xa3\xbb\x49\xaa\x5a\x10\x09\x55\x2d\xa8\x40\x69\x55\xad\xd8\xd2\x00\x19\x9c\x87\xb6\x95\xaa\x46\x46\x16\xf4\xb8\xd2\x40\x55\x9e\x07\x56\xe0\xa4\x8a\x58\x82\x05\x93\x7c\xe7\xe5\x7b\xaa\xb6\xc3\xfc\x56\xdb\x1b\x95\xa4\x5a\xf9\x80\x50\x2f\xaa\x21\x76\xac\xd8\x91\xd5\xda\x3b\x76\x43\xbc\x5b\xad\x21\x42\xa8\x16\x92\xd9\x9a\x5e\xa5\xda\xc0\x92\x33\x06\xaf\x08\xb9\xb1\x0c\x98\xbe\xfd\x2a\x38\xfc\x72\x13\x54\xdf\x00\xe5\xaa\xef\x5a\x40\xe1\x02\xaa\x57\xfc\x60\x25\xab\x37\x43\x34\x58\xdf\xf8\xba\x7a\x7b\xa5\xeb\x0d\xf2\x74\x8c\x8a\x67\x62\xd5\xc9\x2b\x1a\x82\xdf\xea\xe3\xbf\x65\xd3\x53\x7d\xcf\xc6\xff\x45\x88\xd5\x5f\x4e\xab\xf1\x38\xa8\xf2\xfb\x40\x85\x16\x56\xff\x9a\xa6\xba\xb0\x62\xeb\x38\x50\xb8\x30\xa8\x55\xa6\xf5\xf2\xa4\xba\x06\x27\xb6\x86\x62\xd2\x6b\x5c\x3c\x7b\xaf\x6b\x40\x20\x30\x6b\x75\xf1\x13\x66\x7d\x86\x96\x03\x09\xd5\xbd\x3e\xf3\x4a\x4d\xb0\x79\x1a\x60\x62\x93\xfe\xb1\x96\xda\xfb\xd5\xab\xc9\x98\x4f\x6a\xc2\xc1\xb5\x37\xba\x68\x2a\x91\x9a\xe6\x4f\x6a\x08\x29\x9a\x9e\x32\xd9\x5c\x4f\x9e\x48\xb6\x7f\x41\x75\xd3\x7e\xe9\x9d\x9a\x06\x0b\x07\x4a\xf8\xe3\x37\xb3\xa6\x6b\x42\x2a\x8d\x01\x47\xd3\x7b\xa4\xa6\xbf\x33\x35\x98\xe7\x77\x65\x9b\x43\xb5\x9b\x23\xa2\x6b\x5e\x0d\x86\xb3\xb9\xef\xcc\x0c\xec\x95\xe6\x81\xd1\x3b\x2b\x4c\x79\xab\x4f\x92\x0b\x52\x6e\x88\xf2\xf0\x0a\xd3\x03\x33\xdb\x56\x2e\x1c\xfe\xbb\x7f\x1b\x8f\x1c\xdb\x9a\xc9\xe5\x93\x7c\xd3\x27\xf9\x46\xbf\xe8\x5b\xb1\x53\x93\x6f\x23\x63\xce\xbe\x0d\x4e\xc3\x37\xae\x8b\x6f\x5f\x1e\xdf\x79\xce\x2b\x92\x67\x6c\x09\xcf\xd3\xc1\xd3\x77\x8f\xe4\xc7\x81\x9f\xf2\x09\x43\xf0\x03\x0e\x00\x61\x87\x7f\xe4\x49\xc0\x41\x4e\x8b\xe5\xe5\xa9\xdd\x72\x72\x18\x38\x07\xec\xf5\x86\x1f\x04\xee\x8d\xe7\x70\xde\xca\x93\xbc\xa3\x7d\x47\x20\xee\xdd\xde\xe2\x4e\x08\xe1\x9d\xab\xe3\xef\xb7\x4b\x0f\x40\x46\x8f\x4c\x28\xf8\x9e\x2a\x79\xec\xd6\x60\x68\x3d\x4e\x8c\x34\x78\x80\xed\x61\x27\xe3\x36\x8f\x7e\x21\x7b\x4c\x9e\x14\xbc\x0a\xe9\x6b\x12\x5d\xf8\x9a\xef\x1b\xa0\x80\xaf\x49\xaf\xef\x08\x18\xfd\x8b\x11\x61\xf5\x80\x98\xfd\x06\x74\xf0\xdf\xe7\x44\x2e\x95\x2b\xf9\x1f\xe6\x42\xb8\xd3\x85\xbb\xb6\x63\x3b\xf3\xb0\xae\x4b\x01\xba\xee\x52\x6a\x42\x10\x2e\xa0\x5a\x40\x2d\x83\x72\x14\x5d\x3a\x69\x20\x9e\xee\xc2\xb3\xd2\x2e\xf1\x01\x09\xe7\xf3\x7c\x52\x87\x51\xeb\xb4\x66\x1d\x46\xac\xcb\xb4\xb7\x26\x4f\xac\x3b\x8d\x59\x4b\x9d\x5f\x41\x3a\xfc\x5b\x97\x87\x7b\xb7\x2b\x07\xa1\x02\x1d\xe0\x07\xe5\xae\x32\x84\x25\xc5\xb2\xb4\x04\xb1\x77\x6d\x82\xa8\xbe\x6b\xcb\x56\x52\x57\x87\xe9\xed\xca\x53\xef\xae\x71\x40\x63\xba\x06\x96\xb0\x6b\xc0\xe9\x75\x9d\xa9\x5f\x9c\xfe\xe5\xd3\x53\xbf\x78\x7a\xd2\xaf\x67\x18\x3c\x51\x37\x69\x9e\xba\x65\xce\xd6\x5e\x6f\xdb\x4d\x31\x1a\x3b\xf1\x53\x70\x01\xba\xec\x56\x30\x53\xf8\xbe\x6e\xde\x14\x7d\x5a\x47\xbd\x31\x31\x3b\xe3\xbc\xed\xef\x4f\x52\x7f\x65\x5a\x04\x3b\xad\x97\xf7\xe4\xae\x13\x59\xf1\x58\xb1\x17\xe2\xc8\x5e\x78\x34\xd6\xe1\xd3\x40\x4f\x10\x28\x4f\x77\xad\x20\x33\x75\x07\x9a\xef\x5e\x20\x12\x00\xf6\xee\xf0\xd2\xa9\x7b\xdb\x41\x9e\xd4\x1d\x9d\x7b\x5f\x6f\x95\xa0\x12\xf2\x00\xf7\xdf\xc3\xb0\x8d\xed\x06\xf8\x4c\x81\x10\xfe\xb9\xd8\x0e\xad\x81\x3c\xfd\x86\x7a\xbe\xa7\x61\x3d\x24\x73\xb7\xf6\x10\xec\xf8\x1e\xca\x1b\x16\x3d\xf4\x60\xb1\x62\xfd\x91\xf2\x2a\x48\x0f\x9d\x60\x11\xfa\x7d\x5f\xdf\xa6\xd0\xce\x1e\x56\xa1\xed\x3d\xec\x2d\xf1\x30\x56\x35\xae\x4c\xd8\x97\x02\x09\xfb\x03\x85\x91\xa9\x48\x79\xd2\xd4\xc3\xf7\x45\x4e\x7e\x60\x35\xc3\x79\x4c\xdc\xc3\x69\x16\x7a\x78\x75\x36\x76\x3f\x40\xfb\x3b\x91\x40\x24\x89\x41\xfa\xfc\x57\x6d\xed\xa0\x3c\xb5\xed\x6b\x43\x7c\xdd\xd7\xbe\xc3\x28\xf5\x85\x45\x5d\xa5\xa7\x17\xf2\xf7\x55\x69\x72\x3b\x61\x44\x5f\x1d\x2a\xb6\x10\xd4\xf5\x15\xef\x17\xb4\xbe\xde\x19\xac\xe0\x8e\xef\x34\x5b\x7d\x0d\x54\x9f\xa9\xaf\xbf\x3f\x48\xfa\x09\xa9\xb6\xa7\xff\x96\xf0\x12\xcd\x7f\x4b\xda\x5c\x15\x69\x60\x37\xfe\xb7\x74\x70\x6d\xfe\x5b\x40\xb0\x70\x3f\x20\x7f\xe9\xbf\x85\x29\x85\x6c\xb0\x1c\x21\x39\xc3\x67\x31\xf6\xe5\x77\x97\x90\x5d\x02\xd4\x3c\x05\x80\x0b\x03\xe2\x77\x91\x42\x80\xbc\x03\xd8\x34\x04\xc3\x0f\x69\x80\xc1\xaf\x2d\x0a\xe9\xb6\xa7\xc0\xb2\xf1\x3b\x42\xbc\x67\x09\x21\xb0\x1c\x21\x77\x0a\xf9\xf3\x48\xef\x2d\x14\x7e\x69\x44\x9c\x83\xce\x15\x48\x38\xf4\xfd\x12\x1c\xca\xef\xb1\xa1\x59\x61\x31\x43\x33\xd4\x3f\x34\x7b\xb0\x90\x5f\x46\x42\xb9\x6e\xa1\x07\x9d\x50\x28\x83\x9f\xd0\x03\x7b\x3e\xf4\x34\xb2\x3d\x43\x51\x76\x52\x69\x43\x7f\xde\xaa\x45\x7e\x41\xb9\x37\x42\x0b\xc2\x77\xde\x5d\x08\x25\x46\x0b\xfd\x07\x60\x42\x89\x2c\x42\xe9\x91\x43\xdb\xce\xcc\xa6\x77\xa2\x65\x0a\xa5\x95\x86\xa6\x1a\x0a\x3a\xd0\x51\xe8\xbb\x2b\x43\x79\x7b\x27\xf4\xbd\x70\x14\x3a\xf2\x62\xa2\x8c\x52\x43\x79\x55\x24\x74\xf8\x0a\x56\x1f\xdd\x1b\x07\x34\x56\x41\xc1\x7c\x9b\xcd\x78\xb9\xce\x15\xe8\x6a\xb5\x77\x66\xdf\x57\x7c\x5f\xe3\x60\x78\x36\x15\xd7\x33\xaf\x9a\xc2\x36\xfc\x36\x54\xc3\x26\xa1\x91\xe7\x46\x79\x3f\xea\x87\x1d\xe8\x9f\x2e\x17\x2e\x61\x4f\x3c\x9e\x0f\x73\xbc\xf3\x7e\x0d\xbf\xf1\x87\x11\x3f\x04\x4f\x0b\x83\x5f\x78\x02\x38\x3b\xf8\xb5\x32\x7c\x73\xd2\xc5\x17\x46\x6d\xe1\x95\x07\x39\xdc\x2c\xe1\xfe\x31\x3e\xd7\x14\xd0\xe2\x70\x86\xc7\xc1\x53\xea\xf7\x02\x4e\xc0\xdb\xa4\x20\xe0\x8e\xb5\x51\xe6\x08\x84\x63\x9d\x29\x00\x77\x62\x35\xfc\x6e\x79\x52\x2c\xc0\x87\x21\x3b\x7e\xf0\x2d\x43\x76\x46\xdf\x43\x0e\xbc\x18\x0a\x0b\x8b\x0b\xc2\x94\x21\xe5\xa5\x13\x04\xfd\x0c\xe0\x9d\xf1\x1e\x34\x0f\x44\xa1\x43\xa6\x8d\xe3\x41\xea\xe3\xb2\x34\x04\x2a\x35\x64\x11\x85\x0e\x38\x8e\x21\x4f\x1a\x19\x01\xf5\x80\x77\x18\x19\xca\x3d\xf2\x0b\x97\x47\xd6\x86\xb7\x4b\x2b\x13\x58\xc8\x91\x8d\xe7\xac\x23\xdb\x18\x1e\x23\x8d\xec\xc1\x0f\xe7\x23\xfb\x9a\x69\xe4\x90\x0e\x8a\x58\x73\xe4\xb0\xce\xbc\xb5\xa5\xa1\x82\x1f\x80\xfd\x78\xb7\xc5\xc0\xca\x0f\xcd\xb0\xc1\x43\x33\x74\x19\xb1\x38\x99\x69\x7e\x6d\xc4\x00\x26\x1b\xaa\x9f\x34\xf4\xa4\x8f\x1b\xfc\xa2\x81\xa4\xa4\x01\x0d\x96\x48\x43\x19\xf3\x0e\x86\x5d\xb0\xa7\xef\x18\x35\x4c\x07\x12\x7e\x2a\x1b\x3a\xc6\xcb\x9b\x01\xd6\xd0\xb9\x7a\x1a\xb0\xb7\x69\x5c\x8c\x05\xc6\x25\xc7\x04\xe5\x21\xce\xb8\x28\x8c\x0b\x03\xb8\xd8\xdb\xa5\x61\xc7\x91\xc6\xc5\xd3\xe3\x71\x19\x6b\x03\xd3\x8c\xcb\x3a\x08\xb4\x68\x5c\x08\xcb\xc6\xe5\xc8\x76\x47\x15\x47\x21\xb6\xcb\xb8\x7c\xf1\xb3\xcc\xb8\xb0\xe7\xc6\x15\x56\x51\x06\x8d\x18\xd7\x3a\xa0\xba\xe3\x7a\x12\x9c\x0d\xb4\x76\xc0\xb4\x11\xa3\x0c\x53\x2c\x1a\xd5\x9a\xdf\x0a\x87\x15\x8a\x03\xf1\xc2\x30\xd8\xad\x61\x85\xfd\x5b\x35\xd8\x83\x61\xaf\x2a\xf0\xeb\xf6\x78\xb9\x05\x26\x6b\x44\x33\x03\xfa\x0f\xb5\xb1\xdf\x34\xe0\x3b\xc6\x87\xaf\x3c\x1b\x48\xe3\x63\xf8\x61\xd6\x30\xe6\xe3\x63\x18\xfd\x07\xb6\x7e\x20\xb8\x1f\x45\x6a\x1a\x45\xb5\x83\xd2\x72\x0c\x7a\xd4\xc1\x93\xcd\xf1\x46\xbc\xa3\x18\x6a\x39\x60\xda\x80\xdb\x1f\x14\x2c\xcf\xb1\x47\x85\x15\x1c\x55\xc0\xb8\x22\x22\x19\xd5\x3f\xa4\x3e\xaf\x34\x1a\x8c\xf5\x68\x88\x61\x46\x83\x4e\x35\xca\x1e\xb0\x77\x38\xde\x3d\x67\xf4\xea\xfc\x92\x3d\x28\x73\xdf\x25\x0d\xc7\xaa\xd0\xd3\x0f\x2f\xbb\xb1\x4e\xb1\x1d\xf4\xbd\x30\x32\x78\x5e\x33\xbc\x2a\x00\xcd\x40\xc8\x3c\x9c\xf9\x08\xd5\x06\xd7\xc9\x17\x78\x62\x13\x0f\x87\x9a\xbc\x56\x6c\xf8\xc2\xd0\x3a\x0c\xe0\xa0\xff\x1e\x00\x67\xe8\xbf\xcb\xdd\xd2\xe8\x2a\x1f\xd0\x77\x4c\x9d\xca\xdb\xa9\x3b\xfc\x24\x3c\xfa\xa5\x6c\x44\x49\x75\x5e\x44\x18\xdd\x3e\x7c\x41\x73\x43\xc8\x38\x7a\x21\x05\xbc\xa6\xd5\x84\x6a\x77\x8e\x90\x36\x77\x74\x48\xb2\x07\xf6\x6e\xe7\xe5\xa6\xd1\x69\xe3\x46\x7f\xd2\x80\x7f\x54\x24\xbc\xef\x84\xb0\x8c\x37\xd5\xc6\x1b\x4f\x8c\x29\xbb\xad\x8a\x14\xd2\x9c\xb4\x04\x53\x0c\x3b\x79\xc2\xef\x8d\x49\xd3\x31\xb9\x2c\xb4\x68\x63\xa2\xa3\xc9\x99\x4d\x25\x2b\x05\x03\x2c\xfd\xd4\x50\x4f\xc0\x65\x28\xa4\xba\x4c\x8e\x64\x72\x3d\xa6\x57\x81\x32\x4d\x0a\x7a\xd2\x80\xf0\x18\x75\x4c\xaa\xff\x84\x1f\x3d\xf1\x1a\x8a\xdd\x3f\x83\xb2\x98\xc1\x35\x99\xb1\x78\xba\x3e\xe6\xe2\x0d\xd8\x31\x17\xc7\xfc\x9e\x83\x8e\xf9\x80\xae\x37\xc0\x19\x6b\x03\x5c\x1d\x6b\x83\x31\x1d\xeb\xbd\x3c\x3b\x10\x5f\x8e\xc5\x93\xdd\xb1\x18\xc0\x8c\x75\x0a\xe9\x89\x10\x8e\x07\x48\x63\xf1\x18\x7a\x2c\x54\x6a\x0d\xcd\xdb\xc0\x70\x56\x67\x76\x47\x40\x3a\x56\x0f\xda\x41\x20\xdb\xb1\x82\xdf\xc7\xc6\x42\xa0\x3f\x56\x00\x8c\xf1\xe1\x35\xfc\x63\xc5\x57\xd1\xe6\xbd\x45\x39\xd6\x60\x9c\x35\xee\x7f\x96\xe5\xa6\xa4\x6f\x21\x89\x9a\xc6\x0d\xac\x3e\x6e\x0a\xe1\xa6\x59\xb9\xb1\x73\x6e\xca\xf2\x26\x24\x1e\x37\xf0\xc1\x78\xea\x06\x29\x3e\xb5\x4f\xaf\x69\x3c\x01\xed\x7c\xb8\x24\xef\x0a\x4f\xe1\x0d\xa2\x29\x67\xe2\xbd\x81\x29\xb4\x13\x53\xca\x27\x4d\x69\x20\x1d\xc5\xfc\x14\x34\x65\x20\x63\x4c\xe4\xcc\xe9\x9e\xa6\xfc\x5a\x9a\xbc\xbd\x38\x55\x6a\x9a\xd0\x5e\x04\x7b\x53\x1b\x02\x89\xa9\xad\xd9\x40\x82\xe7\x40\x85\x81\xa7\xdf\x99\xe6\x45\xf6\x97\xe0\x11\xb2\x9a\x17\xda\x5d\x8a\x15\x9f\xd4\xfc\x79\x29\x1e\x31\xad\x79\x81\xcd\xe5\xbc\xd1\x35\xaf\x50\x94\xf2\x6b\xfb\xbc\x10\xab\xcf\x6b\xd5\x0d\x94\xc6\x65\xbe\x77\x5c\x26\x8c\xcb\xb4\x93\x39\x05\xef\x44\x32\xd3\xd0\x9b\xb5\x27\x4d\xeb\x09\xc8\x62\x4f\xf3\x3d\x7c\x9d\x06\x63\x3f\xe9\xd4\xa7\x6f\x80\x83\x69\xfa\x2e\x0f\xe8\x5e\xd0\xd8\x51\x7e\x2a\xc1\xdc\x74\x2b\xe8\x87\xd7\xfe\xa0\xbe\x13\xd5\xeb\x7b\x09\x91\x6a\x3c\xbd\x9d\x8b\x09\x4d\x1c\x95\x7a\xd2\x64\x4d\xef\xf8\x59\x06\xed\xec\x15\xde\x6e\x7a\x34\xd9\xc1\x26\x26\x83\xff\xe9\x63\xa4\xe9\x53\xd0\x70\x85\x71\x64\x84\x38\x93\xa1\xc3\x44\x00\x3a\xfd\x49\x93\x80\x75\x32\x5a\x9c\x21\x08\xbd\x91\x9e\x6f\x62\x0d\xb4\x0d\x68\xf5\x84\xd7\x9d\xbc\x39\x34\x81\x47\x4b\xe2\xbd\xd0\x17\x5c\x4d\xca\x16\xf8\x2e\x4d\x1e\x8d\x4d\x5e\x3d\x99\xbc\x0a\x39\xc3\x4e\x8a\x33\xac\x82\x80\x8d\xf7\x0b\x6d\xdf\x9b\x14\x33\x16\xab\x2d\x3e\x16\x14\xac\x8a\x78\x70\x06\xb0\xd1\x0c\x98\xc4\x89\x15\x5e\x60\xba\xde\x80\xe9\xdf\x26\x9d\xab\x09\x08\x42\xe1\xb9\xe2\x83\xd5\x07\xd0\x9b\x2b\xb8\x2c\xb7\xc2\x14\xcf\x5b\xdb\x7c\xd2\xbc\x61\x16\xe7\x8d\x89\xdd\x94\xca\xed\x69\x3e\xd0\xd6\xa7\x33\xcc\x5c\x67\x79\xd2\xaa\x5b\x68\x29\x92\xd6\x7b\xd5\x60\xb5\xf7\x36\xf0\x6a\x99\x6f\xef\xc5\x94\x57\x6d\x56\xdb\x3d\xad\xc6\x2b\xea\xab\xf1\x13\xe9\x6a\xef\x27\xa6\xd5\x8c\x98\x7a\x35\x5e\xcd\x5e\xcd\x26\xc8\x57\x11\x8c\xac\xf6\x69\x58\x85\xd5\x78\xc6\xba\xda\xb4\x92\x56\x5b\xbc\xa7\xb8\xda\x57\xf1\xda\x79\x9a\xb9\xfa\xc9\x05\x5a\x9d\x9f\x83\x56\xf7\x96\x16\x43\xe9\xd5\x61\x45\x56\x6c\xd2\x12\x0d\xc5\x0b\xbc\x80\xe0\x79\xe5\x7c\x0d\x3d\x56\x41\xc2\x0b\x12\xff\x98\xcf\xf7\x3f\x03\x5f\xc9\xd8\x6e\x5f\xc9\x6b\xd5\xf4\x15\xe8\xdc\x57\xe0\xc7\xbe\xef\x3d\xf8\xaf\x40\x74\x5f\x69\xf8\xd9\xb8\xd2\x57\xba\x47\xfa\xca\x7b\x15\xeb\x0b\x85\xff\xf2\x83\xfa\x57\x2f\x83\x68\xbe\x10\x36\x5e\xdb\x8e\x8a\xbc\x14\x89\xdc\x06\xd6\x1a\x1b\x88\x1d\x0f\x12\x02\xa5\x2f\x82\xdb\xaf\x8e\xa1\x25\x7d\x75\x6a\xa0\x2f\xa3\xcc\xbf\xb6\xf1\x0b\xe2\xd7\xf2\xdb\x9b\x65\xda\x75\x04\x88\x9e\x88\xda\xbf\x56\x0a\xa6\xfb\xb5\x36\xdf\xd4\x8b\x81\x41\x10\x77\x7f\x2d\xd8\x6e\x08\x88\x81\xd5\x78\xf3\x27\xe9\x17\x33\xe5\x29\xf7\x97\x17\x25\x79\xf9\xfb\xeb\x25\x4b\x73\xa4\xab\x22\x6f\x82\x3c\x60\x7f\xff\x23\xde\xd2\x2d\x36\xd3\x0d\x7b\x07\x7b\x0b\xd2\x16\x32\x1a\x48\x1c\xd0\x15\x5a\xdd\x5b\x02\xc1\x74\xba\xb1\x6d\x6e\x19\x1d\x64\xa2\x10\xf8\xe8\x06\x3e\x86\x33\xb9\xdf\xef\x8a\xb7\x0a\x96\x96\x96\xfa\x46\x6c\x55\x90\xd0\x68\xdc\xba\xa5\x5b\xdf\x70\xf8\x56\xfd\x60\xa7\xdd\x6a\x01\x5a\xf8\xcd\xeb\x86\x91\xbc\x75\xa6\x9b\x5f\xaf\x6e\xd8\xc8\xfb\xd2\x97\x82\x13\x2c\xe5\x4d\x13\x79\x03\x4a\xde\x97\x31\x02\xbf\x61\xef\x6e\xdb\xd1\xbf\x1d\x78\x2c\x3b\x48\x49\xd8\x25\xb7\x35\xc0\xd6\x1b\x08\x94\xae\xe2\xb6\xf6\x01\x69\x6c\xca\x4b\x31\x37\xc2\xac\xdb\x06\xc2\xd8\x1b\xd6\xe7\x86\xae\xdc\xff\xee\x28\xdc\x5e\x8e\x74\x23\xae\x49\xb7\x73\xc7\xdc\xee\x3b\x48\x49\xf4\x37\x3c\xdc\xbc\x3d\x0a\x1f\xe3\x01\xc5\x60\x60\x6f\xee\xd0\xfc\x01\xe5\x25\xde\x9b\x86\xec\xe6\xcd\x8d\x9b\x0e\xfc\x81\x49\x7b\x20\xaf\x47\xe9\xf7\x1e\x5f\xf8\xa1\x88\x40\xea\x4f\xb7\x90\xf4\xa7\xe1\x89\x47\x6b\x7f\xee\xe9\xff\x00\x00\x00\xff\xff\x96\xd2\xdb\xc1\x3c\x33\x00\x00") +var _keysWordsWordlistEnglishTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\x5b\xdd\xbe\xbc\x2a\x08\xbd\xf7\x2d\xc9\xa8\xd8\xa3\xe2\x41\x9d\x76\xfb\xe9\xcf\x6f\xad\xfe\x17\x83\xe5\x07\x2a\x22\x2c\xcc\x91\x4d\xda\xee\x2d\xc9\x66\xc5\xe6\x93\x64\x2b\x9a\x64\xf3\x35\x41\xbf\x78\x1e\xda\xf0\x32\x3c\x36\x24\x33\x24\xf3\x7d\xc5\x9e\x64\x5b\x43\x93\xe4\xac\x63\x20\xb1\x9d\x95\x73\xf6\xf5\xa6\x6f\xf1\x65\x0a\x56\xd9\xf6\x24\xd9\xd7\x98\x96\x93\xe4\xff\x96\x05\x72\xc3\xd9\x18\xf5\xa7\x61\x2c\x79\x7a\x80\xc6\xcb\x75\x2e\x29\x49\x76\xe9\x33\xc9\xbe\xe3\x67\x99\x8f\x6f\xf9\xfe\xb3\x06\x5e\xab\x81\xae\x02\xfa\x95\x96\x15\xa9\x21\xd1\xf0\x0d\x3d\x1e\x87\x58\x20\x71\x0c\xfd\x08\xc1\x78\x4e\xb1\x96\xe4\x54\xfc\x30\xe6\x33\x54\x93\x5c\x2a\x7b\x12\xab\x89\x2d\x2c\xba\xc7\x4c\x62\x03\xd2\x29\x12\x35\x49\xd9\x16\x68\xf6\xcb\x4b\x92\xa2\x28\x2f\xa6\x2d\x49\xc1\x7b\xd1\x07\xd4\xef\x24\xa5\x3a\x06\x58\xbc\xa1\x71\xbf\x24\x49\x09\x95\x1d\x15\x86\x27\x29\x53\x23\x49\xb9\xe5\x19\x49\xaa\x4c\x5d\x81\xf4\xcf\xda\x99\xa4\xfa\x4b\x29\xcf\xba\x86\xee\x49\x9a\x94\x07\x1c\x5b\xbe\x20\xa8\x96\x8d\x23\x6f\x27\xf8\xb4\x13\x63\x6c\x67\x3c\x49\x9a\x55\x88\xae\x7d\x98\xd5\x7c\x51\x2a\xad\x51\xa0\xcd\xe7\xc5\x06\xe3\x66\x32\xb5\x35\x41\x6a\xff\x2d\xd4\xfa\x35\x85\x42\xb4\x27\x49\x17\xcc\xae\x7b\xf1\x13\x6f\x5d\x25\x90\x80\x6b\xef\x41\x35\xe9\x61\x25\x49\xe4\x0b\x84\xeb\x1b\x2a\x20\xe0\x19\x27\x38\x42\x6a\x51\x31\x81\xa8\x18\x77\xd4\x27\x49\xf8\x6a\xc8\x09\x0c\x1f\xa9\x62\x66\x11\xf6\xe5\x1b\xe4\x87\xbe\x63\xea\x41\x15\x89\x69\xac\x30\x6f\x8f\x4f\x92\x81\x5f\x57\x94\x8c\x21\x5c\xfc\x31\x94\x94\xf5\xc6\x58\x55\x93\x8c\x79\x55\x49\x32\xaf\xa2\x53\x93\x4c\xaf\x49\xe6\x94\xfc\x41\xa2\x18\xc0\x9c\x36\xd7\x8e\xb2\x7f\x0a\xbe\xfe\x29\xe3\xda\xa1\x57\xeb\xa4\x92\x71\x15\xd6\xa4\xd8\xd7\x74\x90\x55\x5b\x92\xaf\x06\x55\xe8\xeb\x59\x76\x47\x0a\xd5\xba\xe5\xa3\xa0\x41\xfa\x24\xb9\x75\x38\x86\x73\x1f\xab\x24\xb9\x3f\xb7\x40\x11\x7f\x6d\xa4\x4d\xb6\x27\x6d\x92\x2f\x2d\x1e\x78\xf0\x96\x36\xd9\x4f\x4d\x9b\x9c\x69\x93\x42\x85\xde\xa0\x6f\x0d\x15\x4b\x49\x9b\xd4\xcd\x3d\x6d\xd2\xa4\x09\x92\xa6\x68\xc9\x9f\x16\x54\x0a\xea\xf6\x06\xa1\xa2\xfa\x00\x83\x61\x19\xf4\xa3\x33\x6d\x32\x67\xd1\xb4\xa9\xe4\x0b\xb4\x81\xac\xf9\xa4\x4d\xb3\x60\xe3\x6e\x9a\x31\xdc\x4d\xf5\x48\x9b\x1e\x1e\x78\x3e\xc1\x52\x2f\xf9\xe2\xe5\xb2\xb6\xa7\x4d\x0b\xf7\xf7\xa6\x50\xf7\x4d\xcb\x4c\x9b\x36\xf2\x6c\x7a\x18\xde\x06\xc8\x0c\x01\xef\x09\x75\xdf\x74\xde\xaa\xe0\xf4\x38\x58\x58\x7e\x32\xc6\x62\x78\xfe\xe0\x81\xb9\xaf\xc6\x6d\x16\x78\x89\x79\xa5\xcd\xde\xe6\x05\x6b\xb7\x15\xd9\x15\xb4\x92\x36\x4e\xaa\x08\x3a\x2b\x2a\x28\x87\x81\xd8\x0a\x79\x15\x77\xd2\x31\xbc\x22\xe5\x04\xcb\x22\x01\xc3\x35\xae\xb4\x39\x16\x64\x73\x99\x69\xf3\xfd\x49\x9b\x5b\x49\x9b\xd7\x2d\x6d\xd8\xbc\x9b\xb7\x35\xd2\xe6\xfe\x01\x41\x37\x1e\x3b\x46\xe3\x81\xbd\xba\x39\xf5\x75\x83\x39\xdb\x7c\x42\xc9\xb6\x77\xcb\x6d\xfe\x9b\x36\x7f\xd2\x16\x92\x39\xc8\xe0\xc2\x84\x60\x60\x21\xa8\x1f\x14\x28\xcc\x02\xa8\xfe\xe1\xc5\x30\xc7\x30\x6a\x41\x18\x16\x21\xec\xbc\xd0\x9c\xdd\x85\x0d\x94\x7b\xce\x5e\x0c\x0f\x1f\x08\x34\xbc\xb1\xb1\xa3\xfb\x78\xf7\xf8\x16\x7e\xa3\x88\x73\x5c\x1b\x6c\xfc\xb6\x76\x4c\x70\xed\x27\xc6\xb3\x8e\x43\x8a\xa7\x6d\x59\xd9\xd3\xb6\xca\x06\xf2\x01\x29\x2c\x6e\x3b\x9b\xb4\x0f\x98\xad\xd8\xd1\xd1\x8a\xf3\x7d\x83\x20\x20\x97\x35\xac\x51\xe0\x6b\x80\xf3\xbb\x50\xeb\x21\xfd\xfb\x4b\x59\xb6\x0d\x9b\x24\xcb\x66\x0d\xb4\xe0\x39\xcf\x35\x52\x7e\xf3\x3f\x20\xa5\x80\xd4\x94\xa5\x6a\x08\x92\x9e\xb2\xa0\x41\x13\x14\xb5\xac\x4c\xf6\x07\xb4\x39\x4b\x1c\x2d\xdb\x57\xc0\xaa\x3d\xcc\xeb\xff\x3a\xe8\x36\xd9\xae\x4f\x61\xb7\x81\xdf\xc6\x2a\xb1\x83\x9c\x0e\xda\x75\x22\x09\x70\x0d\x3c\x0e\x34\x1e\x17\x88\x35\x54\x19\x93\xfc\xc6\x22\x3b\x54\x99\x52\xfc\x44\x9a\x51\x6d\xea\xe9\x6c\x3e\xdf\x8a\x0b\x4b\xf5\x6e\xa4\x2c\x8b\xc6\x24\x63\x91\xb3\x5a\xc1\xfa\x65\x2d\x8a\xfa\x5a\x61\xbd\xb3\xb6\x01\x49\x68\x9b\x8b\xb9\xa1\xe8\x47\xe3\x1d\xf6\x05\x3f\x94\x2f\x29\x1f\xd0\xda\xc9\xed\xa2\xcd\xcc\x97\xf8\x00\xed\x10\x78\xbe\x24\xde\xcc\x41\x3a\x53\xbe\x54\x3a\x68\x46\x5b\x55\xe6\xeb\x01\xc2\xe9\x5e\xd8\x9d\xf9\xb2\x0c\xf5\x81\xab\x46\x11\xf4\x20\x5f\x56\x9b\xa2\x86\xc3\x8d\xe6\xcb\x9d\x6d\xc3\x9b\xe5\x94\xaf\x95\xe1\x57\xf2\xb5\x1a\x18\xaf\x68\x29\xdb\x09\xf9\x5a\x6b\xf0\x5b\x29\x5b\x60\x53\x67\x9b\xf6\x07\xde\x00\x18\xd9\xbe\x56\x52\x2e\xf0\xad\xb9\x60\x60\x45\xc2\x8e\x07\xe9\x0d\x82\x27\xd8\xa2\x5c\x34\x3e\xa0\x5f\xcc\xaa\x60\x2f\xe4\x42\x47\x97\x8b\x1d\x07\x68\xdd\x40\x39\x98\x62\xe0\xe4\xac\x84\x35\x29\x1c\x6a\xf1\x79\x81\xae\x1d\xf4\x06\xd3\x85\x36\x0b\x3a\x55\xd6\xa0\xc0\xca\xe2\xfa\xb9\xbc\x14\xc2\xf0\xec\x6d\x21\xdd\x35\x65\x3f\x0e\x45\x82\x61\x3b\xd6\xc2\x4b\x81\xc3\xc9\x0e\x53\x9d\xbd\xc0\x03\x64\xaf\x9b\x35\x54\xab\x24\x07\xf0\x42\xf6\x8a\xb1\x79\xa5\x30\xbc\x76\x38\xd3\xec\x0d\xab\x8a\x74\x5f\x64\xd3\x0e\x8b\x8a\xf4\x24\xa0\xc9\xde\xda\xcb\xbf\x0d\x83\x79\xc9\xde\x66\x38\x7a\x6f\x5f\x83\x39\xc9\xb0\x40\xd9\x99\xd5\x3b\x6b\x74\x30\x0e\x68\x0c\xac\x74\x76\x2c\x86\x47\xbc\x7c\x38\xa5\x39\x39\x88\xc5\x59\xae\x36\xb1\xf4\xbe\xe0\xc3\xb3\xaf\x18\x4c\x06\xa7\x47\x81\xfb\xe3\x53\x53\x86\xc1\x02\xc5\xfe\xcf\x21\xc7\x04\xad\x20\x8d\x19\xd8\x20\x21\x94\x63\xc8\x5d\x40\xff\x9e\x94\x43\x59\x49\xe1\x3b\x73\xa8\x82\x87\xde\x29\xc3\xa4\x61\xa3\x85\x41\x4c\x61\xa3\x83\x02\x2e\xe4\x70\x3c\xc3\x76\xe6\x78\x47\x19\x7e\xef\x29\xc7\xca\x86\x79\xc5\x52\x52\xc3\x50\x63\x55\xee\xee\x58\x8d\x35\x17\xc7\x81\x8e\x9f\xc1\xed\xbe\x36\x4d\x79\x95\xb9\x20\x8d\xd5\xf1\x7b\x8d\x7b\x5e\x61\x8e\x8d\xb6\x22\xa8\x4c\xeb\xdf\x0e\x5b\x81\xbd\xb9\xc6\xc5\xad\xb5\x06\xcc\x77\x5e\x90\x01\x3d\xd3\x2e\x7b\xda\xa5\xc2\x50\xed\x30\x49\x3b\x1d\xf2\xfe\x82\xae\x5d\x68\x91\x77\x88\x63\xe7\xc6\x67\xe6\xdd\xd2\x2e\x4f\xda\xb1\x93\x77\xdd\x64\x2a\x92\xb0\x91\x76\xcd\x70\x5d\xbb\x66\xad\x1b\xea\x2a\xa0\x33\x92\x02\x2d\xda\x15\x8b\xc9\xea\x10\xe5\xc0\x03\x6b\x1d\xda\xf8\x72\xbc\xb5\x0e\x30\x27\x60\xdd\xb5\xb0\xa7\x62\x5f\x56\xac\x70\x2d\xbb\x56\x63\xf5\x66\x1c\x41\x23\x76\xda\xb5\xa1\x26\x31\xdd\xae\x5d\x59\xb1\xfb\x30\xbe\xce\x0b\x14\x28\x60\x57\x82\xb0\x5d\x47\x0e\xdb\xf8\xa0\x6c\x32\xec\x6c\x48\x3e\x20\x1d\x86\x69\xd7\x31\xc3\xd1\x64\x8a\xa1\xa7\x09\xc5\xdb\xf5\xab\xc5\x3b\x52\xd8\x8f\x5d\xbf\x50\xa9\xdd\xe4\x84\x0a\xed\x1c\x93\xc1\x50\xec\x48\xe3\x49\x3b\xab\x99\x0e\x45\x89\xce\xb4\xdb\x71\x60\x3a\x76\xd2\x88\xef\x76\x36\xd8\x90\xdd\x8a\xd6\x2a\x69\x37\x62\x9e\xdd\x9a\x0f\x59\x78\xa0\xc2\xef\x86\x61\xda\x78\xa1\xfc\x6e\xe3\x55\xe9\xdd\xc6\x2b\x4a\xc3\x2a\xd9\xa8\x36\x06\xd2\xd7\x87\xef\x36\x3a\x45\x68\x63\xbe\x4b\x0b\x49\x82\xcf\x97\x2b\x63\x5f\x0f\xe6\xfe\xfd\x3d\x69\x77\x86\x28\xbb\xe7\x45\xe3\xbd\xfb\x99\x76\x2f\x05\xa4\x5f\xd6\xd2\xee\x55\x98\x34\xae\xa2\xb7\x8f\xa2\x55\x63\x23\x12\x0c\xc4\x17\x94\x78\x07\x7e\xde\xb9\xb7\xf6\x90\xd3\x1b\x12\xcc\x2e\x84\x81\xd2\x1e\x72\xa7\x9d\x3b\xea\x8d\x78\xf6\x30\xd6\x35\x74\x18\xd6\x3e\xa0\x1d\x84\x8c\x20\xf1\x58\xa8\xfc\xa4\x7d\xe5\x4f\xda\x57\xdd\xd2\xbe\xa0\x31\xeb\xd5\x53\x60\xd9\x9d\x66\x6f\xe7\x4a\xdf\x12\x47\xda\x9f\x26\xb0\x57\x2a\x50\x69\x15\xc4\x11\x2a\x51\x1e\xd0\x06\x32\xaf\xa4\x32\x8c\x39\x63\x82\x3c\x49\xf3\xe5\x49\xf3\x0b\xd4\x34\x7b\xf3\xfa\x24\x05\x64\xe1\xe6\xd7\x7d\xc1\x33\x26\x3d\x68\x11\xf5\x3c\x93\x12\xc3\xa8\x11\x99\x68\xd9\xfc\x4e\x5a\x76\x3e\x6b\x9e\x81\x11\x14\x3d\xa5\x4d\xa4\x14\xaf\x16\xed\xd7\xbf\x8c\xaf\x40\xf2\x5a\x0c\x4c\xcb\xd0\xa4\x75\x93\xf8\x20\x01\x62\xd3\x0a\x8c\x85\x5c\x85\x1b\xd4\xea\x74\xbc\x5a\x7b\x71\x94\x76\x47\xb0\xa3\xb5\xcf\x27\x69\x23\x44\xd0\x06\xbc\x8f\x6d\xa0\x80\x39\x63\x20\x75\x58\x44\x6d\x8a\xc9\x34\x0d\xcc\xad\x1d\xd4\x00\x6d\x27\x8c\x80\xb6\x13\x7b\x50\xdb\x45\x6d\xd1\xf6\x03\xfe\xad\x60\x87\x69\xf3\x75\x5e\x49\x5b\x58\x66\x02\xd5\x80\x7f\x0f\x54\x84\x6d\xc0\x56\x7c\x5f\x02\xad\xb8\x4f\x34\x69\xb7\x01\x97\xa3\xff\x01\x63\xe8\x7f\xcb\x7a\x02\x06\xd2\x80\xde\x6a\xb0\x2c\x7c\x70\x46\x11\x90\x43\xac\x3e\x93\x8e\x2c\x68\x3e\x86\x3c\xa0\xca\x11\x8d\x49\xc1\x4f\x0d\x00\x27\x9d\x97\xe5\x91\x14\xda\xcc\x62\xb8\x61\xfd\xfa\x07\x8f\x5e\xbe\x9a\xf4\x97\x72\xf8\x95\x0a\xa7\xa0\xbf\x8c\xe9\xf5\xf7\x1f\xca\xd0\xdf\x4c\x91\xff\xe6\x82\x30\x49\x7f\x19\xda\xeb\xaf\xd2\x46\xea\xaf\x46\x36\x66\x5c\x02\xed\xd2\xdf\xcb\x36\xac\xff\xaf\x91\x19\xc5\xf2\xcb\x0c\x87\x52\xeb\x6f\x87\x85\xd2\x5f\xc6\x6e\xfa\xdb\x29\x8e\xdf\x5e\xb0\x6d\xf4\xb7\x3b\x79\xf5\x78\xc7\xc0\x10\x4d\x7f\x27\x64\xf1\x28\x7e\x40\xb4\xe9\x10\x60\xe4\x74\x60\xc1\x0f\x81\xb9\x7f\xd2\x01\xbb\x7a\x88\xb5\x09\x3a\xaf\x74\x00\x51\x1e\x02\x55\x39\x10\x28\x1c\x52\xa1\xc1\x07\x62\xea\x91\x0e\x69\xf8\x65\x64\xb4\x09\x85\x3e\x10\xa7\x1e\xf2\xfa\x81\x43\xc0\x06\xb6\xe7\x10\xea\xeb\x21\xd3\x10\xcc\x1e\x8c\x35\x0f\xf9\x7a\x40\x2c\x87\x0a\x5d\xcd\xa1\x5b\x2c\x98\xb2\x43\x77\x85\x3b\x06\x74\x38\x54\x77\x10\xbc\x55\x29\xc8\xc0\x0a\x1c\x3a\xa6\x7d\x59\x07\x3b\xf1\x20\xd0\x39\xf4\x4e\x87\xc1\x25\x1c\xf6\x06\xa0\x87\x69\xd9\xd3\x61\x27\xf9\x43\x9a\x87\x95\x0a\x32\x59\x0b\x8b\x7b\x20\xc2\xa1\x4f\x38\x8c\x0e\xe9\xb0\x06\x2b\x77\x18\xdb\x60\x42\x06\x98\x7e\xd8\xc8\xac\xce\x32\xbc\x4f\x22\xf6\xc3\x7e\xd3\x51\xe4\x04\x81\x88\x0a\x1c\xd9\x51\x30\xf9\x82\x29\xa6\xa3\x60\x1e\x85\x3b\xf7\x00\xd6\x3a\x8a\xb3\x14\x88\xeb\x28\xce\x2a\xdc\x5a\x47\x59\xb6\x83\x92\xc3\x93\x0e\x97\x9a\x0e\xcf\x90\xb5\x9f\xe9\x00\x8c\x3a\x1c\x33\x72\x9e\x8e\x1c\x08\xcb\x0e\xf7\x99\xde\xed\x85\x28\x73\xf0\x05\x81\xc9\x81\x20\x1f\x96\x03\xd6\xeb\x70\x98\xb5\xc3\x83\x61\xf3\xe1\x63\x90\x17\x51\xdc\xc1\x63\x84\xc3\x7f\xd3\x11\x72\x52\x4a\xc1\xa9\x84\xfe\xb7\x60\x43\x8e\x50\x8c\x28\x0c\xaa\x74\xc0\x0c\xa2\x10\x23\x0a\x67\x31\x50\xd2\xc1\x38\xe9\x08\x07\x5c\x3d\x62\x41\x44\x80\x1d\xc7\x6a\xf8\xb5\x27\x1d\x2b\x1a\xd5\x0d\x20\xfd\x58\x5c\xf4\x53\x18\x44\x31\xd8\x3e\xa5\xc8\xef\x83\x84\xe0\xfe\xc4\x18\x4e\xe9\xe9\x14\x1e\x10\x9c\x12\xdb\xbf\x14\x31\xd4\x29\x51\x2c\x23\xa1\x9d\x3b\x65\xe0\x87\xda\x13\x75\xa8\x71\xa7\x2c\x36\xf8\xd3\x74\xc2\x14\x49\x41\x6a\x6b\x20\x09\x66\x22\xde\x38\xb5\x2d\x28\xc0\xa9\xe3\x1d\xd4\x85\x09\x9d\x06\xb3\x79\xc2\x5f\x9c\x76\xc2\xa2\x9f\xaf\x82\x9c\x16\x72\x1c\x78\x8d\x92\x4e\x38\x8e\xb3\xc8\x0e\x02\xd5\x3c\x8b\x04\xe9\x18\xe9\x2c\xf0\x7f\x67\xb1\xda\x07\x52\xdf\x48\xbd\x82\x62\x8a\xc5\xd9\xda\xef\x74\x22\x9c\x3e\xa1\x18\xa7\xef\x3b\x14\xeb\xc4\x4a\x9f\x58\xe2\x93\xc1\xc3\xe9\xf0\x5a\x92\x4e\x1f\x5d\x0b\x92\x61\x3d\x9d\xf0\xcf\x2d\x9d\x10\xfe\x19\xb2\x81\x60\x14\x8c\x92\xcf\xe0\x14\x02\x16\xee\x64\xac\x7c\x86\x7c\x01\x03\xce\x50\x74\x15\x0a\x49\x86\xed\x20\x7a\x80\x22\xd7\x33\x17\x20\x7c\x75\xd0\x3b\x9d\xb1\xc0\x68\x41\x79\xce\xc5\xd1\x2d\x4e\x6d\x59\x41\xbe\x4d\x89\x74\xae\x96\xce\xa7\xa6\x4b\x60\xbd\x18\x75\x5d\x52\x8e\x74\x49\xad\x8a\xe7\x4a\x75\xbb\x60\xbc\x2e\xe9\xfd\x49\x17\xa2\x49\xe4\x04\x72\x62\x5c\xa0\x5f\xe8\x30\x82\x2f\x9e\x93\x5c\x72\x7f\xd2\x25\x7f\xac\x82\x08\xff\x52\x29\xf3\x42\x12\x13\xf4\xfb\xa4\x0b\x3e\xf3\xf2\x33\x5d\xaf\x7f\xbc\xb4\x14\x07\xad\xca\x97\x9e\x2e\x6d\xe9\xd2\xf0\x74\xd9\x0e\xe5\xb9\xec\xbc\xd2\x05\x10\x70\xc1\xda\x5d\xd6\xd3\x85\xfd\x7e\xd9\x98\x58\x98\xcb\xb7\x0d\x34\x03\x7b\x5c\x58\x88\xcb\x8b\x82\x18\x50\xe9\xf5\xee\xbf\x0b\x01\xcb\xe5\x8d\x75\x1c\x75\x3a\xde\xa3\x81\xc0\xc5\x5c\x74\x85\x97\x8f\x37\x90\xa6\x5a\x5d\x3e\x15\x8f\x0b\xc5\x30\x5b\xd7\xda\xd2\x05\x3d\xbd\x56\x95\x06\x0a\xcf\x7a\xad\x0a\x06\xab\xed\xa1\x3b\xd2\x13\xc3\xc2\x2a\x5c\x2b\x76\x56\x08\xe6\x40\x0a\x6b\x6c\x14\xea\xb3\x61\x29\x81\x04\x2d\x7b\x4b\xb6\xab\x24\x1e\x2b\x23\x48\x34\xb4\xb2\xb3\x21\xc8\xc1\xcc\xad\x00\x2a\x30\xa5\x21\x33\x02\x74\xab\x46\xdf\x67\xb5\x12\x2f\x5b\xad\xb0\x1f\x56\x3b\x3c\x9c\x55\x7a\x17\xab\xef\xc9\xa5\xd5\xbe\xe0\x1c\x0c\x91\x84\xb5\xd7\xbd\x59\x63\x20\x67\xed\x1f\xfc\xb6\xb6\xeb\x2f\xa8\x11\xcd\x58\x23\x8a\xb3\x06\x24\x15\x4f\xb2\x06\xef\x81\xa4\x58\x66\xea\x51\x93\xb5\x0b\xd6\xde\xda\xa5\x50\x49\x6b\x36\x81\x79\xad\xfd\x28\x2b\xfd\x2c\x36\xad\x2f\x47\x20\x59\x6b\xcd\xb3\x92\x53\x5f\xa0\xff\x2d\x63\x9d\x81\x70\xcb\xda\x78\x1b\x22\x2c\x44\x42\xa7\x69\x0d\x11\x0f\xd8\x4e\xce\x0e\xf8\x02\xda\x67\x6d\x7a\xb2\xf6\x7d\x9f\xbf\xc6\x4e\x5e\x4f\x6f\x01\xc1\x8e\x02\x79\xdb\xf0\xc2\x01\x8c\xb1\x34\xd9\xd4\x9a\x00\x75\x9f\xf4\xf3\x1e\x55\xfd\x08\x76\x4c\xfa\xe1\xef\xef\x2f\xfd\xa8\x14\x38\xce\x1f\x95\x06\x5a\xca\x93\x7e\xf4\xd6\x92\x7e\x7c\x4b\x3f\x08\x90\x7f\x00\x2a\x7e\x7c\x05\x94\x0a\xb0\xe8\x67\x01\x0f\xfe\x2c\x2c\xea\x0f\x62\xef\x9f\xc5\x53\xea\x9f\xd5\xcc\x03\xc9\x27\xf1\x10\xff\x23\xed\x94\x70\x4f\x1f\xec\xe9\x8f\x6a\x4f\x1f\x38\xc7\x85\xf4\x49\x1f\xcb\x9f\xf4\xb1\x1d\xbf\xc6\xf7\x86\xe7\x76\xee\x5e\xd3\x07\x70\xfe\x63\x13\xbf\x8c\xbd\xf2\xc1\x94\x3f\x36\x27\x9f\x6f\x4b\x9f\xa6\x9a\x3e\xcd\x0e\x50\x38\xae\x4f\xf3\x3b\x15\xd9\xf0\xd3\x02\xea\x91\x8a\xec\x00\xa3\x45\xf6\x27\x15\xf9\x68\x2a\x08\xf7\x8a\xb4\x73\x41\xb7\x8a\xf4\xe9\x78\x0f\xbe\x4c\x56\x9d\xd6\x52\x41\xdc\x07\xda\x00\xbc\x8b\x7c\x25\x15\x01\xfb\x1b\x65\xf7\x80\x33\x29\xf2\xb0\xfe\xdf\x93\x8a\x0a\xbb\x51\x39\x40\xa2\x81\x7e\x35\x01\x03\xc3\x7e\x17\x3d\x66\x2a\x7a\xa6\x57\xc1\x8b\x9e\x70\x5c\x45\x6d\xbc\xa5\xd5\xd1\x82\x59\xed\x9c\x17\x92\x91\x8a\x7a\x87\x91\x01\x8a\x65\x39\xcf\xe0\x0a\xe2\xb0\x54\x4c\x22\x15\x40\x8b\xf9\x20\x0d\xc0\x94\x62\x99\x3b\xa4\x40\x28\x05\x6e\xe2\xf5\xf1\xc5\x30\x71\xab\x1b\x08\x06\x8e\x28\xa3\x00\x8e\x14\xfb\x0f\x0e\x9e\x38\xb7\x18\x8f\xba\x10\x73\xa6\x62\x34\x6f\xc5\x85\xa4\xa5\xe2\x1b\x4d\x65\x71\x40\x0e\x02\x85\xe2\xa7\xe5\x54\xbc\x69\x79\x90\x9c\xa9\x38\x64\xe9\x18\x26\x72\x16\xda\x2e\xb8\x66\x3a\x95\xe2\x0f\x9a\xae\xfc\x79\x52\x59\x27\x71\x77\x59\x0c\x98\xcb\x6a\x42\x9a\xaf\x54\xd6\x2f\x76\x52\x79\x02\x08\xb7\x4a\xbe\xe0\x08\xab\xec\xa9\x0a\x3a\xac\x72\x36\x9d\xa9\x8a\x21\xc7\x4a\x62\x6c\x56\xe5\xc7\x23\x55\xac\x70\x95\x5a\x05\xd9\xc8\x6d\xe8\x05\xe1\x33\x76\x45\x95\x76\x3a\x28\x31\x77\x15\x7e\x39\xa9\x02\x80\x5c\x25\xb6\x37\xc9\x17\xe8\x49\x9e\xf1\x76\x1d\x1f\x76\x18\x61\x2f\xb7\xf1\x01\xc1\xe0\x28\x93\xca\x23\x43\x6c\xfc\x30\x32\x9c\x7c\x0b\xfb\x45\xf2\xd6\xf8\xb5\xba\x6a\xaa\xf0\xfb\x55\x65\xf7\x1b\x49\x03\xa1\x06\x54\xf8\xbe\xaa\x40\xe7\x98\xa2\xee\xe0\xa3\xbb\x49\xaa\x5a\x10\x09\x55\x2d\xa8\x40\x69\x55\xad\xd8\xd2\x00\x19\x9c\x87\xb6\x95\xaa\x46\x46\x16\xf4\xb8\xd2\x40\x55\x9e\x07\x56\xe0\xa4\x8a\x58\x82\x05\x93\x7c\xe7\xe5\x7b\xaa\xb6\xc3\xfc\x56\xdb\x1b\x95\xa4\x5a\xf9\x80\x50\x2f\xaa\x21\x76\xac\xd8\x91\xd5\xda\x3b\x76\x43\xbc\x5b\xad\x21\x42\xa8\x16\x92\xd9\x9a\x5e\xa5\xda\xc0\x92\x33\x06\xaf\x08\xb9\xb1\x0c\x98\xbe\xfd\x2a\x38\xfc\x72\x13\x54\xdf\x00\xe5\xaa\xef\x5a\x40\xe1\x02\xaa\x57\xfc\x60\x25\xab\x37\x43\x34\x58\xdf\xf8\xba\x7a\x7b\xa5\xeb\x0d\xf2\x74\x8c\x8a\x67\x62\xd5\xc9\x2b\x1a\x82\xdf\xea\xe3\xbf\x65\xd3\x53\x7d\xcf\xc6\xff\x45\x88\xd5\x5f\x4e\xab\xf1\x38\xa8\xf2\xfb\x40\x85\x16\x56\xff\x9a\xa6\xba\xb0\x62\xeb\x38\x50\xb8\x30\xa8\x55\xa6\xf5\xf2\xa4\xba\x06\x27\xb6\x86\x62\xd2\x6b\x5c\x3c\x7b\xaf\x6b\x40\x20\x30\x6b\x75\xf1\x13\x66\x7d\x86\x96\x03\x09\xd5\xbd\x3e\xf3\x4a\x4d\xb0\x79\x1a\x60\x62\x93\xfe\xb1\x96\xda\xfb\xd5\xab\xc9\x98\x4f\x6a\xc2\xc1\xb5\x37\xba\x68\x2a\x91\x9a\xe6\x4f\x6a\x08\x29\x9a\x9e\x32\xd9\x5c\x4f\x9e\x48\xb6\x7f\x41\x75\xd3\x7e\xe9\x9d\x9a\x06\x0b\x07\x4a\xf8\xe3\x37\xb3\xa6\x6b\x42\x2a\x8d\x01\x47\xd3\x7b\xa4\xa6\xbf\x33\x35\x98\xe7\x77\x65\x9b\x43\xb5\x9b\x23\xa2\x6b\x5e\x0d\x86\xb3\xb9\xef\xcc\x0c\xec\x95\xe6\x81\xd1\x3b\x2b\x4c\x79\xab\x4f\x92\x0b\x52\x6e\x88\xf2\xf0\x0a\xd3\x03\x33\xdb\x56\x2e\x1c\xfe\xbb\x7f\x1b\x8f\x1c\xdb\x9a\xc9\xe5\x93\x7c\xd3\x27\xf9\x46\xbf\xe8\x5b\xb1\x53\x93\x6f\x23\x63\xce\xbe\x0d\x4e\xc3\x37\xae\x8b\x6f\x5f\x1e\xdf\x79\xce\x2b\x92\x67\x6c\x09\xcf\xd3\xc1\xd3\x77\x8f\xe4\xc7\x81\x9f\xf2\x09\x43\xf0\x03\x0e\x00\x61\x87\x7f\xe4\x49\xc0\x41\x4e\x8b\xe5\xe5\xa9\xdd\x72\x72\x18\x38\x07\xec\xf5\x86\x1f\x04\xee\x8d\xe7\x70\xde\xca\x93\xbc\xa3\x7d\x47\x20\xee\xdd\xde\xe2\x4e\x08\xe1\x9d\xab\xe3\xef\xb7\x4b\x0f\x40\x46\x8f\x4c\x28\xf8\x9e\x2a\x79\xec\xd6\x60\x68\x3d\x4e\x8c\x34\x78\x80\xed\x61\x27\xe3\x36\x8f\x7e\x21\x7b\x4c\x9e\x14\xbc\x0a\xe9\x6b\x12\x5d\xf8\x9a\xef\x1b\xa0\x80\xaf\x49\xaf\xef\x08\x18\xfd\x8b\x11\x61\xf5\x80\x98\xfd\x06\x74\xf0\xdf\xe7\x44\x2e\x95\x2b\xf9\x1f\xe6\x42\xb8\xd3\x85\xbb\xb6\x63\x3b\xf3\xb0\xae\x4b\x01\xba\xee\x52\x6a\x42\x10\x2e\xa0\x5a\x40\x2d\x83\x72\x14\x5d\x3a\x69\x20\x9e\xee\xc2\xb3\xd2\x2e\xf1\x01\x09\xe7\xf3\x7c\x52\x87\x51\xeb\xb4\x66\x1d\x46\xac\xcb\xb4\xb7\x26\x4f\xac\x3b\x8d\x59\x4b\x9d\x5f\x41\x3a\xfc\x5b\x97\x87\x7b\xb7\x2b\x07\xa1\x02\x1d\xe0\x07\xe5\xae\x32\x84\x25\xc5\xb2\xb4\x04\xb1\x77\x6d\x82\xa8\xbe\x6b\xcb\x56\x52\x57\x87\xe9\xed\xca\x53\xef\xae\x71\x40\x63\xba\x06\x96\xb0\x6b\xc0\xe9\x75\x9d\xa9\x5f\x9c\xfe\xe5\xd3\x53\xbf\x78\x7a\xd2\xaf\x67\x18\x3c\x51\x37\x69\x9e\xba\x65\xce\xd6\x5e\x6f\xdb\x4d\x31\x1a\x3b\xf1\x53\x70\x01\xba\xec\x56\x30\x53\xf8\xbe\x6e\xde\x14\x7d\x5a\x47\xbd\x31\x31\x3b\xe3\xbc\xed\xef\x4f\x52\x7f\x65\x5a\x04\x3b\xad\x97\xf7\xe4\xae\x13\x59\xf1\x58\xb1\x17\xe2\xc8\x5e\x78\x34\xd6\xe1\xd3\x40\x4f\x10\x28\x4f\x77\xad\x20\x33\x75\x07\x9a\xef\x5e\x20\x12\x00\xf6\xee\xf0\xd2\xa9\x7b\xdb\x41\x9e\xd4\x1d\x9d\x7b\x5f\x6f\x95\xa0\x12\xf2\x00\xf7\xdf\xc3\xb0\x8d\xed\x06\xf8\x4c\x81\x10\xfe\xb9\xd8\x0e\xad\x81\x3c\xfd\x86\x7a\xbe\xa7\x61\x3d\x24\x73\xb7\xf6\x10\xec\xf8\x1e\xca\x1b\x16\x3d\xf4\x60\xb1\x62\xfd\x91\xf2\x2a\x48\x0f\x9d\x60\x11\xfa\x7d\x5f\xdf\xa6\xd0\xce\x1e\x56\xa1\xed\x3d\xec\x2d\xf1\x30\x56\x35\xae\x4c\xd8\x97\x02\x09\xfb\x03\x85\x91\xa9\x48\x79\xd2\xd4\xc3\xf7\x45\x4e\x7e\x60\x35\xc3\x79\x4c\xdc\xc3\x69\x16\x7a\x78\x75\x36\x76\x3f\x40\xfb\x3b\x91\x40\x24\x89\x41\xfa\xfc\x57\x6d\xed\xa0\x3c\xb5\xed\x6b\x43\x7c\xdd\xd7\xbe\xc3\x28\xf5\x85\x45\x5d\xa5\xa7\x17\xf2\xf7\x55\x69\x72\x3b\x61\x44\x5f\x1d\x2a\xb6\x10\xd4\xf5\x15\xef\x17\xb4\xbe\xde\x19\xac\xe0\x8e\xef\x34\x5b\x7d\x0d\x54\x9f\xa9\xaf\xbf\x3f\x48\xfa\x09\xa9\xb6\xa7\xff\x96\xf0\x12\xcd\x7f\x4b\xda\x5c\x15\x69\x60\x37\xfe\xb7\x74\x70\x6d\xfe\x5b\x40\xb0\x70\x3f\x20\x7f\xe9\xbf\x85\x29\x85\x6c\xb0\x1c\x21\x39\xc3\x67\x31\xf6\xe5\x77\x97\x90\x5d\x02\xd4\x3c\x05\x80\x0b\x03\xe2\x77\x91\x42\x80\xbc\x03\xd8\x34\x04\xc3\x0f\x69\x80\xc1\xaf\x2d\x0a\xe9\xb6\xa7\xc0\xb2\xf1\x3b\x42\xbc\x67\x09\x21\xb0\x1c\x21\x77\x0a\xf9\xf3\x48\xef\x2d\x14\x7e\x69\x44\x9c\x83\xce\x15\x48\x38\xf4\xfd\x12\x1c\xca\xef\xb1\xa1\x59\x61\x31\x43\x33\xd4\x3f\x34\x7b\xb0\x90\x5f\x46\x42\xb9\x6e\xa1\x07\x9d\x50\x28\x83\x9f\xd0\x03\x7b\x3e\xf4\x34\xb2\x3d\x43\x51\x76\x52\x69\x43\x7f\xde\xaa\x45\x7e\x41\xb9\x37\x42\x0b\xc2\x77\xde\x5d\x08\x25\x46\x0b\xfd\x07\x60\x42\x89\x2c\x42\xe9\x91\x43\xdb\xce\xcc\xa6\x77\xa2\x65\x0a\xa5\x95\x86\xa6\x1a\x0a\x3a\xd0\x51\xe8\xbb\x2b\x43\x79\x7b\x27\xf4\xbd\x70\x14\x3a\xf2\x62\xa2\x8c\x52\x43\x79\x55\x24\x74\xf8\x0a\x56\x1f\xdd\x1b\x07\x34\x56\x41\xc1\x7c\x9b\xcd\x78\xb9\xce\x15\xe8\x6a\xb5\x77\x66\xdf\x57\x7c\x5f\xe3\x60\x78\x36\x15\xd7\x33\xaf\x9a\xc2\x36\xfc\x36\x54\xc3\x26\xa1\x91\xe7\x46\x79\x3f\xea\x87\x1d\xe8\x9f\x2e\x17\x2e\x61\x4f\x3c\x9e\x0f\x73\xbc\xf3\x7e\x0d\xbf\xf1\x87\x11\x3f\x04\x4f\x0b\x83\x5f\x78\x02\x38\x3b\xf8\xb5\x32\x7c\x73\xd2\xc5\x17\x46\x6d\xe1\x95\x07\x39\xdc\x2c\xe1\xfe\x31\x3e\xd7\x14\xd0\xe2\x70\x86\xc7\xc1\x53\xea\xf7\x02\x4e\xc0\xdb\xa4\x20\xe0\x8e\xb5\x51\xe6\x08\x84\x63\x9d\x29\x00\x77\x62\x35\xfc\x6e\x79\x52\x2c\xc0\x87\x21\x3b\x7e\xf0\x2d\x43\x76\x46\xdf\x43\x0e\xbc\x18\x0a\x0b\x8b\x0b\xc2\x94\x21\xe5\xa5\x13\x04\xfd\x0c\xe0\x9d\xf1\x1e\x34\x0f\x44\xa1\x43\xa6\x8d\xe3\x41\xea\xe3\xb2\x34\x04\x2a\x35\x64\x11\x85\x0e\x38\x8e\x21\x4f\x1a\x19\x01\xf5\x80\x77\x18\x19\xca\x3d\xf2\x0b\x97\x47\xd6\x86\xb7\x4b\x2b\x13\x58\xc8\x91\x8d\xe7\xac\x23\xdb\x18\x1e\x23\x8d\xec\xc1\x0f\xe7\x23\xfb\x9a\x69\xe4\x90\x0e\x8a\x58\x73\xe4\xb0\xce\xbc\xb5\xa5\xa1\x82\x1f\x80\xfd\x78\xb7\xc5\xc0\xca\x0f\xcd\xb0\xc1\x43\x33\x74\x19\xb1\x38\x99\x69\x7e\x6d\xc4\x00\x26\x1b\xaa\x9f\x34\xf4\xa4\x8f\x1b\xfc\xa2\x81\xa4\xa4\x01\x0d\x96\x48\x43\x19\xf3\x0e\x86\x5d\xb0\xa7\xef\x18\x35\x4c\x07\x12\x7e\x2a\x1b\x3a\xc6\xcb\x9b\x01\xd6\xd0\xb9\x7a\x1a\xb0\xb7\x69\x5c\x8c\x05\xc6\x25\xc7\x04\xe5\x21\xce\xb8\x28\x8c\x0b\x03\xb8\xd8\xdb\xa5\x61\xc7\x91\xc6\xc5\xd3\xe3\x71\x19\x6b\x03\xd3\x8c\xcb\x3a\x08\xb4\x68\x5c\x08\xcb\xc6\xe5\xc8\x76\x47\x15\x47\x21\xb6\xcb\xb8\x7c\xf1\xb3\xcc\xb8\xb0\xe7\xc6\x15\x56\x51\x06\x8d\x18\xd7\x3a\xa0\xba\xe3\x7a\x12\x9c\x0d\xb4\x76\xc0\xb4\x11\xa3\x0c\x53\x2c\x1a\xd5\x9a\xdf\x0a\x87\x15\x8a\x03\xf1\xc2\x30\xd8\xad\x61\x85\xfd\x5b\x35\xd8\x83\x61\xaf\x2a\xf0\xeb\xf6\x78\xb9\x05\x26\x6b\x44\x33\x03\xfa\x0f\xb5\xb1\xdf\x34\xe0\x3b\xc6\x87\xaf\x3c\x1b\x48\xe3\x63\xf8\x61\xd6\x30\xe6\xe3\x63\x18\xfd\x07\xb6\x7e\x20\xb8\x1f\x45\x6a\x1a\x45\xb5\x83\xd2\x72\x0c\x7a\xd4\xc1\x93\xcd\xf1\x46\xbc\xa3\x18\x6a\x39\x60\xda\x80\xdb\x1f\x14\x2c\xcf\xb1\x47\x85\x15\x1c\x55\xc0\xb8\x22\x22\x19\xd5\x3f\xa4\x3e\xaf\x34\x1a\x8c\xf5\x68\x88\x61\x46\x83\x4e\x35\xca\x1e\xb0\x77\x38\xde\x3d\x67\xf4\xea\xfc\x92\x3d\x28\x73\xdf\x25\x0d\xc7\xaa\xd0\xd3\x0f\x2f\xbb\xb1\x4e\xb1\x1d\xf4\xbd\x30\x32\x78\x5e\x33\xbc\x2a\x00\xcd\x40\xc8\x3c\x9c\xf9\x08\xd5\x06\xd7\xc9\x17\x78\x62\x13\x0f\x87\x9a\xbc\x56\x6c\xf8\xc2\xd0\x3a\x0c\xe0\xa0\xff\x1e\x00\x67\xe8\xbf\xcb\xdd\xd2\xe8\x2a\x1f\xd0\x77\x4c\x9d\xca\xdb\xa9\x3b\xfc\x24\x3c\xfa\xa5\x6c\x44\x49\x75\x5e\x44\x18\xdd\x3e\x7c\x41\x73\x43\xc8\x38\x7a\x21\x05\xbc\xa6\xd5\x84\x6a\x77\x8e\x90\x36\x77\x74\x48\xb2\x07\xf6\x6e\xe7\xe5\xa6\xd1\x69\xe3\x46\x7f\xd2\x80\x7f\x54\x24\xbc\xef\x84\xb0\x8c\x37\xd5\xc6\x1b\x4f\x8c\x29\xbb\xad\x8a\x14\xd2\x9c\xb4\x04\x53\x0c\x3b\x79\xc2\xef\x8d\x49\xd3\x31\xb9\x2c\xb4\x68\x63\xa2\xa3\xc9\x99\x4d\x25\x2b\x05\x03\x2c\xfd\xd4\x50\x4f\xc0\x65\x28\xa4\xba\x4c\x8e\x64\x72\x3d\xa6\x57\x81\x32\x4d\x0a\x7a\xd2\x80\xf0\x18\x75\x4c\xaa\xff\x84\x1f\x3d\xf1\x1a\x8a\xdd\x3f\x83\xb2\x98\xc1\x35\x99\xb1\x78\xba\x3e\xe6\xe2\x0d\xd8\x31\x17\xc7\xfc\x9e\x83\x8e\xf9\x80\xae\x37\xc0\x19\x6b\x03\x5c\x1d\x6b\x83\x31\x1d\xeb\xbd\x3c\x3b\x10\x5f\x8e\xc5\x93\xdd\xb1\x18\xc0\x8c\x75\x0a\xe9\x89\x10\x8e\x07\x48\x63\xf1\x18\x7a\x2c\x54\x6a\x0d\xcd\xdb\xc0\x70\x56\x67\x76\x47\x40\x3a\x56\x0f\xda\x41\x20\xdb\xb1\x82\xdf\xc7\xc6\x42\xa0\x3f\x56\x00\x8c\xf1\xe1\x35\xfc\x63\xc5\x57\xd1\xe6\xbd\x45\x39\xd6\x60\x9c\x35\xee\x7f\x96\xe5\xa6\xa4\x6f\x21\x89\x9a\xc6\x0d\xac\x3e\x6e\x0a\xe1\xa6\x59\xb9\xb1\x73\x6e\xca\xf2\x26\x24\x1e\x37\xf0\xc1\x78\xea\x06\x29\x3e\xb5\x4f\xaf\x69\x3c\x01\xed\x7c\xb8\x24\xef\x0a\x4f\xe1\x0d\xa2\x29\x67\xe2\xbd\x81\x29\xb4\x13\x53\xca\x27\x4d\x69\x20\x1d\xc5\xfc\x14\x34\x65\x20\x63\x4c\xe4\xcc\xe9\x9e\xa6\xfc\x5a\x9a\xbc\xbd\x38\x55\x6a\x9a\xd0\x5e\x04\x7b\x53\x1b\x02\x89\xa9\xad\xd9\x40\x82\xe7\x40\x85\x81\xa7\xdf\x99\xe6\x45\xf6\x97\xe0\x11\xb2\x9a\x17\xda\x5d\x8a\x15\x9f\xd4\xfc\x79\x29\x1e\x31\xad\x79\x81\xcd\xe5\xbc\xd1\x35\xaf\x50\x94\xf2\x6b\xfb\xbc\x10\xab\xcf\x6b\xd5\x0d\x94\xc6\x65\xbe\x77\x5c\x26\x8c\xcb\xb4\x93\x39\x05\xef\x44\x32\xd3\xd0\x9b\xb5\x27\x4d\xeb\x09\xc8\x62\x4f\xf3\x3d\x7c\x9d\x06\x63\x3f\xe9\xd4\xa7\x6f\x80\x83\x69\xfa\x2e\x0f\xe8\x5e\xd0\xd8\x51\x7e\x2a\xc1\xdc\x74\x2b\xe8\x87\xd7\xfe\xa0\xbe\x13\xd5\xeb\x7b\x09\x91\x6a\x3c\xbd\x9d\x8b\x09\x4d\x1c\x95\x7a\xd2\x64\x4d\xef\xf8\x59\x06\xed\xec\x15\xde\x6e\x7a\x34\xd9\xc1\x26\x26\x83\xff\xe9\x63\xa4\xe9\x53\xd0\x70\x85\x71\x64\x84\x38\x93\xa1\xc3\x44\x00\x3a\xfd\x49\x93\x80\x75\x32\x5a\x9c\x21\x08\xbd\x91\x9e\x6f\x62\x0d\xb4\x0d\x68\xf5\x84\xd7\x9d\xbc\x39\x34\x81\x47\x4b\xe2\xbd\xd0\x17\x5c\x4d\xca\x16\xf8\x2e\x4d\x1e\x8d\x4d\x5e\x3d\x99\xbc\x0a\x39\xc3\x4e\x8a\x33\xac\x82\x80\x8d\xf7\x0b\x6d\xdf\x9b\x14\x33\x16\xab\x2d\x3e\x16\x14\xac\x8a\x78\x70\x06\xb0\xd1\x0c\x98\xc4\x89\x15\x5e\x60\xba\xde\x80\xe9\xdf\x26\x9d\xab\x09\x08\x42\xe1\xb9\xe2\x83\xd5\x07\xd0\x9b\x2b\xb8\x2c\xb7\xc2\x14\xcf\x5b\xdb\x7c\xd2\xbc\x61\x16\xe7\x8d\x89\xdd\x94\xca\xed\x69\x3e\xd0\xd6\xa7\x33\xcc\x5c\x67\x79\xd2\xaa\x5b\x68\x29\x92\xd6\x7b\xd5\x60\xb5\xf7\x36\xf0\x6a\x99\x6f\xef\xc5\x94\x57\x6d\x56\xdb\x3d\xad\xc6\x2b\xea\xab\xf1\x13\xe9\x6a\xef\x27\xa6\xd5\x8c\x98\x7a\x35\x5e\xcd\x5e\xcd\x26\xc8\x57\x11\x8c\xac\xf6\x69\x58\x85\xd5\x78\xc6\xba\xda\xb4\x92\x56\x5b\xbc\xa7\xb8\xda\x57\xf1\xda\x79\x9a\xb9\xfa\xc9\x05\x5a\x9d\x9f\x83\x56\xf7\x96\x16\x43\xe9\xd5\x61\x45\x56\x6c\xd2\x12\x0d\xc5\x0b\xbc\x80\xe0\x79\xe5\x7c\x0d\x3d\x56\x41\xc2\x0b\x12\xff\x98\xcf\xf7\x3f\x03\x5f\xc9\xd8\x6e\x5f\xc9\x6b\xd5\xf4\x15\xe8\xdc\x57\xe0\xc7\xbe\xef\x3d\xf8\xaf\x40\x74\x5f\x69\xf8\xd9\xb8\xd2\x57\xba\x47\xfa\xca\x7b\x15\xeb\x0b\x85\xff\xf2\x83\xfa\x57\x2f\x83\x68\xbe\x10\x36\x5e\xdb\x8e\x8a\xbc\x14\x89\xdc\x06\xd6\x1a\x1b\x88\x1d\x0f\x12\x02\xa5\x2f\x82\xdb\xaf\x8e\xa1\x25\x7d\x75\x6a\xa0\x2f\xa3\xcc\xbf\xb6\xf1\x0b\xe2\xd7\xf2\xdb\x9b\x65\xda\x75\x04\x88\x9e\x88\xda\xbf\x56\x0a\xa6\xfb\xb5\x36\xdf\xd4\x8b\x81\x41\x10\x77\x7f\x2d\xd8\x6e\x08\x88\x81\xd5\x78\xf3\x27\xe9\x17\x33\xe5\x29\xf7\x97\x17\x25\x79\xf9\xfb\xeb\x25\x4b\x73\xa4\xab\x22\x6f\x82\x3c\x60\x7f\xff\x23\xde\xd2\x2d\x36\xd3\x0d\x7b\x07\x7b\x0b\xd2\x16\x32\x1a\x48\x1c\xd0\x15\x5a\xdd\x5b\x02\xc1\x74\xba\xb1\x6d\x6e\x19\x1d\x64\xa2\x10\xf8\xe8\x06\x3e\x86\x33\xb9\xdf\xef\x8a\xb7\x0a\x96\x96\x96\xfa\x46\x6c\x55\x90\xd0\x68\xdc\xba\xa5\x5b\xdf\x70\xf8\x56\xfd\x60\xa7\xdd\x6a\x01\x5a\xf8\xcd\xeb\x86\x91\xbc\x75\xa6\x9b\x5f\xaf\x6e\xd8\xc8\xfb\xd2\x97\x82\x13\x2c\xe5\x4d\x13\x79\x03\x4a\xde\x97\x31\x02\xbf\x61\xef\x6e\xdb\xd1\xbf\x1d\x78\x2c\x3b\x48\x49\xd8\x25\xb7\x35\xc0\xd6\x1b\x08\x94\xae\xe2\xb6\xf6\x01\x69\x6c\xca\x4b\x31\x37\xc2\xac\xdb\x06\xc2\xd8\x1b\xd6\xe7\x86\xae\xdc\xff\xee\x28\xdc\x5e\x8e\x74\x23\xae\x49\xb7\x73\xc7\xdc\xee\x3b\x48\x49\xf4\x37\x3c\xdc\xbc\x3d\x0a\x1f\xe3\x01\xc5\x60\x60\x6f\xee\xd0\xfc\x01\xe5\x25\xde\x9b\x86\xec\xe6\xcd\x8d\x9b\x0e\xfc\x81\x49\x7b\x20\xaf\x47\xe9\xf7\x1e\x5f\xf8\xa1\x88\x40\xea\x4f\xb7\x90\xf4\xa7\xe1\x89\x47\x6b\x7f\xee\xe9\xff\x00\x00\x00\xff\xff\x96\xd2\xdb\xc1\x3c\x33\x00\x00") -func keysWordlistEnglishTxtBytes() ([]byte, error) { +func keysWordsWordlistEnglishTxtBytes() ([]byte, error) { return bindataRead( - _keysWordlistEnglishTxt, - "keys/wordlist/english.txt", + _keysWordsWordlistEnglishTxt, + "keys/words/wordlist/english.txt", ) } -func keysWordlistEnglishTxt() (*asset, error) { - bytes, err := keysWordlistEnglishTxtBytes() +func keysWordsWordlistEnglishTxt() (*asset, error) { + bytes, err := keysWordsWordlistEnglishTxtBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "keys/wordlist/english.txt", size: 13116, mode: os.FileMode(420), modTime: time.Unix(1511602021, 0)} + info := bindataFileInfo{name: "keys/words/wordlist/english.txt", size: 13116, mode: os.FileMode(420), modTime: time.Unix(1514928181, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _keysWordlistJapaneseTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x5c\xff\x72\xe2\xb8\xd2\xfd\x9f\xa7\x5e\xbc\x5c\x2f\x01\x3c\x0e\x71\x1c\xc7\x61\x58\x87\x8a\x2f\x43\x60\x80\x0c\x59\xb8\x93\x8f\x2c\x3c\x8c\x5f\xe4\x2b\xf5\xe9\x3e\xea\x99\xaa\x54\xea\x1c\x59\xd6\xcf\x56\x77\xab\x25\xd3\xf5\x93\xae\x3f\xe8\xfa\x45\xd7\xcf\xbb\x7e\xd5\x25\x45\xcf\x92\xca\xae\xdf\x92\x3c\x03\x8d\xba\xfe\xdf\x5d\x72\x03\x32\xee\xfa\x8b\x2e\xf9\x93\xef\x64\x5d\x32\x06\x9a\x76\xfd\x49\xd7\x6f\x8c\x58\x72\x11\x92\x93\x09\x79\xd9\xf5\x07\x44\x07\xa0\x4a\xfe\xaf\x40\x1e\xbb\x24\xef\xfa\x29\xc8\x53\xa8\xd1\x5e\x7d\xea\xfa\x19\xd0\xbc\xeb\x9f\x80\x9a\xae\x3f\x64\x86\x26\xfc\x25\x7d\xc7\x93\x51\xd7\xbf\x74\xfd\x21\xb9\x3e\x69\xd9\x8a\x56\xfa\xa4\xd5\xbd\xc8\x70\xfc\xa7\xeb\xe7\x7c\x78\xe9\x92\x91\x11\x57\xf4\xb2\xeb\xaf\x89\xf6\x92\x4d\x9f\x1c\x88\x4e\x1c\xb5\x13\xd3\x8e\x7e\x2c\x2e\x6c\xc5\xa5\xeb\xbf\x1a\x4a\x06\xd2\xa4\x9a\x5c\xeb\xbf\x76\x49\xd2\xf5\x77\x42\x42\x4b\x46\x5d\x1f\xe5\x84\x17\x58\x7f\x92\x76\xc9\x1f\x40\x37\x32\x8b\xb7\x5d\xff\x42\x5e\x11\xd5\x5d\xff\x91\xc4\x8f\x5a\x72\x23\x65\x44\x92\x5b\x5b\x42\x8d\x93\xae\xbf\xb2\xe1\x0a\x4f\x66\xcc\x99\x87\xa1\x30\x52\x58\xcf\x12\x99\x7f\x47\x0a\xa2\xaf\x26\x44\x81\x2c\x7d\x9e\xb5\x27\x3a\x00\x03\x88\x24\xda\x32\x08\x52\x29\x6f\x0f\x58\x3c\x50\x0e\x94\x89\xd8\x0e\x48\xd6\x2c\x24\xe3\x28\x0e\x28\xbd\x03\x59\x08\x8f\x44\x27\x96\x3d\xed\xfa\x6f\x98\x69\x21\x96\x5c\x60\x08\x74\x0d\x11\xb5\x3d\x5b\x44\x17\x11\xea\x81\x71\x7b\xaf\x82\x04\x0f\x44\xca\xff\xc3\x42\x1e\xbb\xe4\x2f\x4f\x72\x36\xeb\xa9\xeb\x5f\x0d\x25\x13\xa0\x19\x0b\x9e\x05\xe1\xef\xbf\x93\x8c\xfd\x13\xad\xe8\x2b\x2b\x9f\x77\xfd\xb4\x4b\x32\x56\x34\x97\x01\x8b\xcd\x7c\xf6\x48\x3b\xd5\x48\xc5\x37\x24\x57\x43\x41\x16\x12\x90\x85\x8c\x75\x4a\xf2\x48\xf4\x4a\xf4\x46\x74\x32\x94\x8c\xfc\x10\xb4\x10\xe6\x41\x5c\x83\xd6\xec\x17\xdf\xe3\x17\x74\x83\xa4\xf1\xd9\x16\x44\x4b\xff\xc2\xbf\x7c\x61\xd9\xf5\x1f\x0c\xd9\x7b\xaf\x7c\xba\x82\x70\x0e\x28\x7f\x40\xda\xac\x6d\x97\xfc\x41\x21\xda\xb1\xb2\x1d\xa7\x6a\xcf\xf9\x7f\x73\x69\x56\xcd\x3b\x27\xe4\xc0\xb4\x23\x87\xf9\x27\xd3\xce\x6c\xce\xd5\xd2\x82\xbc\xa6\x50\x8f\x20\x8d\x89\x42\x92\x58\x8b\x12\x91\x7e\xad\x36\x10\xac\x92\x64\x28\xfa\xb3\x20\x41\x7d\xa2\x19\x88\x6a\x96\x3d\x12\x6d\xb1\x30\x12\x85\x32\xe1\x1a\x0b\xda\x8b\xeb\x27\x89\x55\x66\xa2\x87\x8b\xae\xff\x8f\x0d\x43\x50\x08\x03\xa2\x94\x28\xb6\x27\x37\xb9\x08\x02\x9f\xb2\xa8\xa2\xeb\xdf\xd9\xca\xef\x33\xa9\x64\xb9\x85\x08\x48\x6c\x5b\x21\x3d\x0b\x24\x95\xf5\x90\x19\x92\x02\x53\x91\xce\x07\x20\xed\x46\x2a\x4b\xe5\x44\xf4\xc1\xac\x59\x97\xe4\x40\xb9\xe9\xcf\x35\xf9\x04\xe3\x9e\x8a\x5a\x68\xa4\x7d\x39\xdf\x9c\x8a\x0c\x4f\x49\x56\xee\x49\x18\xb1\x96\x44\x93\xef\xa9\xe5\x41\xb4\xde\x02\xc3\x93\x4a\x8f\xbf\x00\x55\x22\x88\xa9\x91\x30\xd8\x13\xac\xc5\x54\xa6\x6f\x40\xf4\x85\xe8\x96\xb3\x2c\xdc\xf4\x7b\x2a\xab\x49\x1b\xb3\xa0\x16\x27\x9f\x70\x00\x16\x1c\xc9\x05\x17\x6a\x2a\x0b\x6a\x0c\xa9\x4b\xa5\xc7\x39\x55\x48\xaa\x2b\xd2\x8d\x7c\x4b\xf4\xca\x6e\xad\xd9\xca\x35\x74\x05\xd0\x13\x47\x60\xcd\x97\xb6\x44\x3b\xd6\x7f\xea\xfa\x77\x44\xf7\x30\xed\xa9\xcc\xc5\xc4\x72\xc7\xbe\xca\xd2\x01\x12\x1b\x69\x64\x68\x95\x85\x31\x9a\x88\xd4\xd4\xe4\xba\x04\x40\xd6\xd6\x37\x51\x78\x56\x77\x20\x99\x49\x43\x32\xa6\x57\x93\xca\x4a\xa9\x1c\x49\x52\x1b\x46\xd7\xbe\x0c\x9a\x26\x95\xb1\xcf\x88\x4a\xa0\x82\xf6\x05\x64\x61\x43\x07\x3b\xe9\x88\xea\xae\xa1\xc8\xe9\x10\x4f\x40\x26\x44\x19\x97\x0a\xf8\x3d\x91\x6a\x55\x90\x93\x7b\xdb\x96\x13\x48\x0e\x34\xc2\xa4\x0f\x65\xbc\x22\xd2\xa7\x99\x4c\xbc\x16\x17\xdd\x82\xa1\x88\xeb\x9f\xcc\x56\x77\xfd\x25\x50\x2b\xae\x85\x56\xb9\xeb\xfa\xb7\x40\x67\x9d\x4c\x19\x15\xe1\x96\x87\x69\x61\x4e\x1f\x89\x76\x40\x37\x56\x79\x40\x27\x20\xb5\x50\x50\x4b\x1c\x9d\x40\xc6\xcc\x5d\x40\x18\x87\xaa\x75\xac\x8a\xc2\xfc\xc0\x94\xfc\x2b\x56\x0d\xc8\xdc\x7a\xa4\xf3\xf3\x97\xcf\xb9\x42\xce\x91\x8c\xeb\x98\x4b\x7e\x64\x5e\x42\x4d\xa2\x82\x32\x32\x0b\x98\x83\xa4\x6c\xee\xc8\x14\xc1\x85\xe4\x91\x68\xc6\x7a\x52\x8e\x3e\xc8\xd1\x17\xf5\xe1\x9e\xd8\xcc\x8e\xb8\x48\x47\x74\x94\x46\x34\xe3\x40\xaf\x9c\x73\xe1\x09\xf3\x84\x42\xe6\x20\x63\x0c\x34\xc9\x13\xd0\x04\x2e\xa8\xa4\x05\x15\xa9\x19\xbe\x50\x8d\x8d\xe8\x7a\x8d\x44\x5c\x62\x0f\x73\xef\x0d\x09\x57\xaf\x73\x4d\xce\xd7\x6c\x45\x8d\xfc\xb0\x16\xbe\x92\x82\x19\x4a\xdf\xe3\x92\xeb\x5a\x88\xe9\x8b\x11\x66\x04\xeb\x1a\x24\xbe\xf3\x08\x49\x01\x2a\x39\x3d\x22\xde\xf6\xc2\x5c\xc4\x2f\x27\x89\x8d\x6d\x68\x7b\x40\x34\xcf\x33\x9c\x7d\x90\x85\x97\x81\x17\x18\xe5\x91\xac\x14\x1d\xbf\x6f\x10\x27\x90\x95\xd4\xad\x2b\x00\x7c\xed\x25\xea\x95\xaf\xbd\x8a\xc2\x19\x73\x84\xde\x7c\xfb\x2f\xb0\xf5\x42\x92\xbe\xd4\xb1\xb2\xe1\x4b\xb0\x0d\xfc\x46\x12\x93\x29\x6e\x81\x84\x0d\x21\xc8\xc0\x44\x32\x19\x88\xe6\x7b\xef\x99\xc0\x7c\x5a\xf5\xb2\xec\xb1\xb7\x1c\x49\xc3\x34\xb9\xa0\x3a\x01\x99\xb2\x06\x2c\xc6\x3f\x49\x66\xd6\x78\x29\xc7\x93\x68\xa8\x46\xa6\x1f\xb5\x98\x31\x76\x70\x40\xaa\x1f\x27\xd0\x8f\x44\xea\xde\x4f\xbc\x87\x3f\xf6\xbb\xe2\xb1\x2e\x5a\x69\x0b\x48\xed\x1d\xab\xb1\x77\xb8\x41\xfe\x86\xf1\x23\x6f\x7d\xb1\x4b\x9f\x73\xe5\x9f\xe8\x02\x9e\xa8\x73\x28\x8d\x1c\x7b\xff\x70\xec\xf5\xf4\xc4\xfb\x74\x63\x2a\xed\x31\xc5\x77\xcc\xa5\x3c\xfe\x2d\x79\xc2\x96\x4f\xb0\x39\x1c\xd3\xb5\x18\xcb\x62\xbc\x27\x5a\x31\xeb\x03\x5e\x9f\xa0\x7b\x48\x6b\x58\x7b\x03\xf3\x39\xf1\x8a\x71\x22\x02\x9d\x71\x7a\xc0\x0b\x4f\x4a\x8e\xfe\x8b\xf7\xef\xc6\x22\xd6\x0f\x62\x1f\xb5\x7d\x3b\xbe\xb6\x67\x93\x4e\x58\x45\x63\x3f\x40\x67\xb6\xfe\xc2\xb4\x8b\x48\x22\x46\x3d\x2c\xfb\x09\x37\x92\x63\x11\x58\xf4\x41\x06\x16\xd2\x3b\x76\x03\x9b\x8c\x89\x32\x2b\x31\xb4\x2b\x37\x24\x1b\xa5\x09\x4c\x0c\xd2\x0a\x27\x81\xce\xb0\x8f\xbd\x54\x8f\xcd\xa4\xc4\x27\x0d\xdb\x54\xd8\x68\x06\xa4\x1b\x8b\x0c\x01\x1a\xa2\x16\x28\x78\xe1\x3d\xd1\xb2\x03\xbc\x9e\x49\x2f\x06\x86\x2c\x6d\xc8\x52\x54\xdf\x03\xe5\x44\x0b\x43\xf6\xc6\x98\xa5\x8c\x99\xef\x97\x2e\x64\xf2\xb7\x04\xca\xa5\xa1\x23\x23\x61\xfc\xee\x40\xa6\xba\x7e\xad\xb4\x82\xf5\x17\xbe\x59\x05\x2b\x29\x99\xb5\xf4\x69\x17\x43\xa1\xec\x2f\xe8\xf3\xa3\x97\xe7\x2f\xdc\x6a\xe3\x49\xe3\x17\x38\x92\x36\x7e\xa3\xf8\xc5\x36\xe4\xad\xef\x52\xcd\xe6\xc5\x26\xeb\xc6\x3a\xa3\xf9\xcd\x38\x75\x99\xac\x87\xdc\x90\x0d\x5e\xe3\xbb\x16\x97\x44\x26\x95\x0d\xd9\xa4\x17\xec\x89\xf9\xa4\x65\x45\x6d\xd7\xdf\x02\x2d\xd9\x8c\x57\x16\xf2\xca\x2a\xd7\x7c\xba\x86\x82\x03\xd2\x66\x7c\x17\x6f\xb9\x02\xd9\xb2\x75\x3b\x16\xb4\x93\x31\x6b\x40\xf6\x2c\xf5\x9d\x46\x25\xe3\xde\x35\xa3\x86\xca\xe8\x39\x66\xb2\xb2\xb4\xac\x33\xd3\x2e\xec\xfa\xd5\xc6\x2b\xf9\x43\xe3\x7a\xb1\x60\xb3\xc0\x08\xce\x3c\x8b\x25\xaa\xc8\x17\x3d\x1f\xb6\xc9\xe8\x50\x66\x62\x70\x30\xdf\xa2\x59\x64\x56\xf5\xc9\xd0\x1a\x23\x03\xee\xa3\x0d\x19\x97\x74\x46\x7b\x9d\x49\x06\xb4\xd9\x36\xbb\x40\xda\xe6\x8c\x15\x65\xcc\x97\xb3\xdd\x5f\x10\xf1\xc2\x02\xcc\xcc\xc7\xd4\x98\x12\x78\xf0\x6a\x8c\x38\xfd\x72\xcb\xb5\x9c\x23\xcc\x03\x94\x72\x9f\x0c\x92\x11\xdd\xfa\x64\x5d\x40\xb7\xe6\x0f\x0e\xf8\x64\xee\x9f\x34\xd0\x4c\xb9\x77\x0e\x41\x3e\x81\x62\x5d\x71\xbb\x90\x63\x1b\x8e\x42\x0a\xa6\x95\xac\xa5\x64\xb3\x4a\x46\xc9\x84\xc8\x90\xe4\xe6\xfa\x5f\x49\x62\xc1\xb5\x88\x5b\x66\x24\x8c\xbd\x8e\x87\xec\x1d\x44\x5f\xe4\xb4\xf4\xb7\xb6\x80\x97\x7c\xe7\xd9\xd7\xd3\x04\x29\x35\x67\x30\x17\x47\xaa\x60\xbd\x0b\xdf\xd0\x96\x32\x7e\x2b\x2b\xae\xc6\x8a\x93\x27\x61\x8a\x6f\x7b\x66\xea\x52\x9a\xe7\x9c\x6b\x2c\x97\xbd\xa9\xa6\x6d\xf1\x1f\x64\xc7\x9e\x1d\x89\xae\x7e\x73\x0d\xde\x30\x44\x1a\x45\x27\x87\x10\x63\x80\x7a\xa6\x30\x6b\xa2\x0f\x66\x1b\x43\xf1\xe5\xae\xab\x66\x87\x72\xd8\x47\x4c\xcd\xad\xca\x9f\x8e\x5d\x8c\x97\xe4\xe4\x8d\xcf\x19\xd4\xf6\x54\xc4\x70\x0d\x34\xa0\x9e\x9f\x7a\xbd\x09\x12\x91\x7a\x45\x77\x2e\x9e\xd9\xf2\xa1\xd6\x70\x67\xe1\xb2\x54\xb2\xf0\xe5\xb0\xb2\x32\x12\x45\xf0\x62\x6b\x23\xc9\x88\x6b\xfe\x0e\x26\x87\x48\x05\x13\xe4\xd9\x93\x85\x27\x2b\xb6\x30\xa8\x34\x43\xa6\x34\xee\x28\xd6\x77\x76\x16\x12\xb7\x1e\x77\xc1\xe9\x90\x2e\x4c\x29\x40\x92\x66\x7d\xa8\xd8\x81\x2a\x68\x56\xd9\xf0\x4c\xbd\x98\xdf\x31\xb2\x86\x68\xd1\x1b\x90\x9c\x9e\x04\xd9\xfb\x1f\xf9\x0d\x3b\xdd\xd2\x9e\x4f\x79\x46\x31\x55\x43\x61\xd5\xbd\x30\x46\x84\x27\xaa\x58\xa6\x16\x29\x8d\xd9\x96\xbe\x80\x0b\xc7\xa2\xf5\xfa\x07\x7c\xe2\x72\x9a\x82\xbb\xa3\xdc\x4b\x34\x2b\xac\xf0\xba\xe7\x43\x5b\x53\x31\x2f\x77\x44\x35\xd1\x15\xe8\x3b\x87\x6d\xcb\x4e\x6d\xd9\xf4\x3d\x25\xe4\xc0\xb4\x13\x7d\x8d\x3b\x31\x27\x5a\xbb\x1e\x01\x4c\x65\x11\x8d\xad\xf6\x60\x47\x2a\x43\x9a\xc1\x04\x66\x4a\x1d\x3f\x95\x45\x32\x35\x21\x73\xeb\x64\xca\x63\x8a\xa9\x86\x08\xb4\x91\x81\x8c\x88\x20\x75\x01\x65\x4c\xbb\xb3\x16\x3b\x9f\x6e\x6a\x61\xca\x9c\x24\xc6\x10\xc0\x6b\x93\x0c\xe7\xf0\x4d\x75\xe7\xe2\x5e\x5b\xfa\x56\xad\x7c\xb6\xb5\x7f\xb2\xb1\x79\x0a\xe4\xe4\x1b\x7f\x21\xba\xba\x86\x06\xa3\xca\xb7\x2d\xfa\x02\x12\x7a\x5b\x88\xec\xe5\x78\x5b\xac\x59\xff\x3b\xd1\x3b\x24\xf9\x9e\x1e\x65\xe1\xc3\x14\x85\x86\x59\x1d\x51\xf5\x73\x6f\x51\x55\x1d\x87\x7b\x0b\x8f\xc6\x32\x74\xf8\x0a\x0b\x75\xc4\x27\x8f\x44\x1a\xe3\xbc\xf7\x76\xae\x30\x3b\x97\x93\x34\xfe\x89\xee\x4a\x0b\x0b\x54\xc6\x4a\x96\x3e\xdb\xab\x7f\xb2\xf6\x4f\xf6\xbe\xd2\xb3\x6f\xff\xc5\xf5\x34\x48\x1c\x5b\x90\x8c\x30\x0d\xd1\x9d\x2d\xb8\xf5\xba\xa7\x6c\xdf\x8b\x9f\xda\x5a\x9a\x95\xa5\xbb\xad\xc2\x9b\xd9\x82\xf6\x88\x64\xed\x9f\xec\x59\xf9\x2d\x27\x2e\x8e\xee\x94\x6d\x28\x44\x09\x93\xc8\x62\x28\x10\xfb\x00\xaa\xd8\xf0\x9a\x95\xc5\x81\x56\xb5\x12\x0f\xed\x20\xbf\xcf\x30\x1e\x85\x1f\xf9\xc6\x77\xbd\x61\xa9\xd1\xf1\x2d\x10\x43\x06\x6a\x79\x6e\x06\xf2\xc6\xe2\x5b\xc4\xf1\x0a\x3f\x5d\x4b\x3e\x5d\xc9\x96\xe8\x86\xa4\x22\x7a\x33\x64\x42\xbd\x96\x61\x5e\x83\x6c\xf1\xbf\x67\x23\x72\xe1\xa8\xed\xa0\xb6\x04\x25\x43\xcc\xcd\x9e\xf5\x1d\xa0\x6a\x41\x8e\xec\xc8\x91\x19\x3e\x69\x95\xef\xa5\xd4\x78\xfc\x2b\x07\x19\x6e\xea\x2f\x74\x3b\xf0\xa4\x65\xe3\x2e\x36\x6e\x41\xb3\x7d\x81\xa9\x2d\x18\xef\x2c\xe8\x0b\x17\x54\x73\x82\xb4\x09\x66\xd6\x80\xd0\xab\xe0\x55\xa5\x44\xef\x40\x43\x1b\x4f\xf3\x91\x0b\x31\xb5\x5a\xf5\x24\x7a\x6b\x56\x70\x26\x33\x36\x05\xc9\xa5\xf2\x25\xc9\x84\x6f\x16\xdc\x78\x16\x3e\xca\x5a\x50\x77\x16\xbf\x29\xc5\xc2\x94\x62\xcc\x46\x89\x82\xea\x73\xa5\xad\x3d\x79\xef\xfa\x1b\x92\x7f\xfd\x93\x0b\x1b\x5a\x20\x64\x09\x34\x71\x95\xd8\x96\xfd\x41\xc3\xe6\xd2\xb6\xd2\xdc\x9e\x01\x89\xda\x41\x64\xbb\xf3\xa4\x60\x1e\x75\xda\x4a\x1f\x50\x7f\x30\x07\x28\x56\x12\x03\x53\xa5\x77\x64\x1f\x7e\x3b\x68\x2b\xa1\x84\x80\x34\xda\x04\x32\x81\x79\x45\x72\xcc\x70\x85\x40\x94\x3c\xfc\x2b\x65\x2f\x12\x8b\xcb\x59\x42\x4e\x3b\x5b\xc2\xb5\x04\xd2\xbd\x76\xc9\x75\x58\xfa\x4b\x17\x0f\x5c\xfa\x25\x83\x12\xa5\xf9\x23\xda\xd7\x96\x9a\xff\x81\x2b\x1b\xc9\x13\x96\xfd\x62\x1b\x8b\x9c\xd9\x2a\x16\xf5\xe8\xdf\x9e\xb3\xe9\x2d\xbd\xa6\xd2\x1c\x98\x41\x97\x24\xe0\x4b\x4e\xd4\xca\x27\xaf\xf8\xf6\x8a\x31\xeb\x92\x0a\xa2\xa4\xeb\x52\xd2\x65\xc7\xd6\x45\x9b\x19\xf7\xba\xa5\xc4\xcd\x75\x3c\xce\xcc\x7a\x46\x2c\x0f\x07\xfc\x3a\x21\x57\xff\xd2\x55\xdc\xd1\x89\x90\xb0\x8a\xa7\x3d\x1f\x60\x2e\x65\x69\x0e\xfd\xd9\x4d\xc9\x35\x5a\x72\x3d\x96\x8c\x28\x22\xc2\xf1\xdc\x43\xcc\x4d\x46\x07\x03\x92\xe4\x8c\x1c\x97\x8c\x33\x97\x7e\x0d\x96\x74\x5e\x80\xe2\xb6\xb9\xf4\x5e\x4b\x69\x5e\x0b\x66\xd3\x36\x0b\x7c\x52\xfb\x6c\x33\xeb\xa7\xf8\x2f\x44\x0b\xa2\x0b\xd1\xd5\x90\x39\x1a\x15\x37\xba\x15\x0f\xd2\x2a\xbb\x07\xf4\x82\x65\x5f\xf9\x2d\x93\x84\xe2\xa5\xc1\x15\x3b\x55\xc1\xb2\xf7\x34\x36\x6f\xc5\x8d\x30\xd0\x15\x17\x70\xc5\x1d\xcc\x23\x2d\xac\xb8\xe9\xe2\xc5\x54\xec\xd6\x23\x6f\x3d\x54\x22\x6d\x29\x0b\x6a\x10\x58\x02\x5a\x12\x5d\x81\xa2\x35\xab\xec\x2a\x83\x56\x11\x8f\x47\x2b\x9a\x0c\x41\xa6\xa8\x2b\x0a\x6f\x45\x3d\x00\xd4\xa2\x41\x6a\xe4\x1e\x29\x22\x38\xfd\xfd\x02\xb1\x12\x62\xea\xbf\xa2\x5a\xac\xc4\xb4\x5d\x0c\x59\x9a\x1e\xac\x01\x9d\x80\xf6\xac\xfd\xcd\xb7\x55\xaf\x2f\x08\x32\xdf\xb9\xa2\x09\xac\x44\x7b\xc4\x3e\x1f\x39\xba\x27\x66\xf8\xc9\x97\xce\xcc\x77\xe6\xd3\x0b\xd3\xd4\xcc\x55\xf4\x4e\x2b\x2c\x15\x24\x3f\xc2\xaf\x87\x0c\x56\x74\x5a\x2b\x2e\xa2\xca\x0d\x65\x10\xe9\x81\x27\xa9\x27\x23\x1b\xc9\x40\x26\xd4\x13\xd5\x6f\x3b\x6e\x3d\xa1\x74\xcd\x0e\x7c\xea\x4b\x8a\xe8\x81\xcd\xf9\x93\x57\xe7\x40\x66\x9e\xcc\x7d\x51\x8d\x7f\xc7\x8b\x8e\xee\x04\x33\xdf\xce\x8b\x3d\x89\x42\x25\x27\x4c\x28\xe3\x91\xea\xe2\xd1\x42\x5e\xb1\x17\xff\xf1\x2e\x21\x9e\xc7\x16\xfe\xc7\xef\x0f\xc1\xaf\x86\xc2\x7c\xbf\xd9\x3b\x1a\x68\xd6\xd7\xfe\xb2\x3b\x12\x03\xf2\x9c\xc6\x0d\xfc\xc5\x0f\xd6\x5f\x4e\x6c\x83\x0b\x91\x98\x58\x85\x3a\x66\x9c\xc1\x18\xd8\xa8\xa8\xa7\x2a\xaf\x97\x1e\x2d\x68\xf6\x27\x9f\xcc\x10\x68\x20\x5f\xb0\x11\x05\x07\xab\xa6\x6e\x01\xaa\x88\x82\xd1\x7c\xc2\x9d\xb2\x9e\x9e\xdb\x98\x06\x01\x19\x13\xa9\x15\x79\xf2\x07\xe3\x3c\xe8\x51\x3f\xaa\xb6\xfb\x24\x39\xc9\x23\xba\x5a\xeb\x26\xc5\x5e\x8b\x67\x71\x35\x22\xa2\x40\x7a\x27\xa6\xf6\x3e\x7d\xcd\x55\x50\x8b\xb2\xd2\xb4\x02\xfd\x78\xe2\x21\x49\x2d\xa4\x62\x86\x1a\xe1\x87\xda\x5f\xf4\xa8\xbd\x2e\x7a\xb2\x53\x95\x48\x56\xc8\xa3\x1a\xa8\x66\x64\xaa\xe6\xb5\x0b\x04\xe9\xb4\xbe\x3d\xcc\x50\x2d\xb2\x71\xc3\xca\x9f\xbc\x5e\x78\x92\x6d\xe8\x77\x28\xaa\x5a\x86\x4e\xbb\x7d\x64\xda\x07\xb4\x69\xcd\xf9\x7f\xe2\xba\xab\xc5\x8b\xd6\xfa\x2e\xd6\x39\x0b\x05\xd7\x3c\x81\xac\x65\xfd\xa2\xd5\xb8\xbf\x24\xce\x4c\x1d\x2c\xa4\x6c\x67\x6a\x59\x2e\x72\x99\xc5\x5e\xc8\x5c\x9f\xcd\x5c\xd6\xfe\x16\x62\xad\xae\xa4\xbc\x30\xf3\xfe\xfb\xcc\x3c\xc3\x96\x44\x9d\xc1\x28\x90\x33\x7f\x1c\x37\xe3\xc1\xca\xcc\xbc\xb8\x31\x5f\xc8\xb8\x6f\x9f\x21\x16\x4e\x94\x12\xe1\x84\x34\x65\xb6\x29\x51\xc1\x72\x6b\x56\xac\xda\x05\x68\x0a\xf4\x42\xfb\x37\x33\x0d\xa3\xc6\xff\xab\xf0\xf8\x24\x96\xfd\x42\x17\x70\xa6\x07\x72\xb2\xcc\x21\xb0\x33\x31\x66\x7f\xf3\xcd\x96\x61\x37\x90\x6f\xbe\x98\x1f\xfe\xc9\x3b\xd1\xc9\x25\x9b\x5a\x07\x19\xb1\x5e\xbd\x6f\x37\x13\xd1\xd3\x57\xf7\x50\x4e\x33\x89\xf2\x66\x40\x9f\xd8\xc4\xcd\x28\x28\x33\xda\x95\x19\x97\xc0\xcc\xdf\x96\x9b\x49\x35\xc7\x1e\x66\x1c\xb1\x0e\x24\x17\x56\x82\x06\x81\x22\x19\x13\x65\x50\xb2\x20\xf1\x3d\x15\x04\x94\x78\xcf\xe4\xd2\x17\x12\x34\x2c\x49\xed\x9f\xcc\x3c\xf9\x9b\xa8\xf1\x35\x44\x73\x31\xf3\xb1\xa1\x99\x8f\x0d\x81\x68\xb4\x0d\x64\x6b\x63\x1d\xc8\x0f\xbc\x83\x56\x9e\x88\xfe\x75\x6f\xab\x1c\x22\x4a\xe4\x8e\x2b\x90\x94\xb8\xd2\x6c\x9b\x09\x92\xfa\x32\x54\xfe\xbf\xc2\xed\x23\x1a\x51\xf8\x66\x7e\x2f\x06\x12\x9a\x3c\xe7\x6c\xcc\x4d\xff\xde\x61\x06\xc1\xb7\x3d\xbd\xbc\xaa\xc7\xa0\xf1\x8c\x62\xce\xc3\x11\xa0\x7b\x22\x35\x7c\x20\xcf\x9e\xac\x3d\x79\x37\x24\xdd\x26\x19\x01\xc5\x2b\x46\x73\xc6\xba\xe6\xbc\xc9\x31\xe7\x8d\xa1\x39\x57\xe6\xdc\x42\x23\x9a\xf5\x81\x59\x2b\x98\xa0\x39\xa7\x7d\x4e\x23\x31\x97\xbf\xdb\x1e\x63\x2a\xec\x7c\xcb\x52\x5b\xdf\x80\x17\x6a\x14\x3c\xf9\xe2\x07\xe4\x05\x71\x5c\x92\xc2\x3f\x99\xf9\x32\x56\x40\x2b\xde\xfa\x03\xf9\x2f\x26\x6f\x2e\xab\x71\xc8\xb6\xac\x71\x70\x32\x17\xe7\xef\x13\xe8\x93\xd3\xf6\xc9\xa9\xbc\xb0\xf2\x8b\xbd\x1b\x3c\xba\xdc\x50\x58\x86\x43\x90\x3e\x33\x24\xf8\x0f\x22\x97\x56\xfb\x5f\x7b\x76\xa1\x46\xef\x81\xce\x79\xdc\x31\xf7\xf1\x85\xb9\x3f\x65\x07\x79\xf0\xa4\xb2\xf6\xc8\x2a\x63\x43\x7e\x59\x5b\x7f\x23\xaa\x40\x74\xb2\x61\x72\x31\xd4\x86\x1b\x18\x1c\x46\x0d\x98\x3c\xa0\xb2\x6e\x7c\x48\x01\x44\x4d\xc1\x33\xae\x9d\xa0\xfa\x86\x37\x4f\x80\x6e\x91\xe7\x97\x53\xea\x86\x91\x06\x20\xed\xd3\x73\xe7\x2e\x8c\x63\x35\x3f\xdb\x4d\x94\x58\xa0\x9e\x4d\x83\xcc\x7d\x0b\x1a\xdf\x85\x38\x00\x3c\x5f\x8b\x75\xbc\x32\x50\x88\x87\x6b\xff\xe6\xd6\x57\xb0\xf3\x65\xe8\x86\x01\x65\x1c\x7e\xab\xe0\xe8\xc9\x4f\xdf\xd1\x33\xd1\x45\x03\x81\xb2\x5c\x90\x74\x95\x79\xb8\x35\x2e\xca\x0a\xa8\xef\xca\x48\xfc\x98\x9a\x32\x02\xb9\x21\x1a\x31\x0c\x01\x3e\x26\xca\x59\x54\x0a\x01\x8d\x91\xcc\x46\xa6\xb1\x36\x14\xd3\x2c\xfa\xd5\x50\x1a\x81\xb6\x40\x19\x64\xaa\xb1\x73\x51\x2d\xbf\x60\x03\x0a\xdf\xe8\x92\x25\x54\x3c\x68\x7a\xd6\x6d\x81\x98\xb0\xc6\x7b\x88\x8d\x39\x84\x39\xf9\x1c\x9f\xda\xf4\xf4\x43\x18\xfb\xae\xa5\xa1\x49\x69\xa4\xc0\x8a\xf5\xe8\x86\xb6\xc1\x15\x7d\x8c\xf8\xb3\x79\x0f\x03\x92\xe8\x3d\x80\x17\x44\x15\x4f\xfd\x9e\xed\xf2\xaf\x16\xbd\x64\xab\x56\x7e\x18\xd7\x52\x4f\x03\xb2\xe1\x88\x7c\xe7\x20\xe0\x16\x82\xb6\x6a\x4f\x29\x3b\x31\xeb\x07\xcb\xfa\x64\xf7\x2e\xd0\xfc\x0d\x55\xce\xb3\x28\x1a\xe4\x13\x57\xc3\xca\x0f\xa4\xee\xf9\x0f\x5e\x1a\xee\x51\x1a\x5c\x9c\xb7\x2e\x24\x6c\xb5\x1d\xd0\x35\x7a\xef\x57\x76\xb5\x30\x46\x96\x1a\xc5\x3c\xa1\x7c\x24\x63\xa8\xd8\xc6\x89\x49\x02\x0b\xa6\xc9\xd1\x2b\x6d\x64\x1e\xff\x60\xce\x67\xf3\x51\xb4\x61\x05\x5b\x55\x70\x5f\xdb\xd0\x47\x69\x18\x62\x6d\x54\x19\xba\x0c\xf7\x44\xa5\x4f\xa6\x0a\x79\x67\x75\x33\x5f\xc9\xdc\x44\xc6\x9d\x17\x3f\x33\xdc\xd3\x78\x67\xa4\xf1\xce\x08\xf2\xac\x99\xbc\x31\x41\x86\x5b\xe2\x3a\x44\xb5\x91\xc8\x67\x03\x2e\xdb\xa7\x7f\x72\x71\xef\x98\xdb\xf8\x6c\x8e\x44\x4b\x92\x11\x85\x66\x2f\xa8\xac\x17\xdc\xf3\x2d\x28\x07\x0b\x3b\xbf\xd6\x0c\x43\x66\x18\x33\x6d\x0c\xad\xb1\xf0\xa7\x57\x0b\xee\xd5\x17\x76\xce\xfd\x64\xc4\x92\x75\x71\x2f\x7c\xf9\x15\xab\xad\xbc\xb0\x2c\x38\xe4\x0b\x6a\xe9\x05\x07\x7b\xc1\x88\xeb\x42\xbf\xb1\x49\x34\x39\x1e\xfa\x2e\xb8\x81\x5b\x30\x70\xb4\xe0\x72\x12\x24\xbe\xcc\x82\xa3\xbd\xf0\x4a\x79\x81\xa0\x0d\xdd\x82\x05\xf7\x62\x0b\x19\xf7\x06\x48\x6f\xee\x00\xbd\x62\xa8\x17\xb6\xae\x5e\x7b\xfc\x22\xd0\x8e\x5b\x3e\x7a\x8c\x78\x5b\x57\x92\xd4\xab\xde\x85\xc9\x5e\x45\x82\x08\x35\x87\xd1\xbe\x55\x03\xba\xf6\x34\xca\x66\x77\x13\x17\xbf\x0e\x63\x58\x69\xda\x8e\xdc\xe6\xdf\x89\xed\x42\x9d\x58\xa9\xbb\xe5\x66\xbf\x35\x83\xb8\x00\x49\x99\x9c\xfa\x9b\x00\xad\x1e\x06\x4a\xcb\x5a\xdc\xd5\xef\xf9\xef\x06\x05\xd9\xc2\x6d\x79\x2d\xa4\xe5\x65\xe5\x16\x27\xdf\x86\x2c\xed\x9e\xaf\x47\x4b\xd3\x06\xf7\xcb\xda\xa9\xe1\x43\x41\x62\xf3\x5a\x09\x60\xf7\x99\x75\xcd\xb8\x7f\xcb\x73\xf7\x56\x56\xd9\x7f\x59\xdf\x8e\x19\x4e\xd0\x62\xf8\xa6\x31\x7e\xda\xd0\x52\x6b\xb6\x32\xc1\x59\xcf\x36\x68\x8d\x65\xb0\xef\x8c\x80\x90\xd5\x8e\x91\x5a\x19\xfd\x4f\xa2\xab\x35\x5f\x4f\x8a\x76\x24\xa1\x84\x25\xa3\x32\x40\x4b\xa2\x2b\x50\xfc\xb2\x6f\xc9\x89\x5a\x72\xe1\x2e\xd5\x43\x92\x9a\x97\x76\x51\x37\x27\xd1\x2b\x29\x4b\x1e\x9d\x2c\xfd\xc1\xcc\xd2\x7b\x40\x4b\x4a\xef\xd2\x3c\x9a\x98\x1c\x97\xc8\xd2\xbb\x2a\x20\x9f\x7c\xa2\xb1\xe8\x25\xef\xa3\x83\x64\x54\x86\x4b\x91\x86\xa0\x61\xbf\xe9\x29\x61\x5f\xcb\xf9\xe5\xa0\x06\xfc\x0e\xa8\xe6\x48\xcd\xf9\x74\xc1\x4d\xc7\xd2\x7b\x6d\x4b\x7f\xcc\xb2\x34\xe9\xc9\x50\x5d\xd8\x88\x33\xf9\xd3\xbd\x20\x6a\xe4\x9b\x68\x89\x31\x3c\x9d\x25\x55\x06\xd0\x2d\xeb\xda\xc9\x58\xdc\xf4\xec\x33\x57\x4d\x3e\xe1\xf2\x11\xc8\x11\xa1\xa1\x25\x8e\x47\x58\xce\x99\x63\x76\x61\x2d\x17\x19\x9c\x27\xce\xcd\x15\x01\x7a\x23\xc1\xfe\x62\x14\xcc\xe4\x2e\x45\xcb\xbf\x03\xe5\x88\x6f\x00\x35\x28\xe4\x9b\x37\x94\x4b\x7f\x00\xb2\xf4\x9b\x84\x25\x2d\xe4\x92\xbe\xe4\xd2\xdb\x4a\x90\x7b\x1b\x4a\xb7\x8b\x07\xa9\x88\xf4\xe8\xe0\x1b\x6d\xe1\xd2\x6c\x61\x2c\x9e\xd3\xef\x2e\x6d\x80\xfc\xcf\x46\xd3\xec\x1c\x4f\x20\x96\x66\xe0\xd8\x13\x0d\x04\x69\x17\xbe\xd9\x66\x5a\x95\xe8\x37\x1a\xbb\x57\x1a\x3b\x1c\x86\x4d\x90\x16\x6f\x61\xac\x7e\xbb\x85\x81\x87\xb7\x7c\x52\x19\x92\x83\xe7\x9e\x9e\x9e\x59\x89\xfa\x9d\xf1\x8a\xb7\x84\x57\x74\x87\x57\x74\x87\x57\x6c\xe7\x8a\xdf\x1a\xac\xec\x1a\xf1\x88\x44\xc5\x63\x85\xeb\x8e\x44\xf1\x4c\x18\x7c\xc9\x76\xe7\x38\xe9\x05\xd2\x23\xb9\x15\x55\xc0\x8a\xfa\x74\x05\x67\x1a\xa8\x64\x8b\x11\x91\x8e\xc3\x30\x67\x2d\x0d\xd3\x16\xbe\xf2\x5f\xae\xa9\x83\xe7\xcc\xd9\x32\x5c\x08\xb2\xf1\x39\x5f\x7d\x5b\x56\xb2\x74\x86\xe4\x6b\xb6\x77\xfd\x6b\xb2\x8d\xcd\x8e\x17\x9b\xe3\x55\xab\x57\x59\x68\xba\x37\x5f\xd1\x36\xaf\xa8\xb0\xa3\x31\x58\xe9\xc5\x59\x11\xc8\x15\xd5\xf4\xab\x0f\x59\xaf\x64\x55\xb1\x72\x15\xad\x16\xd9\x0a\x86\x6b\xd7\xfe\x02\xe0\xda\x7f\x0c\xb1\xf6\x47\xde\x20\x35\x91\xba\x10\x6b\xbf\xe5\x5c\x53\x50\xd6\x54\x60\x6b\xdc\xf9\x04\xd2\x30\xcf\x9a\x97\x71\x40\x4a\x2c\xf4\xb5\xac\x72\x68\x4e\x2d\xfb\x85\x6b\x6b\x0d\x55\x26\xeb\xf1\x0a\x8e\xea\x2a\x90\x0d\x8f\xfb\x84\x98\x29\x02\xd1\xae\xe9\x95\x98\x35\x75\xd8\x5a\x8f\x99\x45\x48\xd7\xd4\x5c\x40\x5a\xcb\xd5\xb2\x86\xb1\xbf\xb1\x12\x6c\x22\xd6\xf2\xe9\xcb\x1f\x40\x37\xd6\xd4\x80\xde\x89\x4e\x40\x13\xbe\x81\x2b\x3e\xef\x24\x7a\x7d\x7e\x23\xeb\x3a\x05\x1a\xf0\xe7\x15\x36\x3c\xa7\xdc\x70\x99\x6e\xb8\xfc\x36\x92\x6f\x09\xa4\x1b\xd0\x8d\x7d\xa6\x79\x25\xd1\x2b\x4c\x1b\xce\xc1\x86\x47\xc6\xdc\x01\x20\x55\x9d\xd7\x8d\xc5\x53\x77\x20\x0b\xef\x23\x09\x77\xa2\xb6\xe1\x4d\x00\xa0\x8c\x68\xca\x56\xc6\xd0\xd4\xc6\x7f\x00\xb2\x71\x1f\x80\xe4\xe4\xb5\xcf\x39\xf3\x05\x2e\x59\xe0\x9a\x79\xce\x2c\x4a\x43\x47\x1b\x6e\xf2\x36\x32\x3f\x18\x5d\xf3\x50\x2d\x77\xf2\xcb\xc7\x46\x1b\x9d\x17\xcb\x5c\x58\x45\xb6\xeb\xda\xd0\xa6\x6c\x7c\x30\x78\x63\x51\xa7\xf8\xe4\xc9\x5a\x96\xc4\x7b\x7f\x1b\xef\xa1\x6e\x68\x4c\x36\x7e\x63\xb5\xd1\x1d\x94\x0e\x84\xd8\x0f\xa2\x8b\x6b\x99\x08\xdc\xc6\xef\x90\x36\x3e\x22\xfb\x1d\x47\xe9\xd0\xed\xdf\xa9\x9f\xd5\xd2\xf3\x56\xc4\x77\x46\xa2\xbe\x8b\xd6\x53\xaf\xef\x3b\x0f\x98\xbe\x63\x45\x60\x8e\xbf\xe3\x47\x28\x80\x6e\xac\x44\x8d\xab\x69\xbc\x60\xcb\xe3\xb8\x2d\x97\xd5\x96\x71\x97\x2d\x2f\xff\x6e\xa5\xe6\x59\xcf\xae\x55\xeb\xb0\x6c\x79\x53\x05\xf7\xb6\xbe\x1a\x92\xd6\x6c\xe9\x35\x6d\xed\xc0\xac\x06\x99\x33\x4c\xb0\x65\xf0\x77\xcb\x0b\xb5\x5b\x93\xb0\x98\xac\xdf\x31\x6d\x19\xc4\x80\x77\x86\xa4\x13\x37\xc3\x5b\x2a\x8a\x2d\x5d\xaa\xad\x88\xdb\x48\xbc\xa3\x33\xc6\x63\xcb\xaf\x55\xb7\xfa\x91\xb8\x28\xa5\xad\xe8\x8e\x6b\x4f\x7f\x4b\x40\xdb\x12\x10\xbb\x9b\xe8\xcf\xa0\x6c\xa9\x3b\xb6\xf2\xfa\x03\x10\x9c\x9b\x11\xc9\xc8\x0a\x4e\xe2\x85\xef\xad\x85\xc8\x23\xb9\x25\x8a\xe5\xc4\xf7\xfc\x6c\xc9\xc5\x14\xa2\x7f\x88\xf4\x76\xe9\xd6\x6f\xc8\xb7\xce\x1f\x49\xc9\x55\xcb\xef\xb8\x39\xde\x49\x33\xff\x0b\xdb\xb6\xe3\x4d\xa6\x9d\x7d\x9e\x72\x05\x29\x64\xc4\x47\x24\xb5\x21\x99\xc6\x1d\xcf\x8e\x77\x8c\xe1\x0a\x12\x41\xd8\x59\x10\x28\x05\x59\xf0\xa2\xce\x8e\xa7\x5d\x3b\x5a\xd5\x1d\x6e\x38\x00\x7d\xb0\xd4\x4f\xa2\xf8\x3b\x2b\x3b\x5e\xa5\xdb\xd9\xaf\x01\x7c\x27\xd9\xc2\x28\xed\xfc\x3d\xf5\x9d\x7d\xca\x90\x81\x68\x88\x68\x47\x4d\xf1\x46\x57\x6d\xcf\x43\x8f\x37\xbd\x05\x23\x59\xdf\xb8\xeb\x79\xe3\xfd\x97\xbd\x8f\x0b\x83\xdc\x13\x55\x3e\xb9\x66\xd9\xd1\x22\xef\xbd\x45\x06\x59\xb0\xf8\x37\xf7\x82\xc5\x53\xf6\x74\x12\xf6\x74\xef\xf6\xb4\x2f\xf1\xd2\xc8\x9e\xd7\xc4\xf6\x74\xe2\x40\x62\x53\xf5\xc0\x69\x8f\xcb\x51\x86\xec\x69\x85\x8e\xbc\xd1\xa9\x90\x34\x2b\x52\x67\xfc\x87\x9e\xaa\xd8\x4b\x73\xa2\x86\x28\x06\x29\xf6\xfe\x42\xda\xde\x9f\x84\xee\xb9\x39\xda\x9b\x9b\x37\x22\xc9\xf9\xf6\x8b\x6f\x7e\xb4\x51\x7b\x6f\xa3\xf6\x5e\x83\xec\x4d\x69\xc4\x02\xa2\x47\xb9\x57\x1b\xe5\x72\xfe\xc3\x15\xb3\xf7\x3f\x4f\xb2\xe7\x1d\x7a\xa0\x77\x20\x31\xec\x22\xe5\x7b\x9c\x48\x63\xe9\xee\xa5\xc3\x13\xeb\x4f\x50\x22\x63\x2b\xc7\xf6\x10\x7b\x91\xde\x01\x11\xde\x33\xc5\xb2\xc7\x69\x4a\xd7\xff\xd3\x1a\x67\x3f\xd8\xb1\xa7\xad\x03\x1a\x7a\xc2\x91\x55\x57\x21\x27\x89\xa7\x72\x6f\xd0\x3a\x36\xe1\x89\xba\x6f\x7b\x6f\x5d\xf7\x7e\x2f\x05\xa2\x8a\xfa\x07\x6d\x21\x50\xcb\x0c\x4b\xdf\x90\x15\x3b\x14\x43\x89\x20\x3f\x88\x4e\xbe\xb1\xff\xe7\xc9\x27\x0f\x0e\xf7\xde\x6a\xee\x3b\x77\x63\x0d\x44\x35\xe9\x81\xf6\xeb\xc0\xd3\x9e\x03\x17\xca\x81\x63\x71\xe0\xf2\x38\x70\x79\x1c\xa8\x9c\x0f\xdc\xf7\x1c\x78\x4a\x77\x30\xe7\x37\x23\xd1\x82\x4a\x66\x2d\x65\xad\x9c\x58\xb0\xca\xe1\xbb\xfb\x6c\x31\xd6\xa0\x6b\xe9\x20\xeb\x66\x6c\x48\x64\xe8\x20\x8b\xe6\x0f\xd6\xf5\xcc\x12\x1b\x36\xb5\x85\x9b\x70\x30\xe9\xaf\x48\x2a\x66\x40\xad\x07\x56\xf9\x02\xc9\x3d\xf8\x2d\xd2\x3f\xf6\x03\x3d\x23\x92\x05\xab\x6b\xe9\x9b\x1c\x38\xaf\x07\x99\xd4\x7b\x88\xcd\xc1\xbc\xee\x96\xef\xac\x59\xdd\x96\x8d\xdd\x33\xed\x9d\xc3\x16\x83\x37\x07\xee\x99\x0e\xf6\x6b\x2d\x23\x12\x7d\xef\x6a\xb3\x60\x32\x00\xf4\x68\xdd\x0d\x2b\x67\x4a\x84\x5e\x5a\xdb\xdf\x2d\x8e\x89\xe1\xd4\x1f\x13\x59\x93\xa0\x41\x76\xbd\xe1\xe0\xad\xe5\x81\xdf\x73\x09\x72\x1b\x99\x03\x8d\xe8\x41\x96\x68\x44\x29\x51\x66\x28\x89\x95\x17\x4e\x06\xf5\x44\xb4\x25\x29\xac\xbf\xee\x46\xc2\xc1\xbb\xa3\xff\x70\xd5\x21\xf9\x87\x49\x98\x8b\xc7\x1f\x19\x4a\x3f\xea\xa1\xa7\xbc\x70\xf4\xdf\x74\x1c\xfd\xed\xa7\xff\xd9\xd7\x87\x19\x0b\x48\xb9\x81\x03\x39\x02\xe9\x3a\x3a\x52\xc1\x1c\x69\x70\x8e\xf4\x66\x8e\xb2\x7a\x1e\xd0\xaf\xa3\xfe\x52\x97\x05\xa2\x8e\x54\xd5\x47\xae\x9c\xa3\x2c\x9b\x2f\x40\x8f\x18\xde\x23\xae\x17\x01\xcd\x98\x6f\x06\x37\xe9\x48\x5f\xef\xa4\x47\x54\x42\x8e\x34\x36\x47\x1f\x7f\x3b\xf2\x84\xfe\xc8\x5f\xb0\x3a\x9a\xcd\x69\x49\x32\xa2\x82\x65\xbf\xf2\xbd\x15\xbb\xbe\x62\x15\x3b\x3e\xdd\xb3\x85\x07\x5f\xed\x4f\x66\xbd\x10\x5d\x0d\x99\x01\x38\xf2\x7c\xf4\x48\x91\x3d\x8a\x38\x16\x86\xb4\xea\x84\x63\x0d\x1f\x53\x9a\x7c\xd2\x53\x2e\x6d\xb2\x79\x92\xc7\xce\x9d\xaa\x9f\xec\xe0\x28\xe3\x13\x15\x28\x3c\x51\xe3\x86\x53\x06\x15\x9e\x9f\x3e\xca\xfb\xd3\x76\xb6\x03\x92\x8c\xe8\xce\xe7\x29\x7c\x51\x25\x91\xda\x93\x9f\xfe\xdc\x1b\x64\x4e\xa4\xc7\x9f\x3f\x3b\xf7\xab\x0b\x3f\xfd\x39\xf6\xcf\xce\x7e\x34\xe1\xa7\xf8\xa5\x13\x20\xdd\x68\x7c\xe8\x06\x5c\xe4\xec\x43\x37\xc5\xba\xf2\x91\xd3\xf6\x3f\x3f\xbd\x27\xfe\xf1\x9b\x59\xfc\xb0\x10\x63\xc5\x9c\xa5\xf5\xdb\xed\x05\x3f\x3a\xfb\x22\xeb\xcc\x21\x3b\xd3\x17\x84\xe1\xd2\xcd\xc9\xd9\x3e\xa0\xca\x49\x74\xf4\xcf\xfe\xa3\xa5\xb3\x7e\xa7\x64\x45\xc5\xef\x94\xce\x5c\x79\x67\xce\xc8\x99\x1d\x38\xfb\xd6\x7f\x72\x19\x9e\xb9\xe6\xce\xd4\x32\x67\x7a\x4d\x67\xce\xd4\x99\xee\xfb\x99\x87\xce\x67\x4a\xce\x99\x7a\xe8\xdc\xb9\xaf\x26\xcf\x5c\x94\x67\x5c\xff\x21\xd2\x3e\xea\x75\xec\x33\x4d\xd6\xbf\xf8\x59\x39\xdf\xa8\x5f\x3e\x37\x00\x2f\x89\x1a\xb6\x73\xc5\xfd\xce\x99\xf1\x9b\x33\x9d\x9f\x33\x9d\x76\xa0\x29\x11\x7b\xe0\xae\x43\x21\x6c\xb4\x81\x46\x8c\xdf\xfb\x00\xa9\x27\x7b\xe1\x71\xcd\x85\xb1\xc2\x0b\xbe\x56\x02\xd2\xe3\x8b\x8b\x18\xd8\x7e\x4f\xbf\x15\xb2\xf2\xbf\xf2\x0d\xb5\x89\x17\x44\x00\x81\xd6\xf0\xb4\x2f\xb2\x4b\x9f\x02\x6d\xf9\xae\x4a\xc2\x85\x91\xc1\x8b\x98\x8e\x3b\xa0\x21\x9f\x66\xfc\xac\xe0\xc2\x1f\x7e\x8c\x86\x33\xfe\xe0\xd9\x05\xba\x81\x28\xb3\x96\xbb\x4b\x36\x17\x8b\x7e\x87\x17\xae\xbc\x87\x71\xa5\xe1\xb8\x52\xfa\xae\xd4\x33\x57\x04\xa0\x0c\xc9\x54\x5d\x29\x5c\x57\x5a\xb2\xab\xfd\xe2\xc3\x00\xa4\xf6\x28\x96\x3a\x23\x7a\x61\x3b\x5a\x3a\x66\x57\x7f\x22\x77\xa5\x23\x72\xf5\x91\xd5\xab\x74\x61\x45\x84\x06\x96\xcc\x29\x5b\x75\xcb\xa9\x7a\xfb\xea\x77\xba\x57\xc6\xa3\xae\xdc\xdf\xc7\xa3\x8e\x2b\x2f\xdb\x5f\x7d\x70\xff\xca\xaf\x94\xae\x8c\x37\x5d\xdd\xe0\x4a\xfc\x40\x92\x03\xc2\x85\x23\xa0\x50\x93\x6e\x07\x06\x3d\xb7\x31\x50\x34\x24\xaa\x7a\xf6\x9d\x19\xbe\x94\x8c\x77\xf0\x03\xba\x63\x41\xa5\xed\x8d\x71\x2f\x3f\xfe\x7a\xaa\xf2\x37\xa0\x47\xfb\xcd\x46\xbd\xbe\xaf\x0d\xaa\x59\x79\x2d\x66\x47\xd1\xc9\x50\x10\xdf\x80\x66\xac\x62\xc6\x52\xb8\x8d\x0a\x84\x3f\x6e\x14\xc8\xce\x92\xc3\x30\x5e\x81\x86\x4c\xbb\xb1\x2f\xb6\x71\xdb\x4c\x55\x4b\x20\xd0\x60\x7a\x72\x9d\x78\x92\x7a\x32\xf4\x04\x4e\x95\xdd\x22\xb1\x19\x52\x0e\x39\x50\x52\x11\x41\x0b\x2b\x41\xf0\x04\x44\x5d\x3b\x25\x39\x8b\xba\x75\xbf\x60\x17\xf8\x83\xc8\x8e\xdc\x7d\x96\xd5\x10\xd0\x93\xbb\x78\x1d\xf8\x33\xcb\xbd\x58\x9a\xba\xa8\x7a\x87\x13\x97\x56\x95\xc0\x46\x2b\x81\xf7\xa1\x3f\x2c\xa9\xdf\xe3\xa0\xee\x84\x1f\xc5\xda\xa2\x0b\x49\x43\x3e\x44\x2c\x4b\x11\xce\xbc\x40\x62\xf4\x57\x7f\x12\x2a\xe3\xdb\xaf\xf6\xb6\xee\x3d\x13\xfc\xb0\x6b\x4e\x84\x13\xb0\x64\x60\x97\x1c\x92\x01\x45\x31\x8e\xf1\xc0\xb6\x41\x4a\x6a\x8f\xe8\x63\x46\x47\x3a\x19\x50\xaa\xe2\x8c\xf0\xfc\x37\x19\xd8\x6f\x05\x24\x03\xbb\x85\xa3\xe8\x87\x28\xbb\x64\x60\x3f\xdb\x9b\x0c\x4c\x19\x24\xb8\x64\x56\xb8\x66\xe8\x31\x78\x82\x0b\x64\x37\x5c\x77\xa9\xed\x0b\x14\xbd\x3b\x67\x20\x67\xea\x87\x21\xdd\x7c\x24\xa9\x59\xd4\x24\x75\xb7\xab\x12\xba\xd4\x09\x4d\x7c\x82\xef\x9d\xc7\x40\x0c\xe2\x05\xf2\x0d\x8d\x4d\xdd\x01\x55\x82\x26\x20\x83\x6a\x9c\x84\xbf\x49\xa8\x73\x37\x20\x8a\x69\x3c\x0c\x53\xfe\x48\x54\x13\xf1\x06\x4d\xbc\xb9\x19\x7f\x78\x34\x19\x9a\xe3\x90\xd8\x4f\x03\x5a\x45\xb9\xed\x2c\x02\x99\x32\xf9\xde\x37\xab\xe4\xab\x95\x6f\xc9\xdc\xa3\x1c\xe8\x85\xed\x5e\xb2\xac\x57\x9c\x9f\x31\x0f\xfc\xbd\x64\x68\x76\x3b\xa0\xd4\xca\x4a\x32\x0b\x58\x29\xd1\x59\x46\xe4\x2f\x05\xca\x2d\xec\xa2\xe4\x9e\x08\xd6\x5b\xc9\x73\x4f\x57\x6b\xc2\xcf\x69\xf4\x0b\x18\x45\xaa\xc7\x6f\x28\x90\x37\xec\xc1\x8d\x85\xe2\xe4\xaa\x2c\x2a\x1b\x51\xb2\x46\xee\xf7\x90\x94\xcc\x98\x3b\xb7\x1f\x88\x51\xa2\xc9\x53\xa6\xc1\x37\x0b\x68\xc6\xe2\xe6\x4c\x9b\xb3\xd4\x25\xdf\xd8\x1a\xb2\x81\x1a\xd9\xc1\xc9\xc4\x72\x9b\xee\x1d\xf1\xc7\x76\x48\xc6\x7c\xfb\x2f\xfd\x39\x16\xb1\x35\xe0\x6c\x4c\x32\x62\x51\x13\xeb\xaf\x29\x10\x1c\xca\x84\x61\x1e\xbb\xdb\x1f\xc9\xd8\xeb\x5f\x90\x47\x22\x55\x76\x63\xfb\x60\xa5\x10\x82\x0b\x44\xfa\x3b\x5d\xc9\xa4\x8b\x5f\x66\x28\xf9\x42\xa4\x83\x03\x82\x1f\x71\x8b\xd9\xb0\x81\x55\xf2\x49\x92\x41\x35\x4e\xf4\x47\x49\xb4\x00\xbd\x9e\x10\xc9\xd4\x93\xc2\xaa\x8f\xbb\x01\x25\x51\xdc\x27\xde\xee\x4f\x34\x42\x25\x24\xe3\x62\xcd\xec\xfa\xbb\x22\x7c\x53\xab\x64\xce\xdc\xb9\xf8\x6c\x2a\xe7\x2d\xd0\xa3\xcc\xd8\x4d\x4f\x25\xde\x54\x4e\x46\x61\xcd\x28\x0d\x99\x6d\x28\x13\xfe\x36\x52\x82\x5f\x37\xfa\x42\xf4\x83\xe8\xc4\xac\xd8\xcf\xe0\xc7\x7f\x45\x6f\xe0\x27\x87\xfa\x44\x88\xb2\x2b\xd1\xc5\x9f\x9b\xa3\x9d\xc8\x0f\xb3\xc8\x4f\x6a\x83\xd4\xee\x57\x88\x55\xeb\xa6\xbd\xf8\x31\xfa\xff\x07\x00\x00\xff\xff\xaa\x0a\xcc\xb8\xdf\x5e\x00\x00") +var _keysWordsWordlistJapaneseTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x5c\xff\x72\xe2\xb8\xd2\xfd\x9f\xa7\x5e\xbc\x5c\x2f\x01\x3c\x0e\x71\x1c\xc7\x61\x58\x87\x8a\x2f\x43\x60\x80\x0c\x59\xb8\x93\x8f\x2c\x3c\x8c\x5f\xe4\x2b\xf5\xe9\x3e\xea\x99\xaa\x54\xea\x1c\x59\xd6\xcf\x56\x77\xab\x25\xd3\xf5\x93\xae\x3f\xe8\xfa\x45\xd7\xcf\xbb\x7e\xd5\x25\x45\xcf\x92\xca\xae\xdf\x92\x3c\x03\x8d\xba\xfe\xdf\x5d\x72\x03\x32\xee\xfa\x8b\x2e\xf9\x93\xef\x64\x5d\x32\x06\x9a\x76\xfd\x49\xd7\x6f\x8c\x58\x72\x11\x92\x93\x09\x79\xd9\xf5\x07\x44\x07\xa0\x4a\xfe\xaf\x40\x1e\xbb\x24\xef\xfa\x29\xc8\x53\xa8\xd1\x5e\x7d\xea\xfa\x19\xd0\xbc\xeb\x9f\x80\x9a\xae\x3f\x64\x86\x26\xfc\x25\x7d\xc7\x93\x51\xd7\xbf\x74\xfd\x21\xb9\x3e\x69\xd9\x8a\x56\xfa\xa4\xd5\xbd\xc8\x70\xfc\xa7\xeb\xe7\x7c\x78\xe9\x92\x91\x11\x57\xf4\xb2\xeb\xaf\x89\xf6\x92\x4d\x9f\x1c\x88\x4e\x1c\xb5\x13\xd3\x8e\x7e\x2c\x2e\x6c\xc5\xa5\xeb\xbf\x1a\x4a\x06\xd2\xa4\x9a\x5c\xeb\xbf\x76\x49\xd2\xf5\x77\x42\x42\x4b\x46\x5d\x1f\xe5\x84\x17\x58\x7f\x92\x76\xc9\x1f\x40\x37\x32\x8b\xb7\x5d\xff\x42\x5e\x11\xd5\x5d\xff\x91\xc4\x8f\x5a\x72\x23\x65\x44\x92\x5b\x5b\x42\x8d\x93\xae\xbf\xb2\xe1\x0a\x4f\x66\xcc\x99\x87\xa1\x30\x52\x58\xcf\x12\x99\x7f\x47\x0a\xa2\xaf\x26\x44\x81\x2c\x7d\x9e\xb5\x27\x3a\x00\x03\x88\x24\xda\x32\x08\x52\x29\x6f\x0f\x58\x3c\x50\x0e\x94\x89\xd8\x0e\x48\xd6\x2c\x24\xe3\x28\x0e\x28\xbd\x03\x59\x08\x8f\x44\x27\x96\x3d\xed\xfa\x6f\x98\x69\x21\x96\x5c\x60\x08\x74\x0d\x11\xb5\x3d\x5b\x44\x17\x11\xea\x81\x71\x7b\xaf\x82\x04\x0f\x44\xca\xff\xc3\x42\x1e\xbb\xe4\x2f\x4f\x72\x36\xeb\xa9\xeb\x5f\x0d\x25\x13\xa0\x19\x0b\x9e\x05\xe1\xef\xbf\x93\x8c\xfd\x13\xad\xe8\x2b\x2b\x9f\x77\xfd\xb4\x4b\x32\x56\x34\x97\x01\x8b\xcd\x7c\xf6\x48\x3b\xd5\x48\xc5\x37\x24\x57\x43\x41\x16\x12\x90\x85\x8c\x75\x4a\xf2\x48\xf4\x4a\xf4\x46\x74\x32\x94\x8c\xfc\x10\xb4\x10\xe6\x41\x5c\x83\xd6\xec\x17\xdf\xe3\x17\x74\x83\xa4\xf1\xd9\x16\x44\x4b\xff\xc2\xbf\x7c\x61\xd9\xf5\x1f\x0c\xd9\x7b\xaf\x7c\xba\x82\x70\x0e\x28\x7f\x40\xda\xac\x6d\x97\xfc\x41\x21\xda\xb1\xb2\x1d\xa7\x6a\xcf\xf9\x7f\x73\x69\x56\xcd\x3b\x27\xe4\xc0\xb4\x23\x87\xf9\x27\xd3\xce\x6c\xce\xd5\xd2\x82\xbc\xa6\x50\x8f\x20\x8d\x89\x42\x92\x58\x8b\x12\x91\x7e\xad\x36\x10\xac\x92\x64\x28\xfa\xb3\x20\x41\x7d\xa2\x19\x88\x6a\x96\x3d\x12\x6d\xb1\x30\x12\x85\x32\xe1\x1a\x0b\xda\x8b\xeb\x27\x89\x55\x66\xa2\x87\x8b\xae\xff\x8f\x0d\x43\x50\x08\x03\xa2\x94\x28\xb6\x27\x37\xb9\x08\x02\x9f\xb2\xa8\xa2\xeb\xdf\xd9\xca\xef\x33\xa9\x64\xb9\x85\x08\x48\x6c\x5b\x21\x3d\x0b\x24\x95\xf5\x90\x19\x92\x02\x53\x91\xce\x07\x20\xed\x46\x2a\x4b\xe5\x44\xf4\xc1\xac\x59\x97\xe4\x40\xb9\xe9\xcf\x35\xf9\x04\xe3\x9e\x8a\x5a\x68\xa4\x7d\x39\xdf\x9c\x8a\x0c\x4f\x49\x56\xee\x49\x18\xb1\x96\x44\x93\xef\xa9\xe5\x41\xb4\xde\x02\xc3\x93\x4a\x8f\xbf\x00\x55\x22\x88\xa9\x91\x30\xd8\x13\xac\xc5\x54\xa6\x6f\x40\xf4\x85\xe8\x96\xb3\x2c\xdc\xf4\x7b\x2a\xab\x49\x1b\xb3\xa0\x16\x27\x9f\x70\x00\x16\x1c\xc9\x05\x17\x6a\x2a\x0b\x6a\x0c\xa9\x4b\xa5\xc7\x39\x55\x48\xaa\x2b\xd2\x8d\x7c\x4b\xf4\xca\x6e\xad\xd9\xca\x35\x74\x05\xd0\x13\x47\x60\xcd\x97\xb6\x44\x3b\xd6\x7f\xea\xfa\x77\x44\xf7\x30\xed\xa9\xcc\xc5\xc4\x72\xc7\xbe\xca\xd2\x01\x12\x1b\x69\x64\x68\x95\x85\x31\x9a\x88\xd4\xd4\xe4\xba\x04\x40\xd6\xd6\x37\x51\x78\x56\x77\x20\x99\x49\x43\x32\xa6\x57\x93\xca\x4a\xa9\x1c\x49\x52\x1b\x46\xd7\xbe\x0c\x9a\x26\x95\xb1\xcf\x88\x4a\xa0\x82\xf6\x05\x64\x61\x43\x07\x3b\xe9\x88\xea\xae\xa1\xc8\xe9\x10\x4f\x40\x26\x44\x19\x97\x0a\xf8\x3d\x91\x6a\x55\x90\x93\x7b\xdb\x96\x13\x48\x0e\x34\xc2\xa4\x0f\x65\xbc\x22\xd2\xa7\x99\x4c\xbc\x16\x17\xdd\x82\xa1\x88\xeb\x9f\xcc\x56\x77\xfd\x25\x50\x2b\xae\x85\x56\xb9\xeb\xfa\xb7\x40\x67\x9d\x4c\x19\x15\xe1\x96\x87\x69\x61\x4e\x1f\x89\x76\x40\x37\x56\x79\x40\x27\x20\xb5\x50\x50\x4b\x1c\x9d\x40\xc6\xcc\x5d\x40\x18\x87\xaa\x75\xac\x8a\xc2\xfc\xc0\x94\xfc\x2b\x56\x0d\xc8\xdc\x7a\xa4\xf3\xf3\x97\xcf\xb9\x42\xce\x91\x8c\xeb\x98\x4b\x7e\x64\x5e\x42\x4d\xa2\x82\x32\x32\x0b\x98\x83\xa4\x6c\xee\xc8\x14\xc1\x85\xe4\x91\x68\xc6\x7a\x52\x8e\x3e\xc8\xd1\x17\xf5\xe1\x9e\xd8\xcc\x8e\xb8\x48\x47\x74\x94\x46\x34\xe3\x40\xaf\x9c\x73\xe1\x09\xf3\x84\x42\xe6\x20\x63\x0c\x34\xc9\x13\xd0\x04\x2e\xa8\xa4\x05\x15\xa9\x19\xbe\x50\x8d\x8d\xe8\x7a\x8d\x44\x5c\x62\x0f\x73\xef\x0d\x09\x57\xaf\x73\x4d\xce\xd7\x6c\x45\x8d\xfc\xb0\x16\xbe\x92\x82\x19\x4a\xdf\xe3\x92\xeb\x5a\x88\xe9\x8b\x11\x66\x04\xeb\x1a\x24\xbe\xf3\x08\x49\x01\x2a\x39\x3d\x22\xde\xf6\xc2\x5c\xc4\x2f\x27\x89\x8d\x6d\x68\x7b\x40\x34\xcf\x33\x9c\x7d\x90\x85\x97\x81\x17\x18\xe5\x91\xac\x14\x1d\xbf\x6f\x10\x27\x90\x95\xd4\xad\x2b\x00\x7c\xed\x25\xea\x95\xaf\xbd\x8a\xc2\x19\x73\x84\xde\x7c\xfb\x2f\xb0\xf5\x42\x92\xbe\xd4\xb1\xb2\xe1\x4b\xb0\x0d\xfc\x46\x12\x93\x29\x6e\x81\x84\x0d\x21\xc8\xc0\x44\x32\x19\x88\xe6\x7b\xef\x99\xc0\x7c\x5a\xf5\xb2\xec\xb1\xb7\x1c\x49\xc3\x34\xb9\xa0\x3a\x01\x99\xb2\x06\x2c\xc6\x3f\x49\x66\xd6\x78\x29\xc7\x93\x68\xa8\x46\xa6\x1f\xb5\x98\x31\x76\x70\x40\xaa\x1f\x27\xd0\x8f\x44\xea\xde\x4f\xbc\x87\x3f\xf6\xbb\xe2\xb1\x2e\x5a\x69\x0b\x48\xed\x1d\xab\xb1\x77\xb8\x41\xfe\x86\xf1\x23\x6f\x7d\xb1\x4b\x9f\x73\xe5\x9f\xe8\x02\x9e\xa8\x73\x28\x8d\x1c\x7b\xff\x70\xec\xf5\xf4\xc4\xfb\x74\x63\x2a\xed\x31\xc5\x77\xcc\xa5\x3c\xfe\x2d\x79\xc2\x96\x4f\xb0\x39\x1c\xd3\xb5\x18\xcb\x62\xbc\x27\x5a\x31\xeb\x03\x5e\x9f\xa0\x7b\x48\x6b\x58\x7b\x03\xf3\x39\xf1\x8a\x71\x22\x02\x9d\x71\x7a\xc0\x0b\x4f\x4a\x8e\xfe\x8b\xf7\xef\xc6\x22\xd6\x0f\x62\x1f\xb5\x7d\x3b\xbe\xb6\x67\x93\x4e\x58\x45\x63\x3f\x40\x67\xb6\xfe\xc2\xb4\x8b\x48\x22\x46\x3d\x2c\xfb\x09\x37\x92\x63\x11\x58\xf4\x41\x06\x16\xd2\x3b\x76\x03\x9b\x8c\x89\x32\x2b\x31\xb4\x2b\x37\x24\x1b\xa5\x09\x4c\x0c\xd2\x0a\x27\x81\xce\xb0\x8f\xbd\x54\x8f\xcd\xa4\xc4\x27\x0d\xdb\x54\xd8\x68\x06\xa4\x1b\x8b\x0c\x01\x1a\xa2\x16\x28\x78\xe1\x3d\xd1\xb2\x03\xbc\x9e\x49\x2f\x06\x86\x2c\x6d\xc8\x52\x54\xdf\x03\xe5\x44\x0b\x43\xf6\xc6\x98\xa5\x8c\x99\xef\x97\x2e\x64\xf2\xb7\x04\xca\xa5\xa1\x23\x23\x61\xfc\xee\x40\xa6\xba\x7e\xad\xb4\x82\xf5\x17\xbe\x59\x05\x2b\x29\x99\xb5\xf4\x69\x17\x43\xa1\xec\x2f\xe8\xf3\xa3\x97\xe7\x2f\xdc\x6a\xe3\x49\xe3\x17\x38\x92\x36\x7e\xa3\xf8\xc5\x36\xe4\xad\xef\x52\xcd\xe6\xc5\x26\xeb\xc6\x3a\xa3\xf9\xcd\x38\x75\x99\xac\x87\xdc\x90\x0d\x5e\xe3\xbb\x16\x97\x44\x26\x95\x0d\xd9\xa4\x17\xec\x89\xf9\xa4\x65\x45\x6d\xd7\xdf\x02\x2d\xd9\x8c\x57\x16\xf2\xca\x2a\xd7\x7c\xba\x86\x82\x03\xd2\x66\x7c\x17\x6f\xb9\x02\xd9\xb2\x75\x3b\x16\xb4\x93\x31\x6b\x40\xf6\x2c\xf5\x9d\x46\x25\xe3\xde\x35\xa3\x86\xca\xe8\x39\x66\xb2\xb2\xb4\xac\x33\xd3\x2e\xec\xfa\xd5\xc6\x2b\xf9\x43\xe3\x7a\xb1\x60\xb3\xc0\x08\xce\x3c\x8b\x25\xaa\xc8\x17\x3d\x1f\xb6\xc9\xe8\x50\x66\x62\x70\x30\xdf\xa2\x59\x64\x56\xf5\xc9\xd0\x1a\x23\x03\xee\xa3\x0d\x19\x97\x74\x46\x7b\x9d\x49\x06\xb4\xd9\x36\xbb\x40\xda\xe6\x8c\x15\x65\xcc\x97\xb3\xdd\x5f\x10\xf1\xc2\x02\xcc\xcc\xc7\xd4\x98\x12\x78\xf0\x6a\x8c\x38\xfd\x72\xcb\xb5\x9c\x23\xcc\x03\x94\x72\x9f\x0c\x92\x11\xdd\xfa\x64\x5d\x40\xb7\xe6\x0f\x0e\xf8\x64\xee\x9f\x34\xd0\x4c\xb9\x77\x0e\x41\x3e\x81\x62\x5d\x71\xbb\x90\x63\x1b\x8e\x42\x0a\xa6\x95\xac\xa5\x64\xb3\x4a\x46\xc9\x84\xc8\x90\xe4\xe6\xfa\x5f\x49\x62\xc1\xb5\x88\x5b\x66\x24\x8c\xbd\x8e\x87\xec\x1d\x44\x5f\xe4\xb4\xf4\xb7\xb6\x80\x97\x7c\xe7\xd9\xd7\xd3\x04\x29\x35\x67\x30\x17\x47\xaa\x60\xbd\x0b\xdf\xd0\x96\x32\x7e\x2b\x2b\xae\xc6\x8a\x93\x27\x61\x8a\x6f\x7b\x66\xea\x52\x9a\xe7\x9c\x6b\x2c\x97\xbd\xa9\xa6\x6d\xf1\x1f\x64\xc7\x9e\x1d\x89\xae\x7e\x73\x0d\xde\x30\x44\x1a\x45\x27\x87\x10\x63\x80\x7a\xa6\x30\x6b\xa2\x0f\x66\x1b\x43\xf1\xe5\xae\xab\x66\x87\x72\xd8\x47\x4c\xcd\xad\xca\x9f\x8e\x5d\x8c\x97\xe4\xe4\x8d\xcf\x19\xd4\xf6\x54\xc4\x70\x0d\x34\xa0\x9e\x9f\x7a\xbd\x09\x12\x91\x7a\x45\x77\x2e\x9e\xd9\xf2\xa1\xd6\x70\x67\xe1\xb2\x54\xb2\xf0\xe5\xb0\xb2\x32\x12\x45\xf0\x62\x6b\x23\xc9\x88\x6b\xfe\x0e\x26\x87\x48\x05\x13\xe4\xd9\x93\x85\x27\x2b\xb6\x30\xa8\x34\x43\xa6\x34\xee\x28\xd6\x77\x76\x16\x12\xb7\x1e\x77\xc1\xe9\x90\x2e\x4c\x29\x40\x92\x66\x7d\xa8\xd8\x81\x2a\x68\x56\xd9\xf0\x4c\xbd\x98\xdf\x31\xb2\x86\x68\xd1\x1b\x90\x9c\x9e\x04\xd9\xfb\x1f\xf9\x0d\x3b\xdd\xd2\x9e\x4f\x79\x46\x31\x55\x43\x61\xd5\xbd\x30\x46\x84\x27\xaa\x58\xa6\x16\x29\x8d\xd9\x96\xbe\x80\x0b\xc7\xa2\xf5\xfa\x07\x7c\xe2\x72\x9a\x82\xbb\xa3\xdc\x4b\x34\x2b\xac\xf0\xba\xe7\x43\x5b\x53\x31\x2f\x77\x44\x35\xd1\x15\xe8\x3b\x87\x6d\xcb\x4e\x6d\xd9\xf4\x3d\x25\xe4\xc0\xb4\x13\x7d\x8d\x3b\x31\x27\x5a\xbb\x1e\x01\x4c\x65\x11\x8d\xad\xf6\x60\x47\x2a\x43\x9a\xc1\x04\x66\x4a\x1d\x3f\x95\x45\x32\x35\x21\x73\xeb\x64\xca\x63\x8a\xa9\x86\x08\xb4\x91\x81\x8c\x88\x20\x75\x01\x65\x4c\xbb\xb3\x16\x3b\x9f\x6e\x6a\x61\xca\x9c\x24\xc6\x10\xc0\x6b\x93\x0c\xe7\xf0\x4d\x75\xe7\xe2\x5e\x5b\xfa\x56\xad\x7c\xb6\xb5\x7f\xb2\xb1\x79\x0a\xe4\xe4\x1b\x7f\x21\xba\xba\x86\x06\xa3\xca\xb7\x2d\xfa\x02\x12\x7a\x5b\x88\xec\xe5\x78\x5b\xac\x59\xff\x3b\xd1\x3b\x24\xf9\x9e\x1e\x65\xe1\xc3\x14\x85\x86\x59\x1d\x51\xf5\x73\x6f\x51\x55\x1d\x87\x7b\x0b\x8f\xc6\x32\x74\xf8\x0a\x0b\x75\xc4\x27\x8f\x44\x1a\xe3\xbc\xf7\x76\xae\x30\x3b\x97\x93\x34\xfe\x89\xee\x4a\x0b\x0b\x54\xc6\x4a\x96\x3e\xdb\xab\x7f\xb2\xf6\x4f\xf6\xbe\xd2\xb3\x6f\xff\xc5\xf5\x34\x48\x1c\x5b\x90\x8c\x30\x0d\xd1\x9d\x2d\xb8\xf5\xba\xa7\x6c\xdf\x8b\x9f\xda\x5a\x9a\x95\xa5\xbb\xad\xc2\x9b\xd9\x82\xf6\x88\x64\xed\x9f\xec\x59\xf9\x2d\x27\x2e\x8e\xee\x94\x6d\x28\x44\x09\x93\xc8\x62\x28\x10\xfb\x00\xaa\xd8\xf0\x9a\x95\xc5\x81\x56\xb5\x12\x0f\xed\x20\xbf\xcf\x30\x1e\x85\x1f\xf9\xc6\x77\xbd\x61\xa9\xd1\xf1\x2d\x10\x43\x06\x6a\x79\x6e\x06\xf2\xc6\xe2\x5b\xc4\xf1\x0a\x3f\x5d\x4b\x3e\x5d\xc9\x96\xe8\x86\xa4\x22\x7a\x33\x64\x42\xbd\x96\x61\x5e\x83\x6c\xf1\xbf\x67\x23\x72\xe1\xa8\xed\xa0\xb6\x04\x25\x43\xcc\xcd\x9e\xf5\x1d\xa0\x6a\x41\x8e\xec\xc8\x91\x19\x3e\x69\x95\xef\xa5\xd4\x78\xfc\x2b\x07\x19\x6e\xea\x2f\x74\x3b\xf0\xa4\x65\xe3\x2e\x36\x6e\x41\xb3\x7d\x81\xa9\x2d\x18\xef\x2c\xe8\x0b\x17\x54\x73\x82\xb4\x09\x66\xd6\x80\xd0\xab\xe0\x55\xa5\x44\xef\x40\x43\x1b\x4f\xf3\x91\x0b\x31\xb5\x5a\xf5\x24\x7a\x6b\x56\x70\x26\x33\x36\x05\xc9\xa5\xf2\x25\xc9\x84\x6f\x16\xdc\x78\x16\x3e\xca\x5a\x50\x77\x16\xbf\x29\xc5\xc2\x94\x62\xcc\x46\x89\x82\xea\x73\xa5\xad\x3d\x79\xef\xfa\x1b\x92\x7f\xfd\x93\x0b\x1b\x5a\x20\x64\x09\x34\x71\x95\xd8\x96\xfd\x41\xc3\xe6\xd2\xb6\xd2\xdc\x9e\x01\x89\xda\x41\x64\xbb\xf3\xa4\x60\x1e\x75\xda\x4a\x1f\x50\x7f\x30\x07\x28\x56\x12\x03\x53\xa5\x77\x64\x1f\x7e\x3b\x68\x2b\xa1\x84\x80\x34\xda\x04\x32\x81\x79\x45\x72\xcc\x70\x85\x40\x94\x3c\xfc\x2b\x65\x2f\x12\x8b\xcb\x59\x42\x4e\x3b\x5b\xc2\xb5\x04\xd2\xbd\x76\xc9\x75\x58\xfa\x4b\x17\x0f\x5c\xfa\x25\x83\x12\xa5\xf9\x23\xda\xd7\x96\x9a\xff\x81\x2b\x1b\xc9\x13\x96\xfd\x62\x1b\x8b\x9c\xd9\x2a\x16\xf5\xe8\xdf\x9e\xb3\xe9\x2d\xbd\xa6\xd2\x1c\x98\x41\x97\x24\xe0\x4b\x4e\xd4\xca\x27\xaf\xf8\xf6\x8a\x31\xeb\x92\x0a\xa2\xa4\xeb\x52\xd2\x65\xc7\xd6\x45\x9b\x19\xf7\xba\xa5\xc4\xcd\x75\x3c\xce\xcc\x7a\x46\x2c\x0f\x07\xfc\x3a\x21\x57\xff\xd2\x55\xdc\xd1\x89\x90\xb0\x8a\xa7\x3d\x1f\x60\x2e\x65\x69\x0e\xfd\xd9\x4d\xc9\x35\x5a\x72\x3d\x96\x8c\x28\x22\xc2\xf1\xdc\x43\xcc\x4d\x46\x07\x03\x92\xe4\x8c\x1c\x97\x8c\x33\x97\x7e\x0d\x96\x74\x5e\x80\xe2\xb6\xb9\xf4\x5e\x4b\x69\x5e\x0b\x66\xd3\x36\x0b\x7c\x52\xfb\x6c\x33\xeb\xa7\xf8\x2f\x44\x0b\xa2\x0b\xd1\xd5\x90\x39\x1a\x15\x37\xba\x15\x0f\xd2\x2a\xbb\x07\xf4\x82\x65\x5f\xf9\x2d\x93\x84\xe2\xa5\xc1\x15\x3b\x55\xc1\xb2\xf7\x34\x36\x6f\xc5\x8d\x30\xd0\x15\x17\x70\xc5\x1d\xcc\x23\x2d\xac\xb8\xe9\xe2\xc5\x54\xec\xd6\x23\x6f\x3d\x54\x22\x6d\x29\x0b\x6a\x10\x58\x02\x5a\x12\x5d\x81\xa2\x35\xab\xec\x2a\x83\x56\x11\x8f\x47\x2b\x9a\x0c\x41\xa6\xa8\x2b\x0a\x6f\x45\x3d\x00\xd4\xa2\x41\x6a\xe4\x1e\x29\x22\x38\xfd\xfd\x02\xb1\x12\x62\xea\xbf\xa2\x5a\xac\xc4\xb4\x5d\x0c\x59\x9a\x1e\xac\x01\x9d\x80\xf6\xac\xfd\xcd\xb7\x55\xaf\x2f\x08\x32\xdf\xb9\xa2\x09\xac\x44\x7b\xc4\x3e\x1f\x39\xba\x27\x66\xf8\xc9\x97\xce\xcc\x77\xe6\xd3\x0b\xd3\xd4\xcc\x55\xf4\x4e\x2b\x2c\x15\x24\x3f\xc2\xaf\x87\x0c\x56\x74\x5a\x2b\x2e\xa2\xca\x0d\x65\x10\xe9\x81\x27\xa9\x27\x23\x1b\xc9\x40\x26\xd4\x13\xd5\x6f\x3b\x6e\x3d\xa1\x74\xcd\x0e\x7c\xea\x4b\x8a\xe8\x81\xcd\xf9\x93\x57\xe7\x40\x66\x9e\xcc\x7d\x51\x8d\x7f\xc7\x8b\x8e\xee\x04\x33\xdf\xce\x8b\x3d\x89\x42\x25\x27\x4c\x28\xe3\x91\xea\xe2\xd1\x42\x5e\xb1\x17\xff\xf1\x2e\x21\x9e\xc7\x16\xfe\xc7\xef\x0f\xc1\xaf\x86\xc2\x7c\xbf\xd9\x3b\x1a\x68\xd6\xd7\xfe\xb2\x3b\x12\x03\xf2\x9c\xc6\x0d\xfc\xc5\x0f\xd6\x5f\x4e\x6c\x83\x0b\x91\x98\x58\x85\x3a\x66\x9c\xc1\x18\xd8\xa8\xa8\xa7\x2a\xaf\x97\x1e\x2d\x68\xf6\x27\x9f\xcc\x10\x68\x20\x5f\xb0\x11\x05\x07\xab\xa6\x6e\x01\xaa\x88\x82\xd1\x7c\xc2\x9d\xb2\x9e\x9e\xdb\x98\x06\x01\x19\x13\xa9\x15\x79\xf2\x07\xe3\x3c\xe8\x51\x3f\xaa\xb6\xfb\x24\x39\xc9\x23\xba\x5a\xeb\x26\xc5\x5e\x8b\x67\x71\x35\x22\xa2\x40\x7a\x27\xa6\xf6\x3e\x7d\xcd\x55\x50\x8b\xb2\xd2\xb4\x02\xfd\x78\xe2\x21\x49\x2d\xa4\x62\x86\x1a\xe1\x87\xda\x5f\xf4\xa8\xbd\x2e\x7a\xb2\x53\x95\x48\x56\xc8\xa3\x1a\xa8\x66\x64\xaa\xe6\xb5\x0b\x04\xe9\xb4\xbe\x3d\xcc\x50\x2d\xb2\x71\xc3\xca\x9f\xbc\x5e\x78\x92\x6d\xe8\x77\x28\xaa\x5a\x86\x4e\xbb\x7d\x64\xda\x07\xb4\x69\xcd\xf9\x7f\xe2\xba\xab\xc5\x8b\xd6\xfa\x2e\xd6\x39\x0b\x05\xd7\x3c\x81\xac\x65\xfd\xa2\xd5\xb8\xbf\x24\xce\x4c\x1d\x2c\xa4\x6c\x67\x6a\x59\x2e\x72\x99\xc5\x5e\xc8\x5c\x9f\xcd\x5c\xd6\xfe\x16\x62\xad\xae\xa4\xbc\x30\xf3\xfe\xfb\xcc\x3c\xc3\x96\x44\x9d\xc1\x28\x90\x33\x7f\x1c\x37\xe3\xc1\xca\xcc\xbc\xb8\x31\x5f\xc8\xb8\x6f\x9f\x21\x16\x4e\x94\x12\xe1\x84\x34\x65\xb6\x29\x51\xc1\x72\x6b\x56\xac\xda\x05\x68\x0a\xf4\x42\xfb\x37\x33\x0d\xa3\xc6\xff\xab\xf0\xf8\x24\x96\xfd\x42\x17\x70\xa6\x07\x72\xb2\xcc\x21\xb0\x33\x31\x66\x7f\xf3\xcd\x96\x61\x37\x90\x6f\xbe\x98\x1f\xfe\xc9\x3b\xd1\xc9\x25\x9b\x5a\x07\x19\xb1\x5e\xbd\x6f\x37\x13\xd1\xd3\x57\xf7\x50\x4e\x33\x89\xf2\x66\x40\x9f\xd8\xc4\xcd\x28\x28\x33\xda\x95\x19\x97\xc0\xcc\xdf\x96\x9b\x49\x35\xc7\x1e\x66\x1c\xb1\x0e\x24\x17\x56\x82\x06\x81\x22\x19\x13\x65\x50\xb2\x20\xf1\x3d\x15\x04\x94\x78\xcf\xe4\xd2\x17\x12\x34\x2c\x49\xed\x9f\xcc\x3c\xf9\x9b\xa8\xf1\x35\x44\x73\x31\xf3\xb1\xa1\x99\x8f\x0d\x81\x68\xb4\x0d\x64\x6b\x63\x1d\xc8\x0f\xbc\x83\x56\x9e\x88\xfe\x75\x6f\xab\x1c\x22\x4a\xe4\x8e\x2b\x90\x94\xb8\xd2\x6c\x9b\x09\x92\xfa\x32\x54\xfe\xbf\xc2\xed\x23\x1a\x51\xf8\x66\x7e\x2f\x06\x12\x9a\x3c\xe7\x6c\xcc\x4d\xff\xde\x61\x06\xc1\xb7\x3d\xbd\xbc\xaa\xc7\xa0\xf1\x8c\x62\xce\xc3\x11\xa0\x7b\x22\x35\x7c\x20\xcf\x9e\xac\x3d\x79\x37\x24\xdd\x26\x19\x01\xc5\x2b\x46\x73\xc6\xba\xe6\xbc\xc9\x31\xe7\x8d\xa1\x39\x57\xe6\xdc\x42\x23\x9a\xf5\x81\x59\x2b\x98\xa0\x39\xa7\x7d\x4e\x23\x31\x97\xbf\xdb\x1e\x63\x2a\xec\x7c\xcb\x52\x5b\xdf\x80\x17\x6a\x14\x3c\xf9\xe2\x07\xe4\x05\x71\x5c\x92\xc2\x3f\x99\xf9\x32\x56\x40\x2b\xde\xfa\x03\xf9\x2f\x26\x6f\x2e\xab\x71\xc8\xb6\xac\x71\x70\x32\x17\xe7\xef\x13\xe8\x93\xd3\xf6\xc9\xa9\xbc\xb0\xf2\x8b\xbd\x1b\x3c\xba\xdc\x50\x58\x86\x43\x90\x3e\x33\x24\xf8\x0f\x22\x97\x56\xfb\x5f\x7b\x76\xa1\x46\xef\x81\xce\x79\xdc\x31\xf7\xf1\x85\xb9\x3f\x65\x07\x79\xf0\xa4\xb2\xf6\xc8\x2a\x63\x43\x7e\x59\x5b\x7f\x23\xaa\x40\x74\xb2\x61\x72\x31\xd4\x86\x1b\x18\x1c\x46\x0d\x98\x3c\xa0\xb2\x6e\x7c\x48\x01\x44\x4d\xc1\x33\xae\x9d\xa0\xfa\x86\x37\x4f\x80\x6e\x91\xe7\x97\x53\xea\x86\x91\x06\x20\xed\xd3\x73\xe7\x2e\x8c\x63\x35\x3f\xdb\x4d\x94\x58\xa0\x9e\x4d\x83\xcc\x7d\x0b\x1a\xdf\x85\x38\x00\x3c\x5f\x8b\x75\xbc\x32\x50\x88\x87\x6b\xff\xe6\xd6\x57\xb0\xf3\x65\xe8\x86\x01\x65\x1c\x7e\xab\xe0\xe8\xc9\x4f\xdf\xd1\x33\xd1\x45\x03\x81\xb2\x5c\x90\x74\x95\x79\xb8\x35\x2e\xca\x0a\xa8\xef\xca\x48\xfc\x98\x9a\x32\x02\xb9\x21\x1a\x31\x0c\x01\x3e\x26\xca\x59\x54\x0a\x01\x8d\x91\xcc\x46\xa6\xb1\x36\x14\xd3\x2c\xfa\xd5\x50\x1a\x81\xb6\x40\x19\x64\xaa\xb1\x73\x51\x2d\xbf\x60\x03\x0a\xdf\xe8\x92\x25\x54\x3c\x68\x7a\xd6\x6d\x81\x98\xb0\xc6\x7b\x88\x8d\x39\x84\x39\xf9\x1c\x9f\xda\xf4\xf4\x43\x18\xfb\xae\xa5\xa1\x49\x69\xa4\xc0\x8a\xf5\xe8\x86\xb6\xc1\x15\x7d\x8c\xf8\xb3\x79\x0f\x03\x92\xe8\x3d\x80\x17\x44\x15\x4f\xfd\x9e\xed\xf2\xaf\x16\xbd\x64\xab\x56\x7e\x18\xd7\x52\x4f\x03\xb2\xe1\x88\x7c\xe7\x20\xe0\x16\x82\xb6\x6a\x4f\x29\x3b\x31\xeb\x07\xcb\xfa\x64\xf7\x2e\xd0\xfc\x0d\x55\xce\xb3\x28\x1a\xe4\x13\x57\xc3\xca\x0f\xa4\xee\xf9\x0f\x5e\x1a\xee\x51\x1a\x5c\x9c\xb7\x2e\x24\x6c\xb5\x1d\xd0\x35\x7a\xef\x57\x76\xb5\x30\x46\x96\x1a\xc5\x3c\xa1\x7c\x24\x63\xa8\xd8\xc6\x89\x49\x02\x0b\xa6\xc9\xd1\x2b\x6d\x64\x1e\xff\x60\xce\x67\xf3\x51\xb4\x61\x05\x5b\x55\x70\x5f\xdb\xd0\x47\x69\x18\x62\x6d\x54\x19\xba\x0c\xf7\x44\xa5\x4f\xa6\x0a\x79\x67\x75\x33\x5f\xc9\xdc\x44\xc6\x9d\x17\x3f\x33\xdc\xd3\x78\x67\xa4\xf1\xce\x08\xf2\xac\x99\xbc\x31\x41\x86\x5b\xe2\x3a\x44\xb5\x91\xc8\x67\x03\x2e\xdb\xa7\x7f\x72\x71\xef\x98\xdb\xf8\x6c\x8e\x44\x4b\x92\x11\x85\x66\x2f\xa8\xac\x17\xdc\xf3\x2d\x28\x07\x0b\x3b\xbf\xd6\x0c\x43\x66\x18\x33\x6d\x0c\xad\xb1\xf0\xa7\x57\x0b\xee\xd5\x17\x76\xce\xfd\x64\xc4\x92\x75\x71\x2f\x7c\xf9\x15\xab\xad\xbc\xb0\x2c\x38\xe4\x0b\x6a\xe9\x05\x07\x7b\xc1\x88\xeb\x42\xbf\xb1\x49\x34\x39\x1e\xfa\x2e\xb8\x81\x5b\x30\x70\xb4\xe0\x72\x12\x24\xbe\xcc\x82\xa3\xbd\xf0\x4a\x79\x81\xa0\x0d\xdd\x82\x05\xf7\x62\x0b\x19\xf7\x06\x48\x6f\xee\x00\xbd\x62\xa8\x17\xb6\xae\x5e\x7b\xfc\x22\xd0\x8e\x5b\x3e\x7a\x8c\x78\x5b\x57\x92\xd4\xab\xde\x85\xc9\x5e\x45\x82\x08\x35\x87\xd1\xbe\x55\x03\xba\xf6\x34\xca\x66\x77\x13\x17\xbf\x0e\x63\x58\x69\xda\x8e\xdc\xe6\xdf\x89\xed\x42\x9d\x58\xa9\xbb\xe5\x66\xbf\x35\x83\xb8\x00\x49\x99\x9c\xfa\x9b\x00\xad\x1e\x06\x4a\xcb\x5a\xdc\xd5\xef\xf9\xef\x06\x05\xd9\xc2\x6d\x79\x2d\xa4\xe5\x65\xe5\x16\x27\xdf\x86\x2c\xed\x9e\xaf\x47\x4b\xd3\x06\xf7\xcb\xda\xa9\xe1\x43\x41\x62\xf3\x5a\x09\x60\xf7\x99\x75\xcd\xb8\x7f\xcb\x73\xf7\x56\x56\xd9\x7f\x59\xdf\x8e\x19\x4e\xd0\x62\xf8\xa6\x31\x7e\xda\xd0\x52\x6b\xb6\x32\xc1\x59\xcf\x36\x68\x8d\x65\xb0\xef\x8c\x80\x90\xd5\x8e\x91\x5a\x19\xfd\x4f\xa2\xab\x35\x5f\x4f\x8a\x76\x24\xa1\x84\x25\xa3\x32\x40\x4b\xa2\x2b\x50\xfc\xb2\x6f\xc9\x89\x5a\x72\xe1\x2e\xd5\x43\x92\x9a\x97\x76\x51\x37\x27\xd1\x2b\x29\x4b\x1e\x9d\x2c\xfd\xc1\xcc\xd2\x7b\x40\x4b\x4a\xef\xd2\x3c\x9a\x98\x1c\x97\xc8\xd2\xbb\x2a\x20\x9f\x7c\xa2\xb1\xe8\x25\xef\xa3\x83\x64\x54\x86\x4b\x91\x86\xa0\x61\xbf\xe9\x29\x61\x5f\xcb\xf9\xe5\xa0\x06\xfc\x0e\xa8\xe6\x48\xcd\xf9\x74\xc1\x4d\xc7\xd2\x7b\x6d\x4b\x7f\xcc\xb2\x34\xe9\xc9\x50\x5d\xd8\x88\x33\xf9\xd3\xbd\x20\x6a\xe4\x9b\x68\x89\x31\x3c\x9d\x25\x55\x06\xd0\x2d\xeb\xda\xc9\x58\xdc\xf4\xec\x33\x57\x4d\x3e\xe1\xf2\x11\xc8\x11\xa1\xa1\x25\x8e\x47\x58\xce\x99\x63\x76\x61\x2d\x17\x19\x9c\x27\xce\xcd\x15\x01\x7a\x23\xc1\xfe\x62\x14\xcc\xe4\x2e\x45\xcb\xbf\x03\xe5\x88\x6f\x00\x35\x28\xe4\x9b\x37\x94\x4b\x7f\x00\xb2\xf4\x9b\x84\x25\x2d\xe4\x92\xbe\xe4\xd2\xdb\x4a\x90\x7b\x1b\x4a\xb7\x8b\x07\xa9\x88\xf4\xe8\xe0\x1b\x6d\xe1\xd2\x6c\x61\x2c\x9e\xd3\xef\x2e\x6d\x80\xfc\xcf\x46\xd3\xec\x1c\x4f\x20\x96\x66\xe0\xd8\x13\x0d\x04\x69\x17\xbe\xd9\x66\x5a\x95\xe8\x37\x1a\xbb\x57\x1a\x3b\x1c\x86\x4d\x90\x16\x6f\x61\xac\x7e\xbb\x85\x81\x87\xb7\x7c\x52\x19\x92\x83\xe7\x9e\x9e\x9e\x59\x89\xfa\x9d\xf1\x8a\xb7\x84\x57\x74\x87\x57\x74\x87\x57\x6c\xe7\x8a\xdf\x1a\xac\xec\x1a\xf1\x88\x44\xc5\x63\x85\xeb\x8e\x44\xf1\x4c\x18\x7c\xc9\x76\xe7\x38\xe9\x05\xd2\x23\xb9\x15\x55\xc0\x8a\xfa\x74\x05\x67\x1a\xa8\x64\x8b\x11\x91\x8e\xc3\x30\x67\x2d\x0d\xd3\x16\xbe\xf2\x5f\xae\xa9\x83\xe7\xcc\xd9\x32\x5c\x08\xb2\xf1\x39\x5f\x7d\x5b\x56\xb2\x74\x86\xe4\x6b\xb6\x77\xfd\x6b\xb2\x8d\xcd\x8e\x17\x9b\xe3\x55\xab\x57\x59\x68\xba\x37\x5f\xd1\x36\xaf\xa8\xb0\xa3\x31\x58\xe9\xc5\x59\x11\xc8\x15\xd5\xf4\xab\x0f\x59\xaf\x64\x55\xb1\x72\x15\xad\x16\xd9\x0a\x86\x6b\xd7\xfe\x02\xe0\xda\x7f\x0c\xb1\xf6\x47\xde\x20\x35\x91\xba\x10\x6b\xbf\xe5\x5c\x53\x50\xd6\x54\x60\x6b\xdc\xf9\x04\xd2\x30\xcf\x9a\x97\x71\x40\x4a\x2c\xf4\xb5\xac\x72\x68\x4e\x2d\xfb\x85\x6b\x6b\x0d\x55\x26\xeb\xf1\x0a\x8e\xea\x2a\x90\x0d\x8f\xfb\x84\x98\x29\x02\xd1\xae\xe9\x95\x98\x35\x75\xd8\x5a\x8f\x99\x45\x48\xd7\xd4\x5c\x40\x5a\xcb\xd5\xb2\x86\xb1\xbf\xb1\x12\x6c\x22\xd6\xf2\xe9\xcb\x1f\x40\x37\xd6\xd4\x80\xde\x89\x4e\x40\x13\xbe\x81\x2b\x3e\xef\x24\x7a\x7d\x7e\x23\xeb\x3a\x05\x1a\xf0\xe7\x15\x36\x3c\xa7\xdc\x70\x99\x6e\xb8\xfc\x36\x92\x6f\x09\xa4\x1b\xd0\x8d\x7d\xa6\x79\x25\xd1\x2b\x4c\x1b\xce\xc1\x86\x47\xc6\xdc\x01\x20\x55\x9d\xd7\x8d\xc5\x53\x77\x20\x0b\xef\x23\x09\x77\xa2\xb6\xe1\x4d\x00\xa0\x8c\x68\xca\x56\xc6\xd0\xd4\xc6\x7f\x00\xb2\x71\x1f\x80\xe4\xe4\xb5\xcf\x39\xf3\x05\x2e\x59\xe0\x9a\x79\xce\x2c\x4a\x43\x47\x1b\x6e\xf2\x36\x32\x3f\x18\x5d\xf3\x50\x2d\x77\xf2\xcb\xc7\x46\x1b\x9d\x17\xcb\x5c\x58\x45\xb6\xeb\xda\xd0\xa6\x6c\x7c\x30\x78\x63\x51\xa7\xf8\xe4\xc9\x5a\x96\xc4\x7b\x7f\x1b\xef\xa1\x6e\x68\x4c\x36\x7e\x63\xb5\xd1\x1d\x94\x0e\x84\xd8\x0f\xa2\x8b\x6b\x99\x08\xdc\xc6\xef\x90\x36\x3e\x22\xfb\x1d\x47\xe9\xd0\xed\xdf\xa9\x9f\xd5\xd2\xf3\x56\xc4\x77\x46\xa2\xbe\x8b\xd6\x53\xaf\xef\x3b\x0f\x98\xbe\x63\x45\x60\x8e\xbf\xe3\x47\x28\x80\x6e\xac\x44\x8d\xab\x69\xbc\x60\xcb\xe3\xb8\x2d\x97\xd5\x96\x71\x97\x2d\x2f\xff\x6e\xa5\xe6\x59\xcf\xae\x55\xeb\xb0\x6c\x79\x53\x05\xf7\xb6\xbe\x1a\x92\xd6\x6c\xe9\x35\x6d\xed\xc0\xac\x06\x99\x33\x4c\xb0\x65\xf0\x77\xcb\x0b\xb5\x5b\x93\xb0\x98\xac\xdf\x31\x6d\x19\xc4\x80\x77\x86\xa4\x13\x37\xc3\x5b\x2a\x8a\x2d\x5d\xaa\xad\x88\xdb\x48\xbc\xa3\x33\xc6\x63\xcb\xaf\x55\xb7\xfa\x91\xb8\x28\xa5\xad\xe8\x8e\x6b\x4f\x7f\x4b\x40\xdb\x12\x10\xbb\x9b\xe8\xcf\xa0\x6c\xa9\x3b\xb6\xf2\xfa\x03\x10\x9c\x9b\x11\xc9\xc8\x0a\x4e\xe2\x85\xef\xad\x85\xc8\x23\xb9\x25\x8a\xe5\xc4\xf7\xfc\x6c\xc9\xc5\x14\xa2\x7f\x88\xf4\x76\xe9\xd6\x6f\xc8\xb7\xce\x1f\x49\xc9\x55\xcb\xef\xb8\x39\xde\x49\x33\xff\x0b\xdb\xb6\xe3\x4d\xa6\x9d\x7d\x9e\x72\x05\x29\x64\xc4\x47\x24\xb5\x21\x99\xc6\x1d\xcf\x8e\x77\x8c\xe1\x0a\x12\x41\xd8\x59\x10\x28\x05\x59\xf0\xa2\xce\x8e\xa7\x5d\x3b\x5a\xd5\x1d\x6e\x38\x00\x7d\xb0\xd4\x4f\xa2\xf8\x3b\x2b\x3b\x5e\xa5\xdb\xd9\xaf\x01\x7c\x27\xd9\xc2\x28\xed\xfc\x3d\xf5\x9d\x7d\xca\x90\x81\x68\x88\x68\x47\x4d\xf1\x46\x57\x6d\xcf\x43\x8f\x37\xbd\x05\x23\x59\xdf\xb8\xeb\x79\xe3\xfd\x97\xbd\x8f\x0b\x83\xdc\x13\x55\x3e\xb9\x66\xd9\xd1\x22\xef\xbd\x45\x06\x59\xb0\xf8\x37\xf7\x82\xc5\x53\xf6\x74\x12\xf6\x74\xef\xf6\xb4\x2f\xf1\xd2\xc8\x9e\xd7\xc4\xf6\x74\xe2\x40\x62\x53\xf5\xc0\x69\x8f\xcb\x51\x86\xec\x69\x85\x8e\xbc\xd1\xa9\x90\x34\x2b\x52\x67\xfc\x87\x9e\xaa\xd8\x4b\x73\xa2\x86\x28\x06\x29\xf6\xfe\x42\xda\xde\x9f\x84\xee\xb9\x39\xda\x9b\x9b\x37\x22\xc9\xf9\xf6\x8b\x6f\x7e\xb4\x51\x7b\x6f\xa3\xf6\x5e\x83\xec\x4d\x69\xc4\x02\xa2\x47\xb9\x57\x1b\xe5\x72\xfe\xc3\x15\xb3\xf7\x3f\x4f\xb2\xe7\x1d\x7a\xa0\x77\x20\x31\xec\x22\xe5\x7b\x9c\x48\x63\xe9\xee\xa5\xc3\x13\xeb\x4f\x50\x22\x63\x2b\xc7\xf6\x10\x7b\x91\xde\x01\x11\xde\x33\xc5\xb2\xc7\x69\x4a\xd7\xff\xd3\x1a\x67\x3f\xd8\xb1\xa7\xad\x03\x1a\x7a\xc2\x91\x55\x57\x21\x27\x89\xa7\x72\x6f\xd0\x3a\x36\xe1\x89\xba\x6f\x7b\x6f\x5d\xf7\x7e\x2f\x05\xa2\x8a\xfa\x07\x6d\x21\x50\xcb\x0c\x4b\xdf\x90\x15\x3b\x14\x43\x89\x20\x3f\x88\x4e\xbe\xb1\xff\xe7\xc9\x27\x0f\x0e\xf7\xde\x6a\xee\x3b\x77\x63\x0d\x44\x35\xe9\x81\xf6\xeb\xc0\xd3\x9e\x03\x17\xca\x81\x63\x71\xe0\xf2\x38\x70\x79\x1c\xa8\x9c\x0f\xdc\xf7\x1c\x78\x4a\x77\x30\xe7\x37\x23\xd1\x82\x4a\x66\x2d\x65\xad\x9c\x58\xb0\xca\xe1\xbb\xfb\x6c\x31\xd6\xa0\x6b\xe9\x20\xeb\x66\x6c\x48\x64\xe8\x20\x8b\xe6\x0f\xd6\xf5\xcc\x12\x1b\x36\xb5\x85\x9b\x70\x30\xe9\xaf\x48\x2a\x66\x40\xad\x07\x56\xf9\x02\xc9\x3d\xf8\x2d\xd2\x3f\xf6\x03\x3d\x23\x92\x05\xab\x6b\xe9\x9b\x1c\x38\xaf\x07\x99\xd4\x7b\x88\xcd\xc1\xbc\xee\x96\xef\xac\x59\xdd\x96\x8d\xdd\x33\xed\x9d\xc3\x16\x83\x37\x07\xee\x99\x0e\xf6\x6b\x2d\x23\x12\x7d\xef\x6a\xb3\x60\x32\x00\xf4\x68\xdd\x0d\x2b\x67\x4a\x84\x5e\x5a\xdb\xdf\x2d\x8e\x89\xe1\xd4\x1f\x13\x59\x93\xa0\x41\x76\xbd\xe1\xe0\xad\xe5\x81\xdf\x73\x09\x72\x1b\x99\x03\x8d\xe8\x41\x96\x68\x44\x29\x51\x66\x28\x89\x95\x17\x4e\x06\xf5\x44\xb4\x25\x29\xac\xbf\xee\x46\xc2\xc1\xbb\xa3\xff\x70\xd5\x21\xf9\x87\x49\x98\x8b\xc7\x1f\x19\x4a\x3f\xea\xa1\xa7\xbc\x70\xf4\xdf\x74\x1c\xfd\xed\xa7\xff\xd9\xd7\x87\x19\x0b\x48\xb9\x81\x03\x39\x02\xe9\x3a\x3a\x52\xc1\x1c\x69\x70\x8e\xf4\x66\x8e\xb2\x7a\x1e\xd0\xaf\xa3\xfe\x52\x97\x05\xa2\x8e\x54\xd5\x47\xae\x9c\xa3\x2c\x9b\x2f\x40\x8f\x18\xde\x23\xae\x17\x01\xcd\x98\x6f\x06\x37\xe9\x48\x5f\xef\xa4\x47\x54\x42\x8e\x34\x36\x47\x1f\x7f\x3b\xf2\x84\xfe\xc8\x5f\xb0\x3a\x9a\xcd\x69\x49\x32\xa2\x82\x65\xbf\xf2\xbd\x15\xbb\xbe\x62\x15\x3b\x3e\xdd\xb3\x85\x07\x5f\xed\x4f\x66\xbd\x10\x5d\x0d\x99\x01\x38\xf2\x7c\xf4\x48\x91\x3d\x8a\x38\x16\x86\xb4\xea\x84\x63\x0d\x1f\x53\x9a\x7c\xd2\x53\x2e\x6d\xb2\x79\x92\xc7\xce\x9d\xaa\x9f\xec\xe0\x28\xe3\x13\x15\x28\x3c\x51\xe3\x86\x53\x06\x15\x9e\x9f\x3e\xca\xfb\xd3\x76\xb6\x03\x92\x8c\xe8\xce\xe7\x29\x7c\x51\x25\x91\xda\x93\x9f\xfe\xdc\x1b\x64\x4e\xa4\xc7\x9f\x3f\x3b\xf7\xab\x0b\x3f\xfd\x39\xf6\xcf\xce\x7e\x34\xe1\xa7\xf8\xa5\x13\x20\xdd\x68\x7c\xe8\x06\x5c\xe4\xec\x43\x37\xc5\xba\xf2\x91\xd3\xf6\x3f\x3f\xbd\x27\xfe\xf1\x9b\x59\xfc\xb0\x10\x63\xc5\x9c\xa5\xf5\xdb\xed\x05\x3f\x3a\xfb\x22\xeb\xcc\x21\x3b\xd3\x17\x84\xe1\xd2\xcd\xc9\xd9\x3e\xa0\xca\x49\x74\xf4\xcf\xfe\xa3\xa5\xb3\x7e\xa7\x64\x45\xc5\xef\x94\xce\x5c\x79\x67\xce\xc8\x99\x1d\x38\xfb\xd6\x7f\x72\x19\x9e\xb9\xe6\xce\xd4\x32\x67\x7a\x4d\x67\xce\xd4\x99\xee\xfb\x99\x87\xce\x67\x4a\xce\x99\x7a\xe8\xdc\xb9\xaf\x26\xcf\x5c\x94\x67\x5c\xff\x21\xd2\x3e\xea\x75\xec\x33\x4d\xd6\xbf\xf8\x59\x39\xdf\xa8\x5f\x3e\x37\x00\x2f\x89\x1a\xb6\x73\xc5\xfd\xce\x99\xf1\x9b\x33\x9d\x9f\x33\x9d\x76\xa0\x29\x11\x7b\xe0\xae\x43\x21\x6c\xb4\x81\x46\x8c\xdf\xfb\x00\xa9\x27\x7b\xe1\x71\xcd\x85\xb1\xc2\x0b\xbe\x56\x02\xd2\xe3\x8b\x8b\x18\xd8\x7e\x4f\xbf\x15\xb2\xf2\xbf\xf2\x0d\xb5\x89\x17\x44\x00\x81\xd6\xf0\xb4\x2f\xb2\x4b\x9f\x02\x6d\xf9\xae\x4a\xc2\x85\x91\xc1\x8b\x98\x8e\x3b\xa0\x21\x9f\x66\xfc\xac\xe0\xc2\x1f\x7e\x8c\x86\x33\xfe\xe0\xd9\x05\xba\x81\x28\xb3\x96\xbb\x4b\x36\x17\x8b\x7e\x87\x17\xae\xbc\x87\x71\xa5\xe1\xb8\x52\xfa\xae\xd4\x33\x57\x04\xa0\x0c\xc9\x54\x5d\x29\x5c\x57\x5a\xb2\xab\xfd\xe2\xc3\x00\xa4\xf6\x28\x96\x3a\x23\x7a\x61\x3b\x5a\x3a\x66\x57\x7f\x22\x77\xa5\x23\x72\xf5\x91\xd5\xab\x74\x61\x45\x84\x06\x96\xcc\x29\x5b\x75\xcb\xa9\x7a\xfb\xea\x77\xba\x57\xc6\xa3\xae\xdc\xdf\xc7\xa3\x8e\x2b\x2f\xdb\x5f\x7d\x70\xff\xca\xaf\x94\xae\x8c\x37\x5d\xdd\xe0\x4a\xfc\x40\x92\x03\xc2\x85\x23\xa0\x50\x93\x6e\x07\x06\x3d\xb7\x31\x50\x34\x24\xaa\x7a\xf6\x9d\x19\xbe\x94\x8c\x77\xf0\x03\xba\x63\x41\xa5\xed\x8d\x71\x2f\x3f\xfe\x7a\xaa\xf2\x37\xa0\x47\xfb\xcd\x46\xbd\xbe\xaf\x0d\xaa\x59\x79\x2d\x66\x47\xd1\xc9\x50\x10\xdf\x80\x66\xac\x62\xc6\x52\xb8\x8d\x0a\x84\x3f\x6e\x14\xc8\xce\x92\xc3\x30\x5e\x81\x86\x4c\xbb\xb1\x2f\xb6\x71\xdb\x4c\x55\x4b\x20\xd0\x60\x7a\x72\x9d\x78\x92\x7a\x32\xf4\x04\x4e\x95\xdd\x22\xb1\x19\x52\x0e\x39\x50\x52\x11\x41\x0b\x2b\x41\xf0\x04\x44\x5d\x3b\x25\x39\x8b\xba\x75\xbf\x60\x17\xf8\x83\xc8\x8e\xdc\x7d\x96\xd5\x10\xd0\x93\xbb\x78\x1d\xf8\x33\xcb\xbd\x58\x9a\xba\xa8\x7a\x87\x13\x97\x56\x95\xc0\x46\x2b\x81\xf7\xa1\x3f\x2c\xa9\xdf\xe3\xa0\xee\x84\x1f\xc5\xda\xa2\x0b\x49\x43\x3e\x44\x2c\x4b\x11\xce\xbc\x40\x62\xf4\x57\x7f\x12\x2a\xe3\xdb\xaf\xf6\xb6\xee\x3d\x13\xfc\xb0\x6b\x4e\x84\x13\xb0\x64\x60\x97\x1c\x92\x01\x45\x31\x8e\xf1\xc0\xb6\x41\x4a\x6a\x8f\xe8\x63\x46\x47\x3a\x19\x50\xaa\xe2\x8c\xf0\xfc\x37\x19\xd8\x6f\x05\x24\x03\xbb\x85\xa3\xe8\x87\x28\xbb\x64\x60\x3f\xdb\x9b\x0c\x4c\x19\x24\xb8\x64\x56\xb8\x66\xe8\x31\x78\x82\x0b\x64\x37\x5c\x77\xa9\xed\x0b\x14\xbd\x3b\x67\x20\x67\xea\x87\x21\xdd\x7c\x24\xa9\x59\xd4\x24\x75\xb7\xab\x12\xba\xd4\x09\x4d\x7c\x82\xef\x9d\xc7\x40\x0c\xe2\x05\xf2\x0d\x8d\x4d\xdd\x01\x55\x82\x26\x20\x83\x6a\x9c\x84\xbf\x49\xa8\x73\x37\x20\x8a\x69\x3c\x0c\x53\xfe\x48\x54\x13\xf1\x06\x4d\xbc\xb9\x19\x7f\x78\x34\x19\x9a\xe3\x90\xd8\x4f\x03\x5a\x45\xb9\xed\x2c\x02\x99\x32\xf9\xde\x37\xab\xe4\xab\x95\x6f\xc9\xdc\xa3\x1c\xe8\x85\xed\x5e\xb2\xac\x57\x9c\x9f\x31\x0f\xfc\xbd\x64\x68\x76\x3b\xa0\xd4\xca\x4a\x32\x0b\x58\x29\xd1\x59\x46\xe4\x2f\x05\xca\x2d\xec\xa2\xe4\x9e\x08\xd6\x5b\xc9\x73\x4f\x57\x6b\xc2\xcf\x69\xf4\x0b\x18\x45\xaa\xc7\x6f\x28\x90\x37\xec\xc1\x8d\x85\xe2\xe4\xaa\x2c\x2a\x1b\x51\xb2\x46\xee\xf7\x90\x94\xcc\x98\x3b\xb7\x1f\x88\x51\xa2\xc9\x53\xa6\xc1\x37\x0b\x68\xc6\xe2\xe6\x4c\x9b\xb3\xd4\x25\xdf\xd8\x1a\xb2\x81\x1a\xd9\xc1\xc9\xc4\x72\x9b\xee\x1d\xf1\xc7\x76\x48\xc6\x7c\xfb\x2f\xfd\x39\x16\xb1\x35\xe0\x6c\x4c\x32\x62\x51\x13\xeb\xaf\x29\x10\x1c\xca\x84\x61\x1e\xbb\xdb\x1f\xc9\xd8\xeb\x5f\x90\x47\x22\x55\x76\x63\xfb\x60\xa5\x10\x82\x0b\x44\xfa\x3b\x5d\xc9\xa4\x8b\x5f\x66\x28\xf9\x42\xa4\x83\x03\x82\x1f\x71\x8b\xd9\xb0\x81\x55\xf2\x49\x92\x41\x35\x4e\xf4\x47\x49\xb4\x00\xbd\x9e\x10\xc9\xd4\x93\xc2\xaa\x8f\xbb\x01\x25\x51\xdc\x27\xde\xee\x4f\x34\x42\x25\x24\xe3\x62\xcd\xec\xfa\xbb\x22\x7c\x53\xab\x64\xce\xdc\xb9\xf8\x6c\x2a\xe7\x2d\xd0\xa3\xcc\xd8\x4d\x4f\x25\xde\x54\x4e\x46\x61\xcd\x28\x0d\x99\x6d\x28\x13\xfe\x36\x52\x82\x5f\x37\xfa\x42\xf4\x83\xe8\xc4\xac\xd8\xcf\xe0\xc7\x7f\x45\x6f\xe0\x27\x87\xfa\x44\x88\xb2\x2b\xd1\xc5\x9f\x9b\xa3\x9d\xc8\x0f\xb3\xc8\x4f\x6a\x83\xd4\xee\x57\x88\x55\xeb\xa6\xbd\xf8\x31\xfa\xff\x07\x00\x00\xff\xff\xaa\x0a\xcc\xb8\xdf\x5e\x00\x00") -func keysWordlistJapaneseTxtBytes() ([]byte, error) { +func keysWordsWordlistJapaneseTxtBytes() ([]byte, error) { return bindataRead( - _keysWordlistJapaneseTxt, - "keys/wordlist/japanese.txt", + _keysWordsWordlistJapaneseTxt, + "keys/words/wordlist/japanese.txt", ) } -func keysWordlistJapaneseTxt() (*asset, error) { - bytes, err := keysWordlistJapaneseTxtBytes() +func keysWordsWordlistJapaneseTxt() (*asset, error) { + bytes, err := keysWordsWordlistJapaneseTxtBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "keys/wordlist/japanese.txt", size: 24287, mode: os.FileMode(420), modTime: time.Unix(1511602021, 0)} + info := bindataFileInfo{name: "keys/words/wordlist/japanese.txt", size: 24287, mode: os.FileMode(420), modTime: time.Unix(1514928181, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _keysWordlistSpanishTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x5b\xbb\x76\xfc\x2e\xaf\xed\x79\x4b\x8c\x65\x8f\xe6\x00\xe2\x27\xc0\x2b\x99\xb7\x49\x99\x62\x8a\xff\x4a\x97\xd6\x2f\x76\xd6\xde\xe4\x2b\x46\x98\x3b\xe8\x2e\x60\xee\xaf\x2d\x26\x0b\x71\xdb\xad\x48\x0d\x71\x93\x67\x0c\x71\x53\xf1\x81\x52\x3b\xe3\xce\xb4\x12\xae\x42\x8f\x2f\x26\xea\x21\x6e\x53\x32\x32\xb3\x5b\x88\x29\x6e\xd1\x91\xec\x52\x34\x86\x98\x92\xb0\x38\xe9\xfd\x53\x43\x4c\xa2\x43\x90\xe4\x13\x95\x52\x31\x5a\x92\x36\xa2\x87\xfb\x2b\x29\x66\x4a\x39\x3a\xc7\xa8\xf7\x77\x88\xc9\x4e\x41\xc6\x38\xcc\xd0\x8b\x09\x81\xeb\x0b\xc9\x64\xe3\xb9\x2b\x13\x71\x8e\x31\x3b\x4a\x77\x65\xd3\xbd\xe8\x40\xed\x6e\x9c\x28\xee\xe6\xd8\xcc\x3e\x63\x8d\x48\x32\x1a\xdd\xdf\x2e\x16\xe2\x21\x89\x6d\x0e\xfd\x5b\xf2\xa1\x75\xe5\xbd\x70\x91\xa7\xe6\x10\x4f\x65\xa3\xd3\xea\xfd\x8e\x48\x3b\x86\x38\x6d\x95\xba\x9c\x2b\x55\x14\x4e\x34\x98\xbb\xa1\xef\xd4\xcc\x1c\x30\xfc\xb0\xd3\x00\xdd\x2d\x44\x75\x09\x51\x7b\x46\xbf\xa7\xec\x2e\x2f\xa4\x58\xe5\x73\x76\xa0\x2c\xc7\xe4\xf7\x57\xc5\x47\xd9\x9c\x05\x5e\x62\x88\x79\x8b\xe1\xfe\xca\xdb\x2c\x21\xe6\x14\xf3\x8e\xaa\x5d\x50\x23\x27\xdb\xc9\x13\x83\x66\xf1\xc1\x42\xc2\x43\x33\xb0\x4a\x2a\xe4\xd3\x76\xee\x34\x2b\x29\x9d\x75\x91\x25\xeb\x85\xf5\x67\xce\x52\xc8\x14\xb9\xdc\x6f\xd2\x37\x8f\x05\xe5\x85\xd2\x45\x15\x62\x31\x8f\xe9\x28\x9a\x05\x6b\xcf\x2f\x34\x2b\x71\xcb\x82\xa4\x0e\x26\xcd\x80\x84\x12\x1d\xfb\x2f\xb1\x13\xad\x65\xfb\x4b\x14\xc3\x14\x6e\xbd\x28\x5b\x68\x1f\x71\x0f\xb1\x18\xc6\x6a\x11\xe8\x2a\x2d\x63\x6d\x35\x3d\x08\x35\x56\xa6\x18\xb7\xee\x98\xb3\xee\xf7\x77\x0d\xb1\x92\x0b\xef\xaf\x7a\x4e\xf0\x68\xd5\x9c\x41\x87\xaa\x05\xb9\xfb\xdd\x43\xac\x8b\x68\x75\x08\x98\xa1\x0e\x3d\x27\xea\x86\x3d\x91\xcc\x98\x01\x49\x97\x3a\x6b\xc2\xac\xf7\x7f\x91\xcc\x76\xff\x27\x4f\x66\x2d\xc4\x16\x49\xf2\x16\x3d\x62\xfd\x4d\x06\xf7\xd1\xd0\xbe\x65\x4d\xac\x34\xa0\xb7\x99\x03\x0d\xcd\x3e\x91\x71\xa9\x3b\x28\xd1\xdc\x88\xd8\x36\xa5\x83\x42\x6d\x62\x9b\x4e\x82\x38\x66\x0c\x14\x8a\xfb\xcb\x37\x1d\x6e\xfc\xb0\x1c\xa2\x6f\x93\xac\xe7\xe9\x41\x22\x38\x24\xd9\x39\xa4\xef\x9a\x81\x10\xdf\x27\xdb\x0b\x10\xe1\x14\x31\x57\xe9\x21\x7a\xf9\x63\x5f\xaf\xf7\x37\xf2\x06\x52\x7b\x23\x20\x47\xb8\xcb\x09\xbc\xb9\xdb\x0b\x70\x82\x5f\xb8\x7c\x1f\xca\x75\x76\xfe\x30\x66\x5f\x0c\xd0\x93\x54\x88\x6a\x97\x73\x52\x8c\xbb\x30\xd7\x41\xbd\xfe\xc7\x5a\x5d\x33\x61\xa7\x58\x76\x10\xaf\x5b\xd9\xb8\xaf\xde\x04\x5b\xef\x63\xad\xbe\x8f\x95\x9b\xec\x37\x0b\x3b\x4c\x8e\x32\xe2\x93\xf0\xdf\x14\x24\x1e\xe2\x58\xc3\x0f\xc1\x40\x43\x81\x8b\x41\x8e\xbf\xbf\x86\x81\xe4\xc3\x23\x50\x33\xb8\x9f\x71\xff\xd6\x10\xe7\x1e\x5f\x80\xa0\xd4\x3c\x25\xc4\x89\x69\x67\x59\x43\xcd\x2e\xe4\xda\x39\xb0\xfe\x0b\xdc\x70\xc5\x9a\x04\x09\x16\x76\xe1\x4b\x72\xa6\x26\xb9\x64\xc1\x3e\x7c\xbe\x42\xbc\x96\x02\xb9\x14\xf8\xf8\xc4\xbc\x9f\x73\x8f\x80\xd8\xf0\x2b\x1e\x4b\xa0\x29\x23\x2f\xc3\x2c\xaf\xfb\x97\x9c\xf2\x9a\x07\x44\xf7\x35\x73\xd8\xe2\x16\x01\xcc\xc3\x16\xd3\x43\xc2\x16\x1f\x20\xda\x16\x35\x23\x03\xe1\xde\x62\x8e\xf5\x85\xb2\x9c\x30\xe5\x46\x35\xb0\xc5\xb2\xdd\xbf\x61\x8b\x35\x19\xe0\x8e\x06\x60\xd6\x2d\x3a\xc7\x74\x96\x7b\xd5\x17\x12\xb7\xb0\xdd\x5f\x3d\x61\xfb\x5b\xec\x63\x0d\xd4\x21\xce\x5b\x1c\x31\xb3\x78\x88\xaf\xc9\x41\xb8\x2d\x8e\x39\x38\xe8\x2f\xd6\x89\x7d\x6c\xb2\xdd\xdf\x80\x8a\xd9\x04\xd2\xb6\x49\x67\x45\xe7\xe7\xd0\x18\x36\x85\xd8\x6e\x2a\x35\x6c\x5a\x4f\x0b\x5b\x5e\x6b\xcc\x06\x52\x6e\x79\xf6\x18\x36\xc3\x6f\xd3\xca\xc4\xc2\x66\x09\x5f\x69\x15\xec\x04\x72\x22\x59\x25\x99\x00\xac\xb3\x59\x66\xff\x82\x4d\x5a\xdd\xe3\x8e\x04\xe2\x48\x1b\xb6\x59\xed\xf7\x97\x86\xcd\x1c\x48\x32\x07\x97\x6e\xd6\x39\x35\xa8\xb0\xd9\xb8\xdf\x35\x6c\xf7\xcf\x25\x9c\xe7\x15\x73\xd8\x3c\x5e\x16\x96\xdd\xdb\x5c\xd2\x23\x22\xb9\x24\x6c\x4e\x9d\xb2\xb9\x72\x0b\xae\x98\xdb\xb9\x58\xca\xd3\xe6\x06\x76\xd9\x9c\x43\x3b\x34\xff\xe6\xb3\xb3\x2d\x78\x7a\x9b\x49\x08\x41\xcd\x09\xb5\xb7\x4d\xf9\x0c\xdb\x3c\x16\xc5\xe6\x41\x42\xdc\xbf\x40\xd9\xd4\xe1\x68\x96\xd9\xd1\x37\x8e\x36\x3d\x13\x62\xeb\xb3\x83\x7f\xb6\x39\x22\x16\x30\x5f\xe8\x0b\x93\x8c\x25\xa6\xb8\x41\x5d\xa7\x48\xa4\x26\x18\xf1\x90\x62\x8a\xa8\xd9\xef\xaf\x4b\x1c\x1f\xc2\x3a\x7e\x1f\xf7\x77\x48\xf1\x7e\xef\x28\xd1\x02\x66\x4d\xf1\x89\xcc\x73\x8d\x9b\xf1\x83\x22\x47\x0a\xd5\x08\xfb\x43\xa8\xc0\x7a\x8a\x39\x0b\x60\x41\x9f\x6c\x6c\x76\xa1\x9e\x05\x65\x63\x8f\x22\x6b\x71\x45\x2b\x93\x66\x21\xdd\x5f\x35\x71\x09\x75\x57\x4c\x52\x25\xa3\x47\x3d\xa1\x15\x53\xac\x9a\x98\x1d\xc8\x40\x37\x02\xae\x25\xd9\x86\x9c\xf5\x90\x62\x8b\x2f\x40\x1d\x6b\xe1\x0d\x04\x48\x91\x1e\x40\x8a\x6d\x82\x84\x29\x12\x07\xbe\xb1\xf3\xfd\xe5\x49\x30\x9d\x43\x65\xa4\xe8\x27\xa1\x42\x66\x52\xf4\x8a\xee\xde\xfe\xea\xb8\x10\xe7\x77\x27\x48\x28\xe8\xc2\xf2\xde\x58\x34\xb8\xe5\x61\x9e\xd0\x15\xa4\x4b\x50\x37\x98\x62\xb2\xd3\xcb\x42\x92\xcd\x20\x5b\x49\xa0\xb4\x93\xec\x18\x40\x32\x70\x7e\x7f\x67\x81\xa9\x4f\x92\xe1\xfd\x20\x3f\xd9\x72\xe9\xa6\x24\x55\x41\x4f\xa9\x83\x7d\x1c\x48\xa1\xfb\x93\xc4\x49\x69\x59\xe5\x60\xf0\x24\x4e\x63\x9d\xee\xef\xde\x64\x0f\x49\xd8\xe9\x11\x49\xc5\x47\xcc\x92\x98\x2d\xed\xfe\x45\x4a\x5b\x9a\x1e\xb1\x11\x3a\x33\xca\x26\x0a\x77\x64\x59\x9b\xf4\xa0\xc0\xa6\x87\x61\xe4\xc7\xa4\xaa\x4d\x8f\xd9\x30\xa1\xa6\x4c\xac\xaa\x9c\x06\x98\x09\x59\x00\x1f\x32\xe9\x01\xdc\xeb\xb9\x50\xa9\x60\x09\x8a\x50\x52\x20\x5a\x2b\x86\xd2\xe6\xb0\x4c\x49\x9d\x15\x3e\xc9\x07\xda\xd9\x82\x0d\x26\x19\x2d\xd3\x39\x48\x39\x56\x00\x8c\x97\x63\x17\xc0\x0b\x50\xa9\xc3\x53\xe6\x24\xf9\x7e\x2f\xfe\x31\xe2\xd6\xfe\x5c\xd3\x64\xe9\x41\x0e\x5c\x2a\x26\x19\x66\xbc\x7f\x76\xb8\x20\x09\x86\x3b\xd9\xc1\xf6\x70\x47\x93\x3d\x04\x23\xda\x13\x9a\x22\xc1\x55\x48\xd0\x40\xc9\x32\xd9\xca\xb2\x9c\xca\x32\x78\x05\xc9\xf2\x1a\x32\xe7\x95\x2b\xac\x9a\x85\x85\x05\x5a\x15\x29\xc7\x2d\x4a\xca\xff\x94\x35\x65\x69\x40\x92\xd5\x1d\x2d\xaa\x70\x9e\x7a\xb2\xc8\x28\x21\x56\xfb\x5f\x29\xf9\xda\x40\x2f\x6b\x0a\xe8\x71\x89\xbf\x39\xf4\x37\x52\xa8\xdd\x64\xbe\xff\x15\x1b\xe7\x77\xe7\x38\x7d\xc1\x02\xd1\x31\x98\x76\xba\x9b\x62\x4c\x07\x2a\x5d\x22\x61\x5a\x99\xfb\x8d\x15\xba\x14\x36\x7d\x03\x2a\xe2\x87\xe4\xda\xd8\x5d\xbb\xf6\x90\x1c\x76\x37\xf9\xfd\xb3\x90\xee\xe0\x18\x56\x4f\x76\x9f\xaf\x90\x66\x24\xd3\xcf\x48\xbe\x98\x91\x9c\x39\x37\x02\x44\x18\x09\xb2\x0a\x3c\xcc\xa5\x2a\xe6\x62\x7f\xb8\xfa\x2c\xe4\x6a\xa7\x5c\x80\x0a\xef\x2f\x4d\x08\x0e\xb2\xb9\x11\xb2\x39\xdd\xe6\x34\xe1\x3a\xa2\x09\x36\x3f\x2b\xd7\x32\x8d\xb0\x2d\x2d\xf0\xdb\x28\x65\xf4\x5e\xd2\x74\xa5\xec\x4d\x5f\x90\x93\x0c\xed\x61\x87\x12\xdb\x69\x76\x31\xe5\x1e\x21\x78\x3b\xbc\x8e\x1c\x76\xd9\xc4\xc3\x7e\x7f\x6f\xc8\xdc\xdf\x29\xee\x31\xec\x92\xd4\xc3\x2e\x68\x26\x87\xd4\x8e\xa2\x43\x2b\x0b\x61\xc5\x77\xc9\x07\xd8\x69\x47\x70\xc4\x56\x19\x46\x6b\x97\x62\x8e\xb6\x70\xab\x76\xa9\x23\x62\x82\xe5\x45\xee\x02\x53\x84\x62\x77\xec\x61\x97\xbe\xbc\x8b\x5d\xe0\x76\xed\xd2\xe1\xe8\x23\xad\x93\x23\xf6\xa1\xab\xf6\xba\xdf\x48\x07\x55\xf4\x2e\x43\x2a\x56\x2c\xf0\x4f\x76\x10\x73\xd7\xb8\x65\x43\xb2\x83\xc2\xbb\xfe\xb9\xef\xbb\xc2\xd3\xd9\x35\x22\xb6\xd9\x75\x9b\x4f\x24\x0c\x99\xf6\x25\x66\xbb\x02\xa7\xbb\xca\x2b\xec\x7a\xdc\xef\x04\x1c\xe8\x89\x69\x35\xaf\xb1\xf2\xc4\xa6\xb5\x42\x3f\xed\xea\x82\x20\x6d\x57\xd7\x93\xc5\xd0\xa4\xbb\x76\x81\xda\xdd\xb5\x1f\x1e\x31\xd2\x85\x8e\x17\x57\x6f\x08\x27\x76\x4b\x00\xb0\x2a\xbb\x15\xba\x11\xbb\x55\xfc\xb0\x14\xa3\xe7\xbc\x9b\xc3\x5f\xdc\x0d\xc4\xdb\xad\xe3\x07\xd2\x79\x3c\x41\xea\xdd\xed\x8c\x61\xa7\x25\xd8\xb9\x73\x46\xb2\xfb\x5c\x53\xcf\x8c\x19\xee\x5f\x7c\x42\xcd\xed\xe4\x88\x7d\x52\xb7\xee\xb0\x44\xf7\xf7\x86\xc0\x43\x36\x20\x03\x3e\x81\x07\xa8\x51\x01\x47\x9b\x07\x81\x6e\x92\xfd\x2f\x90\x94\x5d\x11\x53\x1a\x3e\x06\x6b\x27\x6c\xb5\x1c\xdc\xbe\x1c\x9a\xe2\x2b\xc8\x53\xf0\x2b\x2d\x5b\x90\x2c\x07\x71\x2e\xd0\x26\x8e\x64\x29\x7e\xc9\x72\xa1\x67\xd6\xd6\x25\xdc\xdf\x59\xd9\x48\x3f\xd8\xc8\xa0\x79\x24\x33\x1e\x96\xb2\x81\xee\xb2\xe2\x5f\x29\xf6\xb7\x94\xd2\xa0\x73\xa4\x34\xee\x14\xd3\x09\x13\x97\x1e\x83\x54\x6e\xaa\x26\x06\x68\x52\xd3\x63\x1e\x82\x14\x7c\x21\x88\xa8\x58\x0c\xe2\x49\x3d\x80\x67\xa9\x87\x78\x41\x7a\xd2\xc1\x94\xaa\x67\x41\xdb\x1c\x13\x7a\x9a\x17\x24\x2e\x6c\xdb\xe3\x27\x13\xb9\xff\xc3\x2e\xea\x58\x23\x0d\x67\xee\x82\xe2\x96\x4a\xfe\xbc\xbf\x1b\x1c\x29\xf9\x37\xb5\x59\x10\xd7\x97\x05\xe9\xf0\x39\x90\xc0\x53\x91\x0e\xbd\xeb\x48\x5d\x37\xe5\x07\x77\xdc\x05\x51\x61\x90\x7e\x88\x33\x99\xe2\xec\xdd\x20\x8b\xd2\x1b\xb4\xa6\xf4\xc6\x3d\xf5\x66\x9d\xc9\xc4\xaa\xfb\xbf\x79\xbf\x03\xb4\x0a\x86\x03\x9e\x10\x8b\xa0\xf5\x98\x47\x0c\x32\x60\x14\x65\x88\x57\xac\x70\x40\xad\xc9\xa8\x98\xec\x62\x5c\x28\x57\xcc\x13\x7d\xaf\x45\xad\x8b\x67\x05\xf2\xc1\x63\x0b\xf9\x40\x6c\x1b\xe4\x83\xe7\x22\xf2\x91\xe0\x08\xc8\xc7\x6a\xf9\x41\x09\x90\x0f\x45\x70\x2b\x1f\x2b\x3c\xba\xbf\x3f\x94\x95\x8d\x76\x53\x3e\xfe\xc2\x49\xf9\x68\x06\xa1\x95\x8f\xe1\x52\x2c\x1c\xf7\xd7\xe6\x58\x0c\x3e\xa0\xc1\x8e\x98\x1e\xd8\xec\x71\x7f\x41\x06\x0f\xcc\xef\xe1\x88\xc0\xdb\x01\x3f\xee\x88\x70\x33\x0e\x3a\x87\x47\xcc\x9d\x10\x6b\x3d\xa0\xdb\x8e\x58\x34\x2b\x53\x63\x95\x47\xf0\xce\x11\xbd\xc4\xc4\x72\x37\x8c\xea\x1d\xdf\x5d\xc2\x11\x87\x9e\xf8\x9e\x9c\xe0\xe2\x64\x1f\xe1\x80\x0f\xe3\x16\x0e\x3a\xcd\x87\x64\x7d\x85\x43\x90\x77\x8c\x22\x08\xc5\x8e\xfb\xdb\xa1\x38\x0f\x71\x76\x93\x4e\x17\xfc\x50\x9e\x1c\x1c\x4a\x35\x7b\x28\x96\xa6\x50\xec\x87\xfe\x59\xed\x43\x39\xa8\xee\x18\x50\xe9\x2d\x1d\x2a\x19\x80\xcd\x68\x1b\x0e\x45\x28\x1a\x0e\x7d\x72\x80\x27\x9a\x02\x3f\x9a\x61\xc4\x0f\xec\x12\x3d\x32\xec\xce\xa1\x18\xb4\x02\x8d\x5a\x41\x0d\x68\xe8\x81\x72\x07\x4e\x72\x4c\x06\x88\xb8\xe7\xc8\x6b\x47\x50\x41\x47\x36\x96\x40\xb1\x1d\x19\x4a\xf1\xc8\xf7\x2f\x2a\x6c\xc3\x2e\xc1\xc6\x87\x9d\xb0\xc3\x87\x51\xf9\x1c\x06\x22\x1f\x96\xb3\x60\x78\xab\x3b\x20\x27\xe1\x89\xd0\x61\x3e\x88\x48\x73\x04\x56\x07\x38\xf4\x30\x34\xf5\x98\x22\x08\xe2\xeb\x2c\xea\xf0\x58\x41\x4c\x27\x0d\x3c\xce\x1d\x89\xdc\x6f\x47\x52\xd1\x10\x52\x7d\x38\x24\xea\x70\x6e\xc6\xb9\xfe\x09\xcf\xec\x98\xd4\xda\x94\x0f\x94\x81\x82\x13\x2e\xfd\x31\xeb\x1f\x8e\x27\x02\x91\x63\xfa\x5a\xf7\x24\xd9\x66\xc7\xd4\xf7\xef\xd8\xc0\x04\x73\x40\x1d\x9e\x31\xc1\x3f\x3b\xe3\x11\x7b\x38\x23\x1c\xb4\x13\x21\xfa\x19\x59\x9a\x57\xec\x78\x92\xdf\xce\x88\xf0\xec\x8c\xd0\xd6\xe7\x3a\xc7\x39\x23\x3c\x9b\x33\xc2\xce\x9d\xd1\xe3\x53\x90\xbc\x50\xd4\x97\x07\x75\x46\x0a\xe5\x19\x07\x5a\x5c\x9a\xe1\xd9\x9f\x52\xa0\xb5\x4f\x81\xaa\x3f\xa5\x86\xf3\xfe\xa6\x72\x3a\xa5\x2a\xe1\x90\x70\x8a\xc7\x95\xf3\xff\xe5\x21\x86\xa7\x74\x0c\xa5\x27\xf5\xec\xa9\xa5\xc6\x8e\x56\x0a\x5d\x74\x2a\x06\xc9\x60\x76\x0f\x67\x46\x10\x7a\x66\xc3\xee\x4f\xcb\xf8\x1d\x06\x08\xe1\x38\x2d\x37\x09\x27\xe2\xbd\xd3\xe0\x08\x9c\xe6\x60\xb1\x13\xd1\x65\x38\xc1\x1b\xa7\x0d\x41\x39\x88\x79\x3a\xe4\xf2\xf4\xfb\xeb\x80\x4f\x7d\x3a\x14\xee\xe9\x08\x24\x4e\x8f\xf0\x2e\x4e\x87\xe7\x7a\x3a\x6d\xe9\xb9\x42\xcc\xd3\xb5\xb1\x0c\xd5\x20\xe3\xe9\xd6\x0d\xa3\xdd\xbf\x68\x34\xa1\x51\x4e\x9f\x85\xb0\x59\x38\xe7\xda\xd6\x8c\x2b\xe3\x3b\xd6\x3e\x85\x6b\x9a\xa4\xc5\x64\x70\x73\x4e\xb5\x0a\xd8\xf9\x3d\xe2\x6a\xd1\xb9\xac\x49\x9c\x3f\x22\x5c\x9a\xc7\xfd\x05\x97\xe6\x11\xb7\xcc\x32\xb8\x82\x0f\xa8\x99\x40\x4d\xf3\x88\x79\x95\x17\x84\x9f\x8f\xe8\x20\xda\x23\xbe\xf0\x63\x9c\xf6\x90\x8d\xa7\x3a\x0f\xba\x67\x0f\xfa\x2e\x0f\xc9\xb0\x21\x0f\x81\x3c\x3c\xa4\xac\x1a\xf8\x7d\x0f\xf1\x82\x25\x3c\xee\x6f\x37\x41\xf6\x42\x29\x43\x89\x87\xc2\xe5\x09\x8f\xfb\x4d\x5f\xe9\xa1\xa7\x4a\x95\xf0\x80\x74\x3f\xb4\xa0\x97\x22\xfe\xd2\x18\x1e\x96\x80\xe5\x87\xc1\x17\x7f\x18\x10\x80\xc2\x27\x00\x7d\xc2\x87\xc1\x7b\x78\x58\x35\xd4\x57\xd6\x2e\x50\xa0\xd0\x1e\x3c\x2d\x7e\x18\xac\x40\x78\xd8\xa7\x85\xc7\x84\x99\x7f\x4c\x9e\x62\x3f\x26\x4f\x56\x1f\x44\xff\x63\xca\x05\x08\x2f\xfe\x01\x65\xf0\x98\x7f\x5b\xf8\x2d\xb0\x7e\x8f\x59\x34\xef\x82\x14\x99\xba\xb3\x89\x47\x44\xbc\xf8\x18\x16\x14\xbe\x7d\xd0\x5d\x62\x0e\xba\x2b\x78\x0a\xae\x76\xb6\xa0\x67\x96\xae\x11\xe9\xfd\x1b\xf4\x9c\x68\x91\xe5\x64\x32\x3b\x85\x55\x4b\x84\x0c\xac\x68\x5d\x0b\x4d\x8f\x96\xb6\xa0\xc0\x4f\xd1\xb2\xec\x86\x96\x36\xa1\xf3\xa1\xec\x10\x2a\xdf\xef\xba\x6b\x92\x00\xb7\x6c\x20\xa1\x22\xd5\x7a\xd0\x7a\x6b\x5d\xe2\xa4\x95\x3e\x8c\xd6\x42\x7f\x54\x6b\x99\x15\xb5\x15\x32\xa9\xb5\xd3\x99\xd1\xda\x07\x59\x4f\x61\xdc\x11\xc1\xdd\xef\x3a\xb4\xa0\x66\x00\x2b\x5a\xef\x5f\x60\x53\xeb\xa5\xb4\xa3\xea\x31\x28\x38\x5b\x7d\x9d\x49\x6a\xcf\x04\x08\xda\x9f\x71\x8b\xf9\x7e\x23\xc5\x16\x9f\xb1\xac\xc4\xe3\x86\x4a\xdf\x61\x2b\x9e\x64\xda\x27\x4f\xef\x9e\xf1\x55\x58\x26\x87\x84\xa7\xb8\x42\xb1\x3c\xb5\x42\xdd\x3f\xcd\x2b\x78\xf5\x69\x6e\x1b\x92\x4b\x6a\x78\xda\x67\x0c\xcf\x29\x88\xf8\x9f\x53\x2e\xe9\x48\x5e\xe1\x39\x4f\x7a\x72\xcf\x79\x1a\xc0\xe4\x08\x93\x28\x78\x4e\x44\xab\xcf\x59\x4f\xcc\x38\xeb\x2a\x02\xbe\x9f\xf7\x6f\x53\x84\x4c\x4f\x7a\x8c\x4f\x9e\xd0\x3e\xe7\x25\x55\x73\x78\xce\x17\xf8\xf0\xff\xe0\x51\xfc\x9f\x41\x33\xe6\xb8\xa9\x05\xe8\x19\x42\x47\xc9\x8e\xcf\x1d\x51\x53\xc8\xf1\x64\x60\x94\xef\xaf\xd3\x11\xc1\xe6\x78\xc2\x30\xe4\x08\xae\xce\x11\x71\x63\xbe\xbf\x0a\x64\x0d\x69\x8b\x1c\x81\x2d\x2a\x44\x33\xc7\x7a\x32\xa2\x5b\x87\x84\xf9\xfe\x6a\xfa\x0a\x99\xde\x5d\x8e\x88\x68\xf2\xfd\xd5\xc7\x1a\x7a\x30\x37\xe4\x03\xdf\xea\x21\xc7\xe9\x92\x43\x8e\xf0\x38\x73\x7c\x59\xc8\x60\xcc\x2c\x7f\x06\x18\x36\x50\x00\xe1\x5b\x64\xc1\x5a\xe4\xfc\xab\x39\x57\xc8\x95\xe5\x09\x11\xc8\x52\xcf\x19\x91\x60\x33\x70\xfe\x00\xd9\xd0\x1a\xa3\x27\x70\xf7\x2a\x18\x9c\x62\x60\x23\x72\x61\x84\x4f\x81\x0d\xca\xba\x41\xd6\x76\x7c\xb8\x85\xac\x09\x93\xde\xef\x1d\xd3\x2a\x82\x92\x80\x58\x1f\x8b\x84\xe0\x66\x3d\x85\xcd\xb0\xb3\xfb\x5d\xe0\x26\x67\x25\xf3\x64\x2d\x0d\xe8\xd6\x9a\x50\x06\xe3\x9b\xef\x77\x15\x74\xaa\x50\xd5\x48\x59\x0f\x3f\x8f\xdd\xff\x4d\x45\x2b\xe8\xc8\xcc\xb3\x6f\xb8\xdd\xce\x84\x23\xc1\x7b\xc8\x20\x16\x60\x21\xe4\x4e\x79\x06\x91\x33\xaf\x84\x72\x96\xba\x12\xa2\x33\x9b\xaf\xe4\xc2\x06\xf2\xbc\x34\x06\xda\x99\xfc\xe7\xa8\x67\x4b\xcc\xc0\x7d\xc9\xf7\xcf\x09\xf7\x2e\xdb\x89\x99\xa0\xba\x40\x46\x84\xd7\xd9\xe0\x01\x50\x56\x32\xa3\x99\x3c\x11\x6b\xe6\xc9\x39\xe1\x8d\x64\x72\xcc\xac\xd2\x43\x9e\x0d\x9f\x3c\x57\xcf\x13\x2b\x9c\xaf\x50\x62\x82\xa5\x29\x11\x1a\xb9\xc4\x1d\x1b\x2b\x71\x77\x01\x84\x6d\x2f\x51\xd8\xa3\xc4\x43\x51\x75\x2e\x88\x82\xfb\x8d\xfe\x19\xc1\x4e\x59\xf7\x4b\x85\xa7\xc5\x25\x66\x54\x97\xfb\x0b\x70\xe3\xf7\x1c\xa1\xf0\xac\xb7\x44\xe0\xbc\xc4\xca\xd0\xb7\xd0\xf4\x97\x58\x95\xbe\x77\x81\x47\xc3\x52\x36\xe9\x84\x1c\xf7\xfe\x0f\x8c\x5d\xe0\x81\x97\xfb\xeb\xdf\x54\xe6\xd0\xd4\x39\xa8\x0b\xf3\x87\x66\x24\xd0\x84\x25\xf2\xca\xa3\xdc\x5f\x5e\x8c\xa5\x94\xaa\x12\x7d\x48\x47\xf2\x42\xbf\xce\xf1\x3a\xcf\x03\x4b\xec\x7a\xa1\x70\x70\xe0\x41\x3f\xb5\xc4\xa1\xd8\x26\x2f\x1d\xcb\xfd\xf5\x01\x6d\x56\xe2\xa7\xa1\xc9\xcb\x3c\xc5\x50\xe8\x0e\x16\xd9\xd7\xee\x65\x57\x4c\xfb\xbd\x4f\xe6\x9e\xba\x4a\x9f\xe8\x21\xe0\x03\x24\x5c\x0a\x02\x7c\x4c\x81\x40\x09\xb0\xc3\xf5\x29\xf4\x53\x8a\xd4\xfb\x37\x14\xf1\x04\x95\x50\xe0\xbd\x9c\x53\x30\x2c\x3d\x80\x82\x2d\x48\x5f\xa3\x00\x41\x08\x4b\x50\x3b\x8c\xcd\x49\x31\x79\x25\xcc\xac\xb0\x3f\x05\x3a\xbd\xa8\xf0\xae\x85\xd6\xad\x00\x55\x9a\xe3\xc9\x82\x4c\x83\x51\x34\xaf\x95\x71\x93\xc4\xf1\x0a\xd6\xa1\x55\xff\xca\xc0\x39\x45\xad\x49\x28\xf4\x96\x8a\x02\x87\xda\x17\xb6\xb4\x73\xd8\xce\xb6\x90\xd8\xc2\xe5\x5a\x7a\xc0\x2d\xfa\x5f\x1c\x5a\x6c\x47\x66\x87\x41\x2f\x06\xce\x33\xd2\xdd\x60\x22\x8b\x65\xe1\x37\x04\xb1\xd8\x0a\x7d\x8b\x15\x0c\x8f\x20\x3f\x31\x15\x8e\x00\xf6\x2f\xb6\x1a\xc0\xa1\x29\x46\x0f\xab\x18\x6f\xc2\x8a\xd1\x0f\x06\x96\x99\x71\x7e\x77\xd6\x43\xd3\x14\xeb\x1c\xac\x33\x04\x2d\xc6\xeb\xcc\x42\xa1\x2c\xf7\xcf\x85\x9d\x18\xb8\x64\x52\x38\xe6\x8e\x46\x53\x10\x99\x14\x1e\x48\x96\x49\x8b\x59\x26\x44\x04\xd9\x13\x72\x33\x9f\xe8\x4f\xe2\xaf\x83\xd1\x32\x33\x21\x19\x7f\xde\xff\x09\x26\x9d\x8e\x05\x50\xc2\xee\xdf\x9e\x26\x30\x31\xbb\x10\x9e\xab\x50\xd9\xae\x67\x0b\xf5\xfe\x42\xe4\x57\xe3\x42\x1f\xec\x18\x72\x70\x0b\x6b\x5c\x61\x40\x8d\x60\xd0\x1a\x79\xe8\x5b\x63\x8f\x39\xd4\x38\x16\xc4\xb6\x6a\x1c\x9c\xb2\xde\x5f\xb3\x0b\xda\x5f\xac\xbc\x30\xc4\xc5\x63\xfb\x2a\xb0\x44\xf5\xfe\xe6\xa9\x4e\xa5\xe2\xaa\x72\x1a\x4b\x05\x7c\x52\xa9\xb7\x2b\xfc\x31\x64\x06\xc0\x1c\xac\xb8\xd8\xf8\x82\xfe\xa8\xbc\xe6\xa9\x90\xbe\xaa\xb2\x65\x94\xb0\xad\xde\xff\xc9\x8b\x09\xa6\x79\x8f\xd5\xe2\x92\x1c\xaa\x6d\x59\x5e\x31\x54\x83\x55\xa9\xf7\x0f\x99\xaf\x52\x3c\x2a\x83\xa3\xca\x73\xaf\x0a\x8f\xba\xda\xd0\xc4\x8a\x0b\xce\x47\xb5\x0b\xc4\xa8\xc6\x45\xcd\x4d\x42\x9d\x29\x86\x7a\xff\xa6\x2c\x28\xd9\xe9\x45\xf3\x20\xac\xd2\x07\xac\xb0\xf4\x80\xaf\x50\x27\xd1\xfb\x5b\xc0\xe5\x75\x0e\x4c\x68\xb1\x6b\x0f\xc6\x9b\x2b\xdb\xb4\x37\x24\x4f\xec\xc0\xe0\xa3\xda\x0a\x6b\x6d\xeb\xe2\xd8\xb5\x6d\xeb\x10\xcd\x36\x2c\x00\x01\x9f\x31\x4e\xb3\x74\x7f\x43\x91\x61\x4b\x50\x62\x06\xac\x10\x99\x96\x5c\x82\xa5\x11\x2f\x7c\x8f\xb9\x31\xcb\xd3\x4a\x4b\x3c\x44\x87\xe6\x07\xd3\x1a\x6d\x9b\x41\xa3\xd8\xae\xa0\x9b\xf1\x64\xc2\xd6\x39\xa2\x1d\x74\x41\x6d\x9d\x2f\xd9\xb1\xce\x68\x69\x27\x8c\xc7\xb4\x86\x68\xd0\x9e\x16\x2c\xc7\x60\x59\x20\x1c\x96\x0f\xa0\xcd\x32\xd8\x82\x57\x10\x3c\x98\xe6\x89\x9a\xe5\x0b\x44\xb1\xb2\x65\x3d\x2d\x18\x8c\xaf\xc1\x79\xb0\x86\x00\xd8\xda\x62\xc0\xfb\xa7\x01\x8f\xd6\xf8\x44\xc2\x96\x5f\xb9\xde\x58\xdc\x3f\x8d\x27\x23\xc6\x0b\x6d\x0b\xe6\x7f\x4c\xcb\x93\x39\x47\x92\xc3\xfd\xe3\x1b\xa2\x44\xaa\x4f\xc8\x2a\xaa\xe5\x19\x51\x71\x12\x67\x7e\xc2\x19\x34\x3f\x27\x68\x67\xbe\x8e\x18\xcd\xf5\x64\x5b\xea\x54\xc3\x36\xfd\xdf\x3a\x07\x36\xde\x51\x5b\x8f\x3c\xc5\xb4\x9e\x20\x5a\xd6\xe5\x85\xd1\x40\x0d\x8a\xa8\x0d\xaa\x09\x03\xcf\xda\xb5\x66\xbc\xc0\x02\xf7\xcf\x07\x37\xfe\x71\xbf\x4f\xe8\x0c\xfb\x5c\x13\xbe\xe0\x93\x37\x9e\xe0\x34\x9a\xc5\x16\x05\x73\x37\xc4\xe0\x35\x86\x06\x53\xd8\xe2\xfd\xee\x28\x7a\x46\x47\x2e\xf3\x8a\xad\xc5\x9c\x98\x83\x0e\x68\xf7\x57\xc6\x04\x8d\x97\x62\x2d\x66\x5b\x09\x88\xdd\x62\xc5\x2f\x66\xb4\xaa\xca\x4e\x95\x2e\x46\x8b\xf7\x7f\x3c\x9a\x6c\xb1\xdd\x5f\x80\x92\x01\xb9\xfd\x16\xff\xd1\x2d\x6d\x7c\x20\xd0\xa2\x33\x08\x6f\xd1\x65\x07\x54\x96\x19\xc6\xf4\x16\x39\x35\x70\xc5\xbc\xc7\x83\x79\xf6\xee\xec\x0d\xd5\xd3\xe2\xf2\xc3\x1a\xd8\xb7\x21\xe6\x0e\x2d\x2e\xa0\x28\xa0\x74\x34\x5e\x61\x35\x9e\x84\x34\x70\x70\x8b\x9f\x6c\x2f\x91\x57\xc7\x4d\x68\xb2\x1a\x58\x31\x22\x79\x20\xb3\x63\x77\x82\xa8\xa7\x51\xaf\x34\xd1\x2a\xa1\x49\xe6\x77\xde\x79\x7c\xd8\x24\x0b\xba\x64\x05\x07\x37\xc9\x59\x9e\x4c\x09\x20\xd4\x0d\xe6\xb3\x81\xf7\xd1\x6d\xdd\xfd\x35\x59\xd0\x50\xd4\x60\x34\x9a\xfc\x5b\x47\xb9\x6d\x2d\xc1\x61\x9f\x9b\xd0\x26\xb4\x75\x45\xd6\x84\xbe\x02\x22\xa3\xc4\x76\x99\x65\x45\xb9\x13\xe7\xf4\xde\x8d\xb3\x75\x02\xcc\x7e\x7f\x77\x58\xc1\x06\x8e\x83\x1f\xdb\xee\xef\x11\xb9\xba\xe1\xf7\x0f\xb4\x4d\x93\x17\x7e\x93\xb5\x3c\xae\x6b\x9a\x1e\x5c\xa0\x0a\x7e\x3b\x56\xa4\xf4\x2d\x9b\x72\x25\xfa\x84\xd7\xd8\x94\xa8\xd0\x6c\x60\x35\x2d\x4a\x9d\xb1\xb6\xa3\x15\x4e\x76\xd3\xca\xe6\x6b\x68\x08\x75\xd3\x86\x4f\x27\x8d\x94\x38\xd1\xce\x5b\xac\xc6\x7d\xd0\x5b\x6d\xba\xc8\xa2\x2f\xec\x20\xc7\x05\x2b\xc0\xe0\xe7\x27\x21\x86\xce\x02\x63\xdd\x32\x04\xa0\xd1\xc1\x6c\x79\x62\x6d\x99\xa6\xa3\xf1\xe2\xac\xc1\x35\x6d\x46\x5c\x52\x31\x35\x13\xb4\x31\xe9\x90\xbc\x66\x64\x77\xcb\x52\x01\x35\xad\x42\x48\x71\xb3\x0c\x76\xb1\x02\x2d\xd4\x8c\xa7\x37\x8d\xb3\x58\xc1\x46\xa8\x45\x9a\xf9\xd2\x17\x6d\xd9\xe8\x06\x91\x46\x65\x17\xd6\x76\x85\xfd\x6d\x06\x2d\xd8\x6c\xac\xd3\xde\x46\x81\x6e\x30\xd6\x8d\x17\x00\xcd\x25\xd9\x0b\xc9\x39\x89\x47\x97\xa2\x2c\x86\xda\x6c\x0e\xd5\xde\x5c\x2e\x96\x91\xa4\x7e\xbf\x6b\x82\x41\x6d\xae\x7f\x52\xe0\x0a\xf5\xde\xdc\xd0\x83\xaf\x74\x9a\x5b\x5a\x5d\x6d\x9f\xd4\x09\x6e\xa4\xa1\xdb\xc1\x87\x2e\xcd\xed\x74\x92\xd3\x0d\xcb\x74\x2b\x64\x1f\xa7\x8f\xd2\xdc\x1a\x67\x84\xb6\xe1\xa4\x53\x36\x70\xd1\xef\x96\xc9\x86\x33\x3d\x60\x5a\xda\x84\xa6\x6c\x70\x35\x90\xa1\x8e\xff\x53\xa7\x6d\xe6\x13\x99\x0c\x49\x9a\x99\x31\x4d\x9b\xb9\xb1\x06\x2b\x23\xbd\xf8\x4c\xa6\x81\x09\x33\x13\x64\x80\xe1\x09\x2e\x0b\x6d\xfa\xfd\x1d\xfe\x4d\x81\x17\xf1\x6f\x42\x0b\xfe\x9b\x52\x56\xc6\x85\x49\xb7\xf0\x6f\xd2\x6a\xc3\x31\x2f\xd0\xe8\x70\xba\x93\x20\x81\x9e\xf7\xfb\x8b\x77\x20\x1e\x37\x8d\x80\xf8\x5c\x94\xf3\xb8\x6b\x8a\x39\x38\x23\x04\xa2\xc3\x23\x28\xec\xeb\xbc\xcf\x11\x97\x06\xe7\xe1\x83\x23\x28\xdd\x99\x1b\x80\x9d\x35\x9d\x8d\x59\xf0\x09\xf0\x42\x96\x97\x9a\x2e\xff\x7b\x52\xe8\xf2\xf7\xda\xc0\x65\xbd\x6e\x71\xe1\x2b\x0e\x17\xbe\x62\x80\x29\x1c\x31\xf0\xc5\xc6\x0b\x95\xeb\x02\xd7\x25\xb9\x30\x3b\x08\x79\xbd\x07\x8d\xe9\xb2\xf3\x28\xd6\x65\x67\x0c\xe5\x72\x50\xfb\xb8\xac\xc3\x59\x97\xf5\x6a\xc7\xe5\x98\xa7\xa2\xfc\x84\xe4\x3b\x6f\x68\x5c\xce\x8c\x26\x27\x19\xcb\xe5\x71\x7f\xa3\x25\x84\x77\x1d\xc8\xd2\xb8\xb9\x64\xee\x49\xb2\x5c\x4c\x14\x6e\x88\x43\xcd\xb1\x61\xb6\x67\x70\xd2\xc1\x65\x45\x11\x3c\xdf\x77\xa9\x08\x77\x5d\x78\x68\xe4\xd4\x0b\x2e\x8d\x67\x03\x2e\x4d\x06\x4b\x9b\x71\xe6\x36\x34\x07\x97\x8e\x5f\x8a\x44\x47\x87\x42\x70\xe9\x4d\xd8\xa1\x2f\x38\x8b\x60\x89\x43\x1d\xd9\xc1\xa3\x2e\x47\xe4\xcd\xea\x59\x39\xe8\x75\x7f\x63\xa4\x8b\x8a\xc4\xe5\x33\x40\x77\x7a\xa0\xce\x74\xde\xef\xc3\x30\xef\x11\x09\x29\xa7\x47\x0c\x7e\xbf\x4f\x92\x54\x4f\x2c\x5b\x2b\x9f\x26\xb9\x2e\x6d\xcd\xd3\x68\xd7\x7f\x13\x72\xc3\x47\x33\xae\x03\xbb\x84\xea\xe1\x45\x8f\xf3\x9a\x0f\x92\x06\x00\xff\xc7\x6d\x5f\x10\x94\xb3\xf5\xba\xcd\x0d\xd4\xb4\xe7\xea\x01\x42\x19\x7d\x38\xb7\xd2\x58\x53\xf1\xc3\x3a\xe9\xc4\xb8\x35\x82\xd5\x04\xb3\xd2\xf7\x77\x63\x70\xeb\x7c\x0a\xe8\x73\xbb\xdf\x80\x58\x36\xbc\x45\x87\x88\x04\x9f\x24\x31\x4f\x01\x9c\x81\xa7\x2f\xbf\xde\xe1\x38\xf8\x44\x84\xeb\xb3\xb0\x53\xe3\x2b\x48\x9e\xb2\xfb\x1c\x68\xdb\x21\x27\xbb\x85\xce\x73\xd4\xce\x23\x9f\xce\xdb\x8d\x1e\x61\x1e\x7a\x3c\xe3\x0b\xd0\x57\xab\x1c\x01\xd6\x27\x16\xdb\x23\x44\xbd\xc7\x25\xea\x3d\xe6\xbf\xa4\xb3\xdd\x60\x83\xb9\x03\x5e\x1c\xad\x6c\xa8\xf8\x3b\xc1\xef\xb1\xd2\x1d\xea\xb1\x0a\x6b\x2b\x22\x94\x1e\x2b\x05\x87\xc7\xbc\x9d\x87\x15\x3d\x36\x00\xf8\x07\x3d\xfa\xce\x85\x47\x1f\x60\xe3\x1e\xfb\x60\x27\x3e\xa7\xe9\xbc\xe4\xe9\xf1\xc3\xf8\x3c\xa9\xff\xef\x38\xa8\x4b\x32\x00\xb0\x12\xd2\x11\x43\x97\x3d\x74\x39\x27\x96\x2f\xda\x43\xe7\x25\x7e\x97\x7c\xa1\xae\x20\x9e\xef\x52\x48\xcc\x4e\x26\xea\x52\xa1\x43\x79\x3f\x98\x99\x30\xb7\xfc\x9b\x2e\x4d\xd1\xe4\x1f\xcf\xaf\x3b\x70\x29\xae\x02\xb8\x30\xb3\x0e\x89\xbb\x74\x0a\x48\xff\x3b\x52\xea\xc2\xcc\xf8\x2b\xbc\x88\x52\xf9\x20\xc0\x4a\x15\xf6\xb8\xaf\xeb\xa2\xae\x70\xa7\xba\x9e\x58\x26\x2f\xae\xfb\xfd\xce\x11\x08\xd5\x0c\xf5\xdf\x35\x0b\x5f\x82\xf6\xb5\xea\xfb\x5d\x36\x63\xe3\xc2\x42\x87\x77\xd2\xb5\x0f\x18\xc4\xce\xe3\xa1\xae\x7c\xa6\xdc\x69\x3a\x3b\xbd\xff\x4e\xab\xd9\x2d\xe3\x17\x5b\x44\xb2\x93\xf8\x96\x79\x73\xdc\xef\x1f\xfa\x8a\xdd\x78\x29\xd7\x2d\xcf\x3f\x24\x1b\x0f\xc9\xbb\x55\x48\x42\xb7\xba\x5a\x55\x38\xc2\xdd\x2a\xa5\xa9\x1b\x47\x6c\x99\x3d\xd7\x6b\x81\xce\xab\x89\x6e\xbe\xee\x79\x3b\x0a\x91\xef\x8b\xc0\xf7\xcf\x20\x27\x4c\x04\x83\x7d\x6e\x40\xe3\xa4\x9d\xeb\x34\x44\x7d\xca\x89\x69\xe9\x89\xf6\xe5\x59\xf5\x15\xfa\xf6\x79\x38\x9b\x33\x3c\xea\x33\x2f\x26\xe1\x3d\x52\x9f\x70\xbf\x98\x92\x85\xe7\x32\xf0\x7d\x36\xaa\xb5\x3e\xf1\xed\x89\x5f\x7f\x63\xfa\xc9\x86\x9d\x63\x41\x93\x8d\xc8\x27\xea\x23\x6e\xd0\x18\x48\x73\x04\xbc\x7f\xc3\x58\x15\xd0\xe3\x7c\x0f\x3a\x22\xb6\x3c\xe8\x74\x8f\xb8\x4e\x1b\xd7\xeb\xc5\xb1\x84\x66\xc4\x42\x3b\x31\x62\x81\x84\x0f\x5a\xa1\x11\xeb\x1a\xb8\xa1\x5d\x03\x03\x8c\x08\x4e\x1b\xb1\xad\x4e\xff\xa6\xae\x41\x7c\x47\x9d\x0b\xbf\xa1\xe8\x46\xf4\x27\xd8\x6b\x44\xb7\x01\xe8\x18\xcf\x59\x32\x66\x7c\xa2\xf9\x64\xd9\x0b\x45\xb4\x5f\x43\xf8\xca\x65\xd0\x2d\x1e\x92\x30\xf2\xfd\x9d\xf8\x46\x66\xc8\x13\x6c\x30\xe4\x29\x0e\xa8\xcc\xa0\x85\xe4\xfb\xfb\x40\x24\x42\xce\x1a\x02\x65\x33\xd6\x63\x81\x21\x35\xbe\x00\x77\x76\xaa\x0b\x6a\x07\xec\xa8\x36\x5e\xbe\x21\x9c\xe0\xb6\x04\x18\x1f\xf7\xb7\xf3\xd9\xdd\x10\xaf\xd0\x58\x03\x2e\x2f\x7a\x76\xf6\xec\xc6\x35\xf6\x81\x20\x70\x08\x63\x91\x41\x81\x19\xf2\x0a\x43\xa1\xc4\x86\x6e\x93\x27\x6a\x43\xa5\x34\xe4\x29\xc4\x43\x79\xcd\x34\x14\xfc\x33\x14\xfa\x66\xe8\x93\x03\xf0\x02\x64\x28\xcf\x86\x07\x9c\x0a\xec\x0f\x7e\xd0\xe0\xa3\xaf\x01\xcb\x30\xee\x77\x83\x75\x19\xca\x21\xd9\xed\x6f\x16\xb2\xd6\xb8\xdf\x43\x56\xff\x01\xf5\x3b\x14\xb8\xb5\x45\x67\xdb\x18\xe9\x0f\x83\x62\x1d\x96\xb8\x43\xc3\x2c\x76\xa2\x3a\xf3\xb3\xb0\x92\x55\xe4\x11\x6b\x2c\x68\x12\x06\x5f\xb5\x8d\xfb\xc7\xe3\x47\x18\xc6\x30\x7f\x98\x17\x2a\x0f\x98\x48\x61\x9e\xa0\x09\x07\x73\xac\x85\xcf\x4c\x86\xf9\x98\x9c\xa6\xe3\x87\x3d\xf0\x6d\xd5\x80\xb3\x87\x9c\xc7\x8d\x7c\xea\xeb\x3e\x7e\xbd\x48\x1e\xff\xbb\x0b\x1c\x8e\x48\x72\xf0\xf6\x73\x78\x2c\xfc\x86\xbf\xb5\x4c\xf2\xf0\x08\xcf\x6e\x38\x5f\xdb\x0e\xbf\xbf\x37\xcb\x61\xc0\xbf\x45\xa9\x2c\x0c\xba\x54\x00\x6e\x08\x4e\xc0\x70\xdd\x26\x20\x87\x46\xb4\x30\x9c\xcf\xf8\x86\xeb\xac\x07\x0a\xed\x10\x26\x85\x95\xb4\x98\x83\xc6\x72\xf0\xe1\xea\x70\x38\xd5\xc3\x27\xcb\xf9\x4c\x75\xf8\x04\xf3\xcf\x6d\x5d\xeb\x8e\xb9\x59\x18\x93\x6f\x14\xc6\x84\xf9\x19\x34\x86\xe3\xfe\xad\x92\x99\x90\xb9\xa7\xf3\xf9\xe9\x98\xce\xd3\xc1\x31\xe1\x71\x0c\x3e\xaf\x9e\x1b\x23\xa5\xfb\x37\x33\x66\x9c\xd0\x72\x39\xcc\x65\xa5\xe8\x8a\xcc\xaa\x17\xe2\xb1\x30\x2b\x7e\x50\x8b\x0c\xb1\xa6\xd3\x09\x9d\xbe\x49\x98\xbe\xae\x7c\x27\x62\x2b\xfe\x0d\x64\xf6\xc9\xe7\x4a\xeb\xce\x69\x0e\xe3\xab\x8f\x79\xc5\x70\x21\x0c\xba\x62\x02\xcb\x5d\x91\x6f\xc2\x2e\x3e\xe4\xbf\x40\x85\x2b\x2a\x0b\xd6\xd1\xed\x15\xb3\x84\xeb\x2f\x7e\xbf\xf8\x6e\xea\xe2\xa3\x56\x94\x5d\x93\x2d\x4a\x83\x1f\x75\x45\x47\xc6\x95\x03\x91\x6d\x2f\x84\xc6\x97\x90\x15\xaf\x75\x59\x72\xc9\xe3\x7e\xf3\xc0\xef\x02\xd9\x24\x5c\xf2\x94\x57\xe0\x21\xd6\x25\x34\xfa\x97\x64\x43\x09\x56\x21\x7c\x11\x7b\x51\xb8\x2e\xa9\xc2\x81\x2a\xd7\x2a\x40\xcd\x45\xee\xbc\xa4\xce\x1e\x2e\xb6\xe4\xad\xf2\x25\xbe\x11\xee\x98\xc0\x85\xbd\xfd\x49\xc8\x25\xf9\x40\x63\x20\xe4\x52\x30\xdd\xa5\x1b\xb4\xf5\xc5\xa3\xa4\xeb\x7e\x27\x5e\x0c\x5d\x8a\x8e\xf7\x1b\x06\xe7\xd2\x1d\xd8\xbc\x14\x7e\x31\xef\xef\xa4\x87\x8b\x5e\xde\xa5\x19\x3f\xec\x40\x6b\x84\xd0\xf3\xc5\xd6\xa5\xf7\x7f\x90\x93\x4b\x2d\xdf\xef\x1a\x2e\x05\x61\x2f\x75\x20\x59\x7d\xcc\x3d\x5c\xda\x89\xca\x77\x67\xb0\xbe\x5c\xcd\x4b\x47\xe4\x09\xe0\xa5\x93\xdd\xaf\xf8\x02\x24\x6e\x14\x76\xfe\xd2\xcb\xc2\x65\x99\xf7\xa7\x97\x65\xba\xb3\x97\x65\x62\xc0\x1c\xcd\xe9\xd3\x5d\x08\xa7\x2f\x20\x93\xd6\xeb\x9a\x7c\x98\xf9\xc9\x0b\xec\x4f\xf8\xc7\x9f\x94\xa0\x4f\xe8\xd5\x4f\xde\x48\x7e\x42\x71\x7d\x42\x6b\x7c\x42\x6b\x7c\xda\x39\x3d\xbc\xe2\x01\x02\xbf\x78\xd4\xfa\x8a\x0d\x22\xf9\xe2\x1b\x85\x97\x55\x00\xe8\xfe\xd7\x2c\x00\xb0\xb5\xff\x1f\x00\x00\xff\xff\x11\x91\x1a\xde\x5b\x35\x00\x00") +var _keysWordsWordlistSpanishTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x5b\xbb\x76\xfc\x2e\xaf\xed\x79\x4b\x8c\x65\x8f\xe6\x00\xe2\x27\xc0\x2b\x99\xb7\x49\x99\x62\x8a\xff\x4a\x97\xd6\x2f\x76\xd6\xde\xe4\x2b\x46\x98\x3b\xe8\x2e\x60\xee\xaf\x2d\x26\x0b\x71\xdb\xad\x48\x0d\x71\x93\x67\x0c\x71\x53\xf1\x81\x52\x3b\xe3\xce\xb4\x12\xae\x42\x8f\x2f\x26\xea\x21\x6e\x53\x32\x32\xb3\x5b\x88\x29\x6e\xd1\x91\xec\x52\x34\x86\x98\x92\xb0\x38\xe9\xfd\x53\x43\x4c\xa2\x43\x90\xe4\x13\x95\x52\x31\x5a\x92\x36\xa2\x87\xfb\x2b\x29\x66\x4a\x39\x3a\xc7\xa8\xf7\x77\x88\xc9\x4e\x41\xc6\x38\xcc\xd0\x8b\x09\x81\xeb\x0b\xc9\x64\xe3\xb9\x2b\x13\x71\x8e\x31\x3b\x4a\x77\x65\xd3\xbd\xe8\x40\xed\x6e\x9c\x28\xee\xe6\xd8\xcc\x3e\x63\x8d\x48\x32\x1a\xdd\xdf\x2e\x16\xe2\x21\x89\x6d\x0e\xfd\x5b\xf2\xa1\x75\xe5\xbd\x70\x91\xa7\xe6\x10\x4f\x65\xa3\xd3\xea\xfd\x8e\x48\x3b\x86\x38\x6d\x95\xba\x9c\x2b\x55\x14\x4e\x34\x98\xbb\xa1\xef\xd4\xcc\x1c\x30\xfc\xb0\xd3\x00\xdd\x2d\x44\x75\x09\x51\x7b\x46\xbf\xa7\xec\x2e\x2f\xa4\x58\xe5\x73\x76\xa0\x2c\xc7\xe4\xf7\x57\xc5\x47\xd9\x9c\x05\x5e\x62\x88\x79\x8b\xe1\xfe\xca\xdb\x2c\x21\xe6\x14\xf3\x8e\xaa\x5d\x50\x23\x27\xdb\xc9\x13\x83\x66\xf1\xc1\x42\xc2\x43\x33\xb0\x4a\x2a\xe4\xd3\x76\xee\x34\x2b\x29\x9d\x75\x91\x25\xeb\x85\xf5\x67\xce\x52\xc8\x14\xb9\xdc\x6f\xd2\x37\x8f\x05\xe5\x85\xd2\x45\x15\x62\x31\x8f\xe9\x28\x9a\x05\x6b\xcf\x2f\x34\x2b\x71\xcb\x82\xa4\x0e\x26\xcd\x80\x84\x12\x1d\xfb\x2f\xb1\x13\xad\x65\xfb\x4b\x14\xc3\x14\x6e\xbd\x28\x5b\x68\x1f\x71\x0f\xb1\x18\xc6\x6a\x11\xe8\x2a\x2d\x63\x6d\x35\x3d\x08\x35\x56\xa6\x18\xb7\xee\x98\xb3\xee\xf7\x77\x0d\xb1\x92\x0b\xef\xaf\x7a\x4e\xf0\x68\xd5\x9c\x41\x87\xaa\x05\xb9\xfb\xdd\x43\xac\x8b\x68\x75\x08\x98\xa1\x0e\x3d\x27\xea\x86\x3d\x91\xcc\x98\x01\x49\x97\x3a\x6b\xc2\xac\xf7\x7f\x91\xcc\x76\xff\x27\x4f\x66\x2d\xc4\x16\x49\xf2\x16\x3d\x62\xfd\x4d\x06\xf7\xd1\xd0\xbe\x65\x4d\xac\x34\xa0\xb7\x99\x03\x0d\xcd\x3e\x91\x71\xa9\x3b\x28\xd1\xdc\x88\xd8\x36\xa5\x83\x42\x6d\x62\x9b\x4e\x82\x38\x66\x0c\x14\x8a\xfb\xcb\x37\x1d\x6e\xfc\xb0\x1c\xa2\x6f\x93\xac\xe7\xe9\x41\x22\x38\x24\xd9\x39\xa4\xef\x9a\x81\x10\xdf\x27\xdb\x0b\x10\xe1\x14\x31\x57\xe9\x21\x7a\xf9\x63\x5f\xaf\xf7\x37\xf2\x06\x52\x7b\x23\x20\x47\xb8\xcb\x09\xbc\xb9\xdb\x0b\x70\x82\x5f\xb8\x7c\x1f\xca\x75\x76\xfe\x30\x66\x5f\x0c\xd0\x93\x54\x88\x6a\x97\x73\x52\x8c\xbb\x30\xd7\x41\xbd\xfe\xc7\x5a\x5d\x33\x61\xa7\x58\x76\x10\xaf\x5b\xd9\xb8\xaf\xde\x04\x5b\xef\x63\xad\xbe\x8f\x95\x9b\xec\x37\x0b\x3b\x4c\x8e\x32\xe2\x93\xf0\xdf\x14\x24\x1e\xe2\x58\xc3\x0f\xc1\x40\x43\x81\x8b\x41\x8e\xbf\xbf\x86\x81\xe4\xc3\x23\x50\x33\xb8\x9f\x71\xff\xd6\x10\xe7\x1e\x5f\x80\xa0\xd4\x3c\x25\xc4\x89\x69\x67\x59\x43\xcd\x2e\xe4\xda\x39\xb0\xfe\x0b\xdc\x70\xc5\x9a\x04\x09\x16\x76\xe1\x4b\x72\xa6\x26\xb9\x64\xc1\x3e\x7c\xbe\x42\xbc\x96\x02\xb9\x14\xf8\xf8\xc4\xbc\x9f\x73\x8f\x80\xd8\xf0\x2b\x1e\x4b\xa0\x29\x23\x2f\xc3\x2c\xaf\xfb\x97\x9c\xf2\x9a\x07\x44\xf7\x35\x73\xd8\xe2\x16\x01\xcc\xc3\x16\xd3\x43\xc2\x16\x1f\x20\xda\x16\x35\x23\x03\xe1\xde\x62\x8e\xf5\x85\xb2\x9c\x30\xe5\x46\x35\xb0\xc5\xb2\xdd\xbf\x61\x8b\x35\x19\xe0\x8e\x06\x60\xd6\x2d\x3a\xc7\x74\x96\x7b\xd5\x17\x12\xb7\xb0\xdd\x5f\x3d\x61\xfb\x5b\xec\x63\x0d\xd4\x21\xce\x5b\x1c\x31\xb3\x78\x88\xaf\xc9\x41\xb8\x2d\x8e\x39\x38\xe8\x2f\xd6\x89\x7d\x6c\xb2\xdd\xdf\x80\x8a\xd9\x04\xd2\xb6\x49\x67\x45\xe7\xe7\xd0\x18\x36\x85\xd8\x6e\x2a\x35\x6c\x5a\x4f\x0b\x5b\x5e\x6b\xcc\x06\x52\x6e\x79\xf6\x18\x36\xc3\x6f\xd3\xca\xc4\xc2\x66\x09\x5f\x69\x15\xec\x04\x72\x22\x59\x25\x99\x00\xac\xb3\x59\x66\xff\x82\x4d\x5a\xdd\xe3\x8e\x04\xe2\x48\x1b\xb6\x59\xed\xf7\x97\x86\xcd\x1c\x48\x32\x07\x97\x6e\xd6\x39\x35\xa8\xb0\xd9\xb8\xdf\x35\x6c\xf7\xcf\x25\x9c\xe7\x15\x73\xd8\x3c\x5e\x16\x96\xdd\xdb\x5c\xd2\x23\x22\xb9\x24\x6c\x4e\x9d\xb2\xb9\x72\x0b\xae\x98\xdb\xb9\x58\xca\xd3\xe6\x06\x76\xd9\x9c\x43\x3b\x34\xff\xe6\xb3\xb3\x2d\x78\x7a\x9b\x49\x08\x41\xcd\x09\xb5\xb7\x4d\xf9\x0c\xdb\x3c\x16\xc5\xe6\x41\x42\xdc\xbf\x40\xd9\xd4\xe1\x68\x96\xd9\xd1\x37\x8e\x36\x3d\x13\x62\xeb\xb3\x83\x7f\xb6\x39\x22\x16\x30\x5f\xe8\x0b\x93\x8c\x25\xa6\xb8\x41\x5d\xa7\x48\xa4\x26\x18\xf1\x90\x62\x8a\xa8\xd9\xef\xaf\x4b\x1c\x1f\xc2\x3a\x7e\x1f\xf7\x77\x48\xf1\x7e\xef\x28\xd1\x02\x66\x4d\xf1\x89\xcc\x73\x8d\x9b\xf1\x83\x22\x47\x0a\xd5\x08\xfb\x43\xa8\xc0\x7a\x8a\x39\x0b\x60\x41\x9f\x6c\x6c\x76\xa1\x9e\x05\x65\x63\x8f\x22\x6b\x71\x45\x2b\x93\x66\x21\xdd\x5f\x35\x71\x09\x75\x57\x4c\x52\x25\xa3\x47\x3d\xa1\x15\x53\xac\x9a\x98\x1d\xc8\x40\x37\x02\xae\x25\xd9\x86\x9c\xf5\x90\x62\x8b\x2f\x40\x1d\x6b\xe1\x0d\x04\x48\x91\x1e\x40\x8a\x6d\x82\x84\x29\x12\x07\xbe\xb1\xf3\xfd\xe5\x49\x30\x9d\x43\x65\xa4\xe8\x27\xa1\x42\x66\x52\xf4\x8a\xee\xde\xfe\xea\xb8\x10\xe7\x77\x27\x48\x28\xe8\xc2\xf2\xde\x58\x34\xb8\xe5\x61\x9e\xd0\x15\xa4\x4b\x50\x37\x98\x62\xb2\xd3\xcb\x42\x92\xcd\x20\x5b\x49\xa0\xb4\x93\xec\x18\x40\x32\x70\x7e\x7f\x67\x81\xa9\x4f\x92\xe1\xfd\x20\x3f\xd9\x72\xe9\xa6\x24\x55\x41\x4f\xa9\x83\x7d\x1c\x48\xa1\xfb\x93\xc4\x49\x69\x59\xe5\x60\xf0\x24\x4e\x63\x9d\xee\xef\xde\x64\x0f\x49\xd8\xe9\x11\x49\xc5\x47\xcc\x92\x98\x2d\xed\xfe\x45\x4a\x5b\x9a\x1e\xb1\x11\x3a\x33\xca\x26\x0a\x77\x64\x59\x9b\xf4\xa0\xc0\xa6\x87\x61\xe4\xc7\xa4\xaa\x4d\x8f\xd9\x30\xa1\xa6\x4c\xac\xaa\x9c\x06\x98\x09\x59\x00\x1f\x32\xe9\x01\xdc\xeb\xb9\x50\xa9\x60\x09\x8a\x50\x52\x20\x5a\x2b\x86\xd2\xe6\xb0\x4c\x49\x9d\x15\x3e\xc9\x07\xda\xd9\x82\x0d\x26\x19\x2d\xd3\x39\x48\x39\x56\x00\x8c\x97\x63\x17\xc0\x0b\x50\xa9\xc3\x53\xe6\x24\xf9\x7e\x2f\xfe\x31\xe2\xd6\xfe\x5c\xd3\x64\xe9\x41\x0e\x5c\x2a\x26\x19\x66\xbc\x7f\x76\xb8\x20\x09\x86\x3b\xd9\xc1\xf6\x70\x47\x93\x3d\x04\x23\xda\x13\x9a\x22\xc1\x55\x48\xd0\x40\xc9\x32\xd9\xca\xb2\x9c\xca\x32\x78\x05\xc9\xf2\x1a\x32\xe7\x95\x2b\xac\x9a\x85\x85\x05\x5a\x15\x29\xc7\x2d\x4a\xca\xff\x94\x35\x65\x69\x40\x92\xd5\x1d\x2d\xaa\x70\x9e\x7a\xb2\xc8\x28\x21\x56\xfb\x5f\x29\xf9\xda\x40\x2f\x6b\x0a\xe8\x71\x89\xbf\x39\xf4\x37\x52\xa8\xdd\x64\xbe\xff\x15\x1b\xe7\x77\xe7\x38\x7d\xc1\x02\xd1\x31\x98\x76\xba\x9b\x62\x4c\x07\x2a\x5d\x22\x61\x5a\x99\xfb\x8d\x15\xba\x14\x36\x7d\x03\x2a\xe2\x87\xe4\xda\xd8\x5d\xbb\xf6\x90\x1c\x76\x37\xf9\xfd\xb3\x90\xee\xe0\x18\x56\x4f\x76\x9f\xaf\x90\x66\x24\xd3\xcf\x48\xbe\x98\x91\x9c\x39\x37\x02\x44\x18\x09\xb2\x0a\x3c\xcc\xa5\x2a\xe6\x62\x7f\xb8\xfa\x2c\xe4\x6a\xa7\x5c\x80\x0a\xef\x2f\x4d\x08\x0e\xb2\xb9\x11\xb2\x39\xdd\xe6\x34\xe1\x3a\xa2\x09\x36\x3f\x2b\xd7\x32\x8d\xb0\x2d\x2d\xf0\xdb\x28\x65\xf4\x5e\xd2\x74\xa5\xec\x4d\x5f\x90\x93\x0c\xed\x61\x87\x12\xdb\x69\x76\x31\xe5\x1e\x21\x78\x3b\xbc\x8e\x1c\x76\xd9\xc4\xc3\x7e\x7f\x6f\xc8\xdc\xdf\x29\xee\x31\xec\x92\xd4\xc3\x2e\x68\x26\x87\xd4\x8e\xa2\x43\x2b\x0b\x61\xc5\x77\xc9\x07\xd8\x69\x47\x70\xc4\x56\x19\x46\x6b\x97\x62\x8e\xb6\x70\xab\x76\xa9\x23\x62\x82\xe5\x45\xee\x02\x53\x84\x62\x77\xec\x61\x97\xbe\xbc\x8b\x5d\xe0\x76\xed\xd2\xe1\xe8\x23\xad\x93\x23\xf6\xa1\xab\xf6\xba\xdf\x48\x07\x55\xf4\x2e\x43\x2a\x56\x2c\xf0\x4f\x76\x10\x73\xd7\xb8\x65\x43\xb2\x83\xc2\xbb\xfe\xb9\xef\xbb\xc2\xd3\xd9\x35\x22\xb6\xd9\x75\x9b\x4f\x24\x0c\x99\xf6\x25\x66\xbb\x02\xa7\xbb\xca\x2b\xec\x7a\xdc\xef\x04\x1c\xe8\x89\x69\x35\xaf\xb1\xf2\xc4\xa6\xb5\x42\x3f\xed\xea\x82\x20\x6d\x57\xd7\x93\xc5\xd0\xa4\xbb\x76\x81\xda\xdd\xb5\x1f\x1e\x31\xd2\x85\x8e\x17\x57\x6f\x08\x27\x76\x4b\x00\xb0\x2a\xbb\x15\xba\x11\xbb\x55\xfc\xb0\x14\xa3\xe7\xbc\x9b\xc3\x5f\xdc\x0d\xc4\xdb\xad\xe3\x07\xd2\x79\x3c\x41\xea\xdd\xed\x8c\x61\xa7\x25\xd8\xb9\x73\x46\xb2\xfb\x5c\x53\xcf\x8c\x19\xee\x5f\x7c\x42\xcd\xed\xe4\x88\x7d\x52\xb7\xee\xb0\x44\xf7\xf7\x86\xc0\x43\x36\x20\x03\x3e\x81\x07\xa8\x51\x01\x47\x9b\x07\x81\x6e\x92\xfd\x2f\x90\x94\x5d\x11\x53\x1a\x3e\x06\x6b\x27\x6c\xb5\x1c\xdc\xbe\x1c\x9a\xe2\x2b\xc8\x53\xf0\x2b\x2d\x5b\x90\x2c\x07\x71\x2e\xd0\x26\x8e\x64\x29\x7e\xc9\x72\xa1\x67\xd6\xd6\x25\xdc\xdf\x59\xd9\x48\x3f\xd8\xc8\xa0\x79\x24\x33\x1e\x96\xb2\x81\xee\xb2\xe2\x5f\x29\xf6\xb7\x94\xd2\xa0\x73\xa4\x34\xee\x14\xd3\x09\x13\x97\x1e\x83\x54\x6e\xaa\x26\x06\x68\x52\xd3\x63\x1e\x82\x14\x7c\x21\x88\xa8\x58\x0c\xe2\x49\x3d\x80\x67\xa9\x87\x78\x41\x7a\xd2\xc1\x94\xaa\x67\x41\xdb\x1c\x13\x7a\x9a\x17\x24\x2e\x6c\xdb\xe3\x27\x13\xb9\xff\xc3\x2e\xea\x58\x23\x0d\x67\xee\x82\xe2\x96\x4a\xfe\xbc\xbf\x1b\x1c\x29\xf9\x37\xb5\x59\x10\xd7\x97\x05\xe9\xf0\x39\x90\xc0\x53\x91\x0e\xbd\xeb\x48\x5d\x37\xe5\x07\x77\xdc\x05\x51\x61\x90\x7e\x88\x33\x99\xe2\xec\xdd\x20\x8b\xd2\x1b\xb4\xa6\xf4\xc6\x3d\xf5\x66\x9d\xc9\xc4\xaa\xfb\xbf\x79\xbf\x03\xb4\x0a\x86\x03\x9e\x10\x8b\xa0\xf5\x98\x47\x0c\x32\x60\x14\x65\x88\x57\xac\x70\x40\xad\xc9\xa8\x98\xec\x62\x5c\x28\x57\xcc\x13\x7d\xaf\x45\xad\x8b\x67\x05\xf2\xc1\x63\x0b\xf9\x40\x6c\x1b\xe4\x83\xe7\x22\xf2\x91\xe0\x08\xc8\xc7\x6a\xf9\x41\x09\x90\x0f\x45\x70\x2b\x1f\x2b\x3c\xba\xbf\x3f\x94\x95\x8d\x76\x53\x3e\xfe\xc2\x49\xf9\x68\x06\xa1\x95\x8f\xe1\x52\x2c\x1c\xf7\xd7\xe6\x58\x0c\x3e\xa0\xc1\x8e\x98\x1e\xd8\xec\x71\x7f\x41\x06\x0f\xcc\xef\xe1\x88\xc0\xdb\x01\x3f\xee\x88\x70\x33\x0e\x3a\x87\x47\xcc\x9d\x10\x6b\x3d\xa0\xdb\x8e\x58\x34\x2b\x53\x63\x95\x47\xf0\xce\x11\xbd\xc4\xc4\x72\x37\x8c\xea\x1d\xdf\x5d\xc2\x11\x87\x9e\xf8\x9e\x9c\xe0\xe2\x64\x1f\xe1\x80\x0f\xe3\x16\x0e\x3a\xcd\x87\x64\x7d\x85\x43\x90\x77\x8c\x22\x08\xc5\x8e\xfb\xdb\xa1\x38\x0f\x71\x76\x93\x4e\x17\xfc\x50\x9e\x1c\x1c\x4a\x35\x7b\x28\x96\xa6\x50\xec\x87\xfe\x59\xed\x43\x39\xa8\xee\x18\x50\xe9\x2d\x1d\x2a\x19\x80\xcd\x68\x1b\x0e\x45\x28\x1a\x0e\x7d\x72\x80\x27\x9a\x02\x3f\x9a\x61\xc4\x0f\xec\x12\x3d\x32\xec\xce\xa1\x18\xb4\x02\x8d\x5a\x41\x0d\x68\xe8\x81\x72\x07\x4e\x72\x4c\x06\x88\xb8\xe7\xc8\x6b\x47\x50\x41\x47\x36\x96\x40\xb1\x1d\x19\x4a\xf1\xc8\xf7\x2f\x2a\x6c\xc3\x2e\xc1\xc6\x87\x9d\xb0\xc3\x87\x51\xf9\x1c\x06\x22\x1f\x96\xb3\x60\x78\xab\x3b\x20\x27\xe1\x89\xd0\x61\x3e\x88\x48\x73\x04\x56\x07\x38\xf4\x30\x34\xf5\x98\x22\x08\xe2\xeb\x2c\xea\xf0\x58\x41\x4c\x27\x0d\x3c\xce\x1d\x89\xdc\x6f\x47\x52\xd1\x10\x52\x7d\x38\x24\xea\x70\x6e\xc6\xb9\xfe\x09\xcf\xec\x98\xd4\xda\x94\x0f\x94\x81\x82\x13\x2e\xfd\x31\xeb\x1f\x8e\x27\x02\x91\x63\xfa\x5a\xf7\x24\xd9\x66\xc7\xd4\xf7\xef\xd8\xc0\x04\x73\x40\x1d\x9e\x31\xc1\x3f\x3b\xe3\x11\x7b\x38\x23\x1c\xb4\x13\x21\xfa\x19\x59\x9a\x57\xec\x78\x92\xdf\xce\x88\xf0\xec\x8c\xd0\xd6\xe7\x3a\xc7\x39\x23\x3c\x9b\x33\xc2\xce\x9d\xd1\xe3\x53\x90\xbc\x50\xd4\x97\x07\x75\x46\x0a\xe5\x19\x07\x5a\x5c\x9a\xe1\xd9\x9f\x52\xa0\xb5\x4f\x81\xaa\x3f\xa5\x86\xf3\xfe\xa6\x72\x3a\xa5\x2a\xe1\x90\x70\x8a\xc7\x95\xf3\xff\xe5\x21\x86\xa7\x74\x0c\xa5\x27\xf5\xec\xa9\xa5\xc6\x8e\x56\x0a\x5d\x74\x2a\x06\xc9\x60\x76\x0f\x67\x46\x10\x7a\x66\xc3\xee\x4f\xcb\xf8\x1d\x06\x08\xe1\x38\x2d\x37\x09\x27\xe2\xbd\xd3\xe0\x08\x9c\xe6\x60\xb1\x13\xd1\x65\x38\xc1\x1b\xa7\x0d\x41\x39\x88\x79\x3a\xe4\xf2\xf4\xfb\xeb\x80\x4f\x7d\x3a\x14\xee\xe9\x08\x24\x4e\x8f\xf0\x2e\x4e\x87\xe7\x7a\x3a\x6d\xe9\xb9\x42\xcc\xd3\xb5\xb1\x0c\xd5\x20\xe3\xe9\xd6\x0d\xa3\xdd\xbf\x68\x34\xa1\x51\x4e\x9f\x85\xb0\x59\x38\xe7\xda\xd6\x8c\x2b\xe3\x3b\xd6\x3e\x85\x6b\x9a\xa4\xc5\x64\x70\x73\x4e\xb5\x0a\xd8\xf9\x3d\xe2\x6a\xd1\xb9\xac\x49\x9c\x3f\x22\x5c\x9a\xc7\xfd\x05\x97\xe6\x11\xb7\xcc\x32\xb8\x82\x0f\xa8\x99\x40\x4d\xf3\x88\x79\x95\x17\x84\x9f\x8f\xe8\x20\xda\x23\xbe\xf0\x63\x9c\xf6\x90\x8d\xa7\x3a\x0f\xba\x67\x0f\xfa\x2e\x0f\xc9\xb0\x21\x0f\x81\x3c\x3c\xa4\xac\x1a\xf8\x7d\x0f\xf1\x82\x25\x3c\xee\x6f\x37\x41\xf6\x42\x29\x43\x89\x87\xc2\xe5\x09\x8f\xfb\x4d\x5f\xe9\xa1\xa7\x4a\x95\xf0\x80\x74\x3f\xb4\xa0\x97\x22\xfe\xd2\x18\x1e\x96\x80\xe5\x87\xc1\x17\x7f\x18\x10\x80\xc2\x27\x00\x7d\xc2\x87\xc1\x7b\x78\x58\x35\xd4\x57\xd6\x2e\x50\xa0\xd0\x1e\x3c\x2d\x7e\x18\xac\x40\x78\xd8\xa7\x85\xc7\x84\x99\x7f\x4c\x9e\x62\x3f\x26\x4f\x56\x1f\x44\xff\x63\xca\x05\x08\x2f\xfe\x01\x65\xf0\x98\x7f\x5b\xf8\x2d\xb0\x7e\x8f\x59\x34\xef\x82\x14\x99\xba\xb3\x89\x47\x44\xbc\xf8\x18\x16\x14\xbe\x7d\xd0\x5d\x62\x0e\xba\x2b\x78\x0a\xae\x76\xb6\xa0\x67\x96\xae\x11\xe9\xfd\x1b\xf4\x9c\x68\x91\xe5\x64\x32\x3b\x85\x55\x4b\x84\x0c\xac\x68\x5d\x0b\x4d\x8f\x96\xb6\xa0\xc0\x4f\xd1\xb2\xec\x86\x96\x36\xa1\xf3\xa1\xec\x10\x2a\xdf\xef\xba\x6b\x92\x00\xb7\x6c\x20\xa1\x22\xd5\x7a\xd0\x7a\x6b\x5d\xe2\xa4\x95\x3e\x8c\xd6\x42\x7f\x54\x6b\x99\x15\xb5\x15\x32\xa9\xb5\xd3\x99\xd1\xda\x07\x59\x4f\x61\xdc\x11\xc1\xdd\xef\x3a\xb4\xa0\x66\x00\x2b\x5a\xef\x5f\x60\x53\xeb\xa5\xb4\xa3\xea\x31\x28\x38\x5b\x7d\x9d\x49\x6a\xcf\x04\x08\xda\x9f\x71\x8b\xf9\x7e\x23\xc5\x16\x9f\xb1\xac\xc4\xe3\x86\x4a\xdf\x61\x2b\x9e\x64\xda\x27\x4f\xef\x9e\xf1\x55\x58\x26\x87\x84\xa7\xb8\x42\xb1\x3c\xb5\x42\xdd\x3f\xcd\x2b\x78\xf5\x69\x6e\x1b\x92\x4b\x6a\x78\xda\x67\x0c\xcf\x29\x88\xf8\x9f\x53\x2e\xe9\x48\x5e\xe1\x39\x4f\x7a\x72\xcf\x79\x1a\xc0\xe4\x08\x93\x28\x78\x4e\x44\xab\xcf\x59\x4f\xcc\x38\xeb\x2a\x02\xbe\x9f\xf7\x6f\x53\x84\x4c\x4f\x7a\x8c\x4f\x9e\xd0\x3e\xe7\x25\x55\x73\x78\xce\x17\xf8\xf0\xff\xe0\x51\xfc\x9f\x41\x33\xe6\xb8\xa9\x05\xe8\x19\x42\x47\xc9\x8e\xcf\x1d\x51\x53\xc8\xf1\x64\x60\x94\xef\xaf\xd3\x11\xc1\xe6\x78\xc2\x30\xe4\x08\xae\xce\x11\x71\x63\xbe\xbf\x0a\x64\x0d\x69\x8b\x1c\x81\x2d\x2a\x44\x33\xc7\x7a\x32\xa2\x5b\x87\x84\xf9\xfe\x6a\xfa\x0a\x99\xde\x5d\x8e\x88\x68\xf2\xfd\xd5\xc7\x1a\x7a\x30\x37\xe4\x03\xdf\xea\x21\xc7\xe9\x92\x43\x8e\xf0\x38\x73\x7c\x59\xc8\x60\xcc\x2c\x7f\x06\x18\x36\x50\x00\xe1\x5b\x64\xc1\x5a\xe4\xfc\xab\x39\x57\xc8\x95\xe5\x09\x11\xc8\x52\xcf\x19\x91\x60\x33\x70\xfe\x00\xd9\xd0\x1a\xa3\x27\x70\xf7\x2a\x18\x9c\x62\x60\x23\x72\x61\x84\x4f\x81\x0d\xca\xba\x41\xd6\x76\x7c\xb8\x85\xac\x09\x93\xde\xef\x1d\xd3\x2a\x82\x92\x80\x58\x1f\x8b\x84\xe0\x66\x3d\x85\xcd\xb0\xb3\xfb\x5d\xe0\x26\x67\x25\xf3\x64\x2d\x0d\xe8\xd6\x9a\x50\x06\xe3\x9b\xef\x77\x15\x74\xaa\x50\xd5\x48\x59\x0f\x3f\x8f\xdd\xff\x4d\x45\x2b\xe8\xc8\xcc\xb3\x6f\xb8\xdd\xce\x84\x23\xc1\x7b\xc8\x20\x16\x60\x21\xe4\x4e\x79\x06\x91\x33\xaf\x84\x72\x96\xba\x12\xa2\x33\x9b\xaf\xe4\xc2\x06\xf2\xbc\x34\x06\xda\x99\xfc\xe7\xa8\x67\x4b\xcc\xc0\x7d\xc9\xf7\xcf\x09\xf7\x2e\xdb\x89\x99\xa0\xba\x40\x46\x84\xd7\xd9\xe0\x01\x50\x56\x32\xa3\x99\x3c\x11\x6b\xe6\xc9\x39\xe1\x8d\x64\x72\xcc\xac\xd2\x43\x9e\x0d\x9f\x3c\x57\xcf\x13\x2b\x9c\xaf\x50\x62\x82\xa5\x29\x11\x1a\xb9\xc4\x1d\x1b\x2b\x71\x77\x01\x84\x6d\x2f\x51\xd8\xa3\xc4\x43\x51\x75\x2e\x88\x82\xfb\x8d\xfe\x19\xc1\x4e\x59\xf7\x4b\x85\xa7\xc5\x25\x66\x54\x97\xfb\x0b\x70\xe3\xf7\x1c\xa1\xf0\xac\xb7\x44\xe0\xbc\xc4\xca\xd0\xb7\xd0\xf4\x97\x58\x95\xbe\x77\x81\x47\xc3\x52\x36\xe9\x84\x1c\xf7\xfe\x0f\x8c\x5d\xe0\x81\x97\xfb\xeb\xdf\x54\xe6\xd0\xd4\x39\xa8\x0b\xf3\x87\x66\x24\xd0\x84\x25\xf2\xca\xa3\xdc\x5f\x5e\x8c\xa5\x94\xaa\x12\x7d\x48\x47\xf2\x42\xbf\xce\xf1\x3a\xcf\x03\x4b\xec\x7a\xa1\x70\x70\xe0\x41\x3f\xb5\xc4\xa1\xd8\x26\x2f\x1d\xcb\xfd\xf5\x01\x6d\x56\xe2\xa7\xa1\xc9\xcb\x3c\xc5\x50\xe8\x0e\x16\xd9\xd7\xee\x65\x57\x4c\xfb\xbd\x4f\xe6\x9e\xba\x4a\x9f\xe8\x21\xe0\x03\x24\x5c\x0a\x02\x7c\x4c\x81\x40\x09\xb0\xc3\xf5\x29\xf4\x53\x8a\xd4\xfb\x37\x14\xf1\x04\x95\x50\xe0\xbd\x9c\x53\x30\x2c\x3d\x80\x82\x2d\x48\x5f\xa3\x00\x41\x08\x4b\x50\x3b\x8c\xcd\x49\x31\x79\x25\xcc\xac\xb0\x3f\x05\x3a\xbd\xa8\xf0\xae\x85\xd6\xad\x00\x55\x9a\xe3\xc9\x82\x4c\x83\x51\x34\xaf\x95\x71\x93\xc4\xf1\x0a\xd6\xa1\x55\xff\xca\xc0\x39\x45\xad\x49\x28\xf4\x96\x8a\x02\x87\xda\x17\xb6\xb4\x73\xd8\xce\xb6\x90\xd8\xc2\xe5\x5a\x7a\xc0\x2d\xfa\x5f\x1c\x5a\x6c\x47\x66\x87\x41\x2f\x06\xce\x33\xd2\xdd\x60\x22\x8b\x65\xe1\x37\x04\xb1\xd8\x0a\x7d\x8b\x15\x0c\x8f\x20\x3f\x31\x15\x8e\x00\xf6\x2f\xb6\x1a\xc0\xa1\x29\x46\x0f\xab\x18\x6f\xc2\x8a\xd1\x0f\x06\x96\x99\x71\x7e\x77\xd6\x43\xd3\x14\xeb\x1c\xac\x33\x04\x2d\xc6\xeb\xcc\x42\xa1\x2c\xf7\xcf\x85\x9d\x18\xb8\x64\x52\x38\xe6\x8e\x46\x53\x10\x99\x14\x1e\x48\x96\x49\x8b\x59\x26\x44\x04\xd9\x13\x72\x33\x9f\xe8\x4f\xe2\xaf\x83\xd1\x32\x33\x21\x19\x7f\xde\xff\x09\x26\x9d\x8e\x05\x50\xc2\xee\xdf\x9e\x26\x30\x31\xbb\x10\x9e\xab\x50\xd9\xae\x67\x0b\xf5\xfe\x42\xe4\x57\xe3\x42\x1f\xec\x18\x72\x70\x0b\x6b\x5c\x61\x40\x8d\x60\xd0\x1a\x79\xe8\x5b\x63\x8f\x39\xd4\x38\x16\xc4\xb6\x6a\x1c\x9c\xb2\xde\x5f\xb3\x0b\xda\x5f\xac\xbc\x30\xc4\xc5\x63\xfb\x2a\xb0\x44\xf5\xfe\xe6\xa9\x4e\xa5\xe2\xaa\x72\x1a\x4b\x05\x7c\x52\xa9\xb7\x2b\xfc\x31\x64\x06\xc0\x1c\xac\xb8\xd8\xf8\x82\xfe\xa8\xbc\xe6\xa9\x90\xbe\xaa\xb2\x65\x94\xb0\xad\xde\xff\xc9\x8b\x09\xa6\x79\x8f\xd5\xe2\x92\x1c\xaa\x6d\x59\x5e\x31\x54\x83\x55\xa9\xf7\x0f\x99\xaf\x52\x3c\x2a\x83\xa3\xca\x73\xaf\x0a\x8f\xba\xda\xd0\xc4\x8a\x0b\xce\x47\xb5\x0b\xc4\xa8\xc6\x45\xcd\x4d\x42\x9d\x29\x86\x7a\xff\xa6\x2c\x28\xd9\xe9\x45\xf3\x20\xac\xd2\x07\xac\xb0\xf4\x80\xaf\x50\x27\xd1\xfb\x5b\xc0\xe5\x75\x0e\x4c\x68\xb1\x6b\x0f\xc6\x9b\x2b\xdb\xb4\x37\x24\x4f\xec\xc0\xe0\xa3\xda\x0a\x6b\x6d\xeb\xe2\xd8\xb5\x6d\xeb\x10\xcd\x36\x2c\x00\x01\x9f\x31\x4e\xb3\x74\x7f\x43\x91\x61\x4b\x50\x62\x06\xac\x10\x99\x96\x5c\x82\xa5\x11\x2f\x7c\x8f\xb9\x31\xcb\xd3\x4a\x4b\x3c\x44\x87\xe6\x07\xd3\x1a\x6d\x9b\x41\xa3\xd8\xae\xa0\x9b\xf1\x64\xc2\xd6\x39\xa2\x1d\x74\x41\x6d\x9d\x2f\xd9\xb1\xce\x68\x69\x27\x8c\xc7\xb4\x86\x68\xd0\x9e\x16\x2c\xc7\x60\x59\x20\x1c\x96\x0f\xa0\xcd\x32\xd8\x82\x57\x10\x3c\x98\xe6\x89\x9a\xe5\x0b\x44\xb1\xb2\x65\x3d\x2d\x18\x8c\xaf\xc1\x79\xb0\x86\x00\xd8\xda\x62\xc0\xfb\xa7\x01\x8f\xd6\xf8\x44\xc2\x96\x5f\xb9\xde\x58\xdc\x3f\x8d\x27\x23\xc6\x0b\x6d\x0b\xe6\x7f\x4c\xcb\x93\x39\x47\x92\xc3\xfd\xe3\x1b\xa2\x44\xaa\x4f\xc8\x2a\xaa\xe5\x19\x51\x71\x12\x67\x7e\xc2\x19\x34\x3f\x27\x68\x67\xbe\x8e\x18\xcd\xf5\x64\x5b\xea\x54\xc3\x36\xfd\xdf\x3a\x07\x36\xde\x51\x5b\x8f\x3c\xc5\xb4\x9e\x20\x5a\xd6\xe5\x85\xd1\x40\x0d\x8a\xa8\x0d\xaa\x09\x03\xcf\xda\xb5\x66\xbc\xc0\x02\xf7\xcf\x07\x37\xfe\x71\xbf\x4f\xe8\x0c\xfb\x5c\x13\xbe\xe0\x93\x37\x9e\xe0\x34\x9a\xc5\x16\x05\x73\x37\xc4\xe0\x35\x86\x06\x53\xd8\xe2\xfd\xee\x28\x7a\x46\x47\x2e\xf3\x8a\xad\xc5\x9c\x98\x83\x0e\x68\xf7\x57\xc6\x04\x8d\x97\x62\x2d\x66\x5b\x09\x88\xdd\x62\xc5\x2f\x66\xb4\xaa\xca\x4e\x95\x2e\x46\x8b\xf7\x7f\x3c\x9a\x6c\xb1\xdd\x5f\x80\x92\x01\xb9\xfd\x16\xff\xd1\x2d\x6d\x7c\x20\xd0\xa2\x33\x08\x6f\xd1\x65\x07\x54\x96\x19\xc6\xf4\x16\x39\x35\x70\xc5\xbc\xc7\x83\x79\xf6\xee\xec\x0d\xd5\xd3\xe2\xf2\xc3\x1a\xd8\xb7\x21\xe6\x0e\x2d\x2e\xa0\x28\xa0\x74\x34\x5e\x61\x35\x9e\x84\x34\x70\x70\x8b\x9f\x6c\x2f\x91\x57\xc7\x4d\x68\xb2\x1a\x58\x31\x22\x79\x20\xb3\x63\x77\x82\xa8\xa7\x51\xaf\x34\xd1\x2a\xa1\x49\xe6\x77\xde\x79\x7c\xd8\x24\x0b\xba\x64\x05\x07\x37\xc9\x59\x9e\x4c\x09\x20\xd4\x0d\xe6\xb3\x81\xf7\xd1\x6d\xdd\xfd\x35\x59\xd0\x50\xd4\x60\x34\x9a\xfc\x5b\x47\xb9\x6d\x2d\xc1\x61\x9f\x9b\xd0\x26\xb4\x75\x45\xd6\x84\xbe\x02\x22\xa3\xc4\x76\x99\x65\x45\xb9\x13\xe7\xf4\xde\x8d\xb3\x75\x02\xcc\x7e\x7f\x77\x58\xc1\x06\x8e\x83\x1f\xdb\xee\xef\x11\xb9\xba\xe1\xf7\x0f\xb4\x4d\x93\x17\x7e\x93\xb5\x3c\xae\x6b\x9a\x1e\x5c\xa0\x0a\x7e\x3b\x56\xa4\xf4\x2d\x9b\x72\x25\xfa\x84\xd7\xd8\x94\xa8\xd0\x6c\x60\x35\x2d\x4a\x9d\xb1\xb6\xa3\x15\x4e\x76\xd3\xca\xe6\x6b\x68\x08\x75\xd3\x86\x4f\x27\x8d\x94\x38\xd1\xce\x5b\xac\xc6\x7d\xd0\x5b\x6d\xba\xc8\xa2\x2f\xec\x20\xc7\x05\x2b\xc0\xe0\xe7\x27\x21\x86\xce\x02\x63\xdd\x32\x04\xa0\xd1\xc1\x6c\x79\x62\x6d\x99\xa6\xa3\xf1\xe2\xac\xc1\x35\x6d\x46\x5c\x52\x31\x35\x13\xb4\x31\xe9\x90\xbc\x66\x64\x77\xcb\x52\x01\x35\xad\x42\x48\x71\xb3\x0c\x76\xb1\x02\x2d\xd4\x8c\xa7\x37\x8d\xb3\x58\xc1\x46\xa8\x45\x9a\xf9\xd2\x17\x6d\xd9\xe8\x06\x91\x46\x65\x17\xd6\x76\x85\xfd\x6d\x06\x2d\xd8\x6c\xac\xd3\xde\x46\x81\x6e\x30\xd6\x8d\x17\x00\xcd\x25\xd9\x0b\xc9\x39\x89\x47\x97\xa2\x2c\x86\xda\x6c\x0e\xd5\xde\x5c\x2e\x96\x91\xa4\x7e\xbf\x6b\x82\x41\x6d\xae\x7f\x52\xe0\x0a\xf5\xde\xdc\xd0\x83\xaf\x74\x9a\x5b\x5a\x5d\x6d\x9f\xd4\x09\x6e\xa4\xa1\xdb\xc1\x87\x2e\xcd\xed\x74\x92\xd3\x0d\xcb\x74\x2b\x64\x1f\xa7\x8f\xd2\xdc\x1a\x67\x84\xb6\xe1\xa4\x53\x36\x70\xd1\xef\x96\xc9\x86\x33\x3d\x60\x5a\xda\x84\xa6\x6c\x70\x35\x90\xa1\x8e\xff\x53\xa7\x6d\xe6\x13\x99\x0c\x49\x9a\x99\x31\x4d\x9b\xb9\xb1\x06\x2b\x23\xbd\xf8\x4c\xa6\x81\x09\x33\x13\x64\x80\xe1\x09\x2e\x0b\x6d\xfa\xfd\x1d\xfe\x4d\x81\x17\xf1\x6f\x42\x0b\xfe\x9b\x52\x56\xc6\x85\x49\xb7\xf0\x6f\xd2\x6a\xc3\x31\x2f\xd0\xe8\x70\xba\x93\x20\x81\x9e\xf7\xfb\x8b\x77\x20\x1e\x37\x8d\x80\xf8\x5c\x94\xf3\xb8\x6b\x8a\x39\x38\x23\x04\xa2\xc3\x23\x28\xec\xeb\xbc\xcf\x11\x97\x06\xe7\xe1\x83\x23\x28\xdd\x99\x1b\x80\x9d\x35\x9d\x8d\x59\xf0\x09\xf0\x42\x96\x97\x9a\x2e\xff\x7b\x52\xe8\xf2\xf7\xda\xc0\x65\xbd\x6e\x71\xe1\x2b\x0e\x17\xbe\x62\x80\x29\x1c\x31\xf0\xc5\xc6\x0b\x95\xeb\x02\xd7\x25\xb9\x30\x3b\x08\x79\xbd\x07\x8d\xe9\xb2\xf3\x28\xd6\x65\x67\x0c\xe5\x72\x50\xfb\xb8\xac\xc3\x59\x97\xf5\x6a\xc7\xe5\x98\xa7\xa2\xfc\x84\xe4\x3b\x6f\x68\x5c\xce\x8c\x26\x27\x19\xcb\xe5\x71\x7f\xa3\x25\x84\x77\x1d\xc8\xd2\xb8\xb9\x64\xee\x49\xb2\x5c\x4c\x14\x6e\x88\x43\xcd\xb1\x61\xb6\x67\x70\xd2\xc1\x65\x45\x11\x3c\xdf\x77\xa9\x08\x77\x5d\x78\x68\xe4\xd4\x0b\x2e\x8d\x67\x03\x2e\x4d\x06\x4b\x9b\x71\xe6\x36\x34\x07\x97\x8e\x5f\x8a\x44\x47\x87\x42\x70\xe9\x4d\xd8\xa1\x2f\x38\x8b\x60\x89\x43\x1d\xd9\xc1\xa3\x2e\x47\xe4\xcd\xea\x59\x39\xe8\x75\x7f\x63\xa4\x8b\x8a\xc4\xe5\x33\x40\x77\x7a\xa0\xce\x74\xde\xef\xc3\x30\xef\x11\x09\x29\xa7\x47\x0c\x7e\xbf\x4f\x92\x54\x4f\x2c\x5b\x2b\x9f\x26\xb9\x2e\x6d\xcd\xd3\x68\xd7\x7f\x13\x72\xc3\x47\x33\xae\x03\xbb\x84\xea\xe1\x45\x8f\xf3\x9a\x0f\x92\x06\x00\xff\xc7\x6d\x5f\x10\x94\xb3\xf5\xba\xcd\x0d\xd4\xb4\xe7\xea\x01\x42\x19\x7d\x38\xb7\xd2\x58\x53\xf1\xc3\x3a\xe9\xc4\xb8\x35\x82\xd5\x04\xb3\xd2\xf7\x77\x63\x70\xeb\x7c\x0a\xe8\x73\xbb\xdf\x80\x58\x36\xbc\x45\x87\x88\x04\x9f\x24\x31\x4f\x01\x9c\x81\xa7\x2f\xbf\xde\xe1\x38\xf8\x44\x84\xeb\xb3\xb0\x53\xe3\x2b\x48\x9e\xb2\xfb\x1c\x68\xdb\x21\x27\xbb\x85\xce\x73\xd4\xce\x23\x9f\xce\xdb\x8d\x1e\x61\x1e\x7a\x3c\xe3\x0b\xd0\x57\xab\x1c\x01\xd6\x27\x16\xdb\x23\x44\xbd\xc7\x25\xea\x3d\xe6\xbf\xa4\xb3\xdd\x60\x83\xb9\x03\x5e\x1c\xad\x6c\xa8\xf8\x3b\xc1\xef\xb1\xd2\x1d\xea\xb1\x0a\x6b\x2b\x22\x94\x1e\x2b\x05\x87\xc7\xbc\x9d\x87\x15\x3d\x36\x00\xf8\x07\x3d\xfa\xce\x85\x47\x1f\x60\xe3\x1e\xfb\x60\x27\x3e\xa7\xe9\xbc\xe4\xe9\xf1\xc3\xf8\x3c\xa9\xff\xef\x38\xa8\x4b\x32\x00\xb0\x12\xd2\x11\x43\x97\x3d\x74\x39\x27\x96\x2f\xda\x43\xe7\x25\x7e\x97\x7c\xa1\xae\x20\x9e\xef\x52\x48\xcc\x4e\x26\xea\x52\xa1\x43\x79\x3f\x98\x99\x30\xb7\xfc\x9b\x2e\x4d\xd1\xe4\x1f\xcf\xaf\x3b\x70\x29\xae\x02\xb8\x30\xb3\x0e\x89\xbb\x74\x0a\x48\xff\x3b\x52\xea\xc2\xcc\xf8\x2b\xbc\x88\x52\xf9\x20\xc0\x4a\x15\xf6\xb8\xaf\xeb\xa2\xae\x70\xa7\xba\x9e\x58\x26\x2f\xae\xfb\xfd\xce\x11\x08\xd5\x0c\xf5\xdf\x35\x0b\x5f\x82\xf6\xb5\xea\xfb\x5d\x36\x63\xe3\xc2\x42\x87\x77\xd2\xb5\x0f\x18\xc4\xce\xe3\xa1\xae\x7c\xa6\xdc\x69\x3a\x3b\xbd\xff\x4e\xab\xd9\x2d\xe3\x17\x5b\x44\xb2\x93\xf8\x96\x79\x73\xdc\xef\x1f\xfa\x8a\xdd\x78\x29\xd7\x2d\xcf\x3f\x24\x1b\x0f\xc9\xbb\x55\x48\x42\xb7\xba\x5a\x55\x38\xc2\xdd\x2a\xa5\xa9\x1b\x47\x6c\x99\x3d\xd7\x6b\x81\xce\xab\x89\x6e\xbe\xee\x79\x3b\x0a\x91\xef\x8b\xc0\xf7\xcf\x20\x27\x4c\x04\x83\x7d\x6e\x40\xe3\xa4\x9d\xeb\x34\x44\x7d\xca\x89\x69\xe9\x89\xf6\xe5\x59\xf5\x15\xfa\xf6\x79\x38\x9b\x33\x3c\xea\x33\x2f\x26\xe1\x3d\x52\x9f\x70\xbf\x98\x92\x85\xe7\x32\xf0\x7d\x36\xaa\xb5\x3e\xf1\xed\x89\x5f\x7f\x63\xfa\xc9\x86\x9d\x63\x41\x93\x8d\xc8\x27\xea\x23\x6e\xd0\x18\x48\x73\x04\xbc\x7f\xc3\x58\x15\xd0\xe3\x7c\x0f\x3a\x22\xb6\x3c\xe8\x74\x8f\xb8\x4e\x1b\xd7\xeb\xc5\xb1\x84\x66\xc4\x42\x3b\x31\x62\x81\x84\x0f\x5a\xa1\x11\xeb\x1a\xb8\xa1\x5d\x03\x03\x8c\x08\x4e\x1b\xb1\xad\x4e\xff\xa6\xae\x41\x7c\x47\x9d\x0b\xbf\xa1\xe8\x46\xf4\x27\xd8\x6b\x44\xb7\x01\xe8\x18\xcf\x59\x32\x66\x7c\xa2\xf9\x64\xd9\x0b\x45\xb4\x5f\x43\xf8\xca\x65\xd0\x2d\x1e\x92\x30\xf2\xfd\x9d\xf8\x46\x66\xc8\x13\x6c\x30\xe4\x29\x0e\xa8\xcc\xa0\x85\xe4\xfb\xfb\x40\x24\x42\xce\x1a\x02\x65\x33\xd6\x63\x81\x21\x35\xbe\x00\x77\x76\xaa\x0b\x6a\x07\xec\xa8\x36\x5e\xbe\x21\x9c\xe0\xb6\x04\x18\x1f\xf7\xb7\xf3\xd9\xdd\x10\xaf\xd0\x58\x03\x2e\x2f\x7a\x76\xf6\xec\xc6\x35\xf6\x81\x20\x70\x08\x63\x91\x41\x81\x19\xf2\x0a\x43\xa1\xc4\x86\x6e\x93\x27\x6a\x43\xa5\x34\xe4\x29\xc4\x43\x79\xcd\x34\x14\xfc\x33\x14\xfa\x66\xe8\x93\x03\xf0\x02\x64\x28\xcf\x86\x07\x9c\x0a\xec\x0f\x7e\xd0\xe0\xa3\xaf\x01\xcb\x30\xee\x77\x83\x75\x19\xca\x21\xd9\xed\x6f\x16\xb2\xd6\xb8\xdf\x43\x56\xff\x01\xf5\x3b\x14\xb8\xb5\x45\x67\xdb\x18\xe9\x0f\x83\x62\x1d\x96\xb8\x43\xc3\x2c\x76\xa2\x3a\xf3\xb3\xb0\x92\x55\xe4\x11\x6b\x2c\x68\x12\x06\x5f\xb5\x8d\xfb\xc7\xe3\x47\x18\xc6\x30\x7f\x98\x17\x2a\x0f\x98\x48\x61\x9e\xa0\x09\x07\x73\xac\x85\xcf\x4c\x86\xf9\x98\x9c\xa6\xe3\x87\x3d\xf0\x6d\xd5\x80\xb3\x87\x9c\xc7\x8d\x7c\xea\xeb\x3e\x7e\xbd\x48\x1e\xff\xbb\x0b\x1c\x8e\x48\x72\xf0\xf6\x73\x78\x2c\xfc\x86\xbf\xb5\x4c\xf2\xf0\x08\xcf\x6e\x38\x5f\xdb\x0e\xbf\xbf\x37\xcb\x61\xc0\xbf\x45\xa9\x2c\x0c\xba\x54\x00\x6e\x08\x4e\xc0\x70\xdd\x26\x20\x87\x46\xb4\x30\x9c\xcf\xf8\x86\xeb\xac\x07\x0a\xed\x10\x26\x85\x95\xb4\x98\x83\xc6\x72\xf0\xe1\xea\x70\x38\xd5\xc3\x27\xcb\xf9\x4c\x75\xf8\x04\xf3\xcf\x6d\x5d\xeb\x8e\xb9\x59\x18\x93\x6f\x14\xc6\x84\xf9\x19\x34\x86\xe3\xfe\xad\x92\x99\x90\xb9\xa7\xf3\xf9\xe9\x98\xce\xd3\xc1\x31\xe1\x71\x0c\x3e\xaf\x9e\x1b\x23\xa5\xfb\x37\x33\x66\x9c\xd0\x72\x39\xcc\x65\xa5\xe8\x8a\xcc\xaa\x17\xe2\xb1\x30\x2b\x7e\x50\x8b\x0c\xb1\xa6\xd3\x09\x9d\xbe\x49\x98\xbe\xae\x7c\x27\x62\x2b\xfe\x0d\x64\xf6\xc9\xe7\x4a\xeb\xce\x69\x0e\xe3\xab\x8f\x79\xc5\x70\x21\x0c\xba\x62\x02\xcb\x5d\x91\x6f\xc2\x2e\x3e\xe4\xbf\x40\x85\x2b\x2a\x0b\xd6\xd1\xed\x15\xb3\x84\xeb\x2f\x7e\xbf\xf8\x6e\xea\xe2\xa3\x56\x94\x5d\x93\x2d\x4a\x83\x1f\x75\x45\x47\xc6\x95\x03\x91\x6d\x2f\x84\xc6\x97\x90\x15\xaf\x75\x59\x72\xc9\xe3\x7e\xf3\xc0\xef\x02\xd9\x24\x5c\xf2\x94\x57\xe0\x21\xd6\x25\x34\xfa\x97\x64\x43\x09\x56\x21\x7c\x11\x7b\x51\xb8\x2e\xa9\xc2\x81\x2a\xd7\x2a\x40\xcd\x45\xee\xbc\xa4\xce\x1e\x2e\xb6\xe4\xad\xf2\x25\xbe\x11\xee\x98\xc0\x85\xbd\xfd\x49\xc8\x25\xf9\x40\x63\x20\xe4\x52\x30\xdd\xa5\x1b\xb4\xf5\xc5\xa3\xa4\xeb\x7e\x27\x5e\x0c\x5d\x8a\x8e\xf7\x1b\x06\xe7\xd2\x1d\xd8\xbc\x14\x7e\x31\xef\xef\xa4\x87\x8b\x5e\xde\xa5\x19\x3f\xec\x40\x6b\x84\xd0\xf3\xc5\xd6\xa5\xf7\x7f\x90\x93\x4b\x2d\xdf\xef\x1a\x2e\x05\x61\x2f\x75\x20\x59\x7d\xcc\x3d\x5c\xda\x89\xca\x77\x67\xb0\xbe\x5c\xcd\x4b\x47\xe4\x09\xe0\xa5\x93\xdd\xaf\xf8\x02\x24\x6e\x14\x76\xfe\xd2\xcb\xc2\x65\x99\xf7\xa7\x97\x65\xba\xb3\x97\x65\x62\xc0\x1c\xcd\xe9\xd3\x5d\x08\xa7\x2f\x20\x93\xd6\xeb\x9a\x7c\x98\xf9\xc9\x0b\xec\x4f\xf8\xc7\x9f\x94\xa0\x4f\xe8\xd5\x4f\xde\x48\x7e\x42\x71\x7d\x42\x6b\x7c\x42\x6b\x7c\xda\x39\x3d\xbc\xe2\x01\x02\xbf\x78\xd4\xfa\x8a\x0d\x22\xf9\xe2\x1b\x85\x97\x55\x00\xe8\xfe\xd7\x2c\x00\xb0\xb5\xff\x1f\x00\x00\xff\xff\x11\x91\x1a\xde\x5b\x35\x00\x00") -func keysWordlistSpanishTxtBytes() ([]byte, error) { +func keysWordsWordlistSpanishTxtBytes() ([]byte, error) { return bindataRead( - _keysWordlistSpanishTxt, - "keys/wordlist/spanish.txt", + _keysWordsWordlistSpanishTxt, + "keys/words/wordlist/spanish.txt", ) } -func keysWordlistSpanishTxt() (*asset, error) { - bytes, err := keysWordlistSpanishTxtBytes() +func keysWordsWordlistSpanishTxt() (*asset, error) { + bytes, err := keysWordsWordlistSpanishTxtBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "keys/wordlist/spanish.txt", size: 13659, mode: os.FileMode(420), modTime: time.Unix(1511602021, 0)} + info := bindataFileInfo{name: "keys/words/wordlist/spanish.txt", size: 13659, mode: os.FileMode(420), modTime: time.Unix(1514928181, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -203,10 +203,10 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "keys/wordlist/chinese_simplified.txt": keysWordlistChinese_simplifiedTxt, - "keys/wordlist/english.txt": keysWordlistEnglishTxt, - "keys/wordlist/japanese.txt": keysWordlistJapaneseTxt, - "keys/wordlist/spanish.txt": keysWordlistSpanishTxt, + "keys/words/wordlist/chinese_simplified.txt": keysWordsWordlistChinese_simplifiedTxt, + "keys/words/wordlist/english.txt": keysWordsWordlistEnglishTxt, + "keys/words/wordlist/japanese.txt": keysWordsWordlistJapaneseTxt, + "keys/words/wordlist/spanish.txt": keysWordsWordlistSpanishTxt, } // AssetDir returns the file names below a certain @@ -250,11 +250,13 @@ type bintree struct { } var _bintree = &bintree{nil, map[string]*bintree{ "keys": &bintree{nil, map[string]*bintree{ - "wordlist": &bintree{nil, map[string]*bintree{ - "chinese_simplified.txt": &bintree{keysWordlistChinese_simplifiedTxt, map[string]*bintree{}}, - "english.txt": &bintree{keysWordlistEnglishTxt, map[string]*bintree{}}, - "japanese.txt": &bintree{keysWordlistJapaneseTxt, map[string]*bintree{}}, - "spanish.txt": &bintree{keysWordlistSpanishTxt, map[string]*bintree{}}, + "words": &bintree{nil, map[string]*bintree{ + "wordlist": &bintree{nil, map[string]*bintree{ + "chinese_simplified.txt": &bintree{keysWordsWordlistChinese_simplifiedTxt, map[string]*bintree{}}, + "english.txt": &bintree{keysWordsWordlistEnglishTxt, map[string]*bintree{}}, + "japanese.txt": &bintree{keysWordsWordlistJapaneseTxt, map[string]*bintree{}}, + "spanish.txt": &bintree{keysWordsWordlistSpanishTxt, map[string]*bintree{}}, + }}, }}, }}, }} From 67a47e6a0bf474a76f6a8f09b39cfdf382f39b90 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 6 Jan 2018 16:05:50 -0500 Subject: [PATCH 193/273] Address is a type alias --- pub_key.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pub_key.go b/pub_key.go index cda01a9df..32c0b3237 100644 --- a/pub_key.go +++ b/pub_key.go @@ -16,7 +16,8 @@ import ( // An address is a []byte, but hex-encoded even in JSON. // []byte leaves us the option to change the address length. -type Address cmn.HexBytes +// Use an alias so Unmarshal methods (with ptr receivers) are available too. +type Address = cmn.HexBytes func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { if err := wire.ReadBinaryBytes(pubKeyBytes, &pubKey); err != nil { From 788cc0a79256d4fe0448e17a90217acf3d61346b Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 14 Jan 2018 00:31:39 -0800 Subject: [PATCH 194/273] Use new go-wire; PubKey etc are interfaces; Keybase refactor --- {nano => _nano}/keys.go | 0 {nano => _nano}/keys_test.go | 0 {nano => _nano}/sign.go | 0 {nano => _nano}/sign_test.go | 0 crypto.go | 9 -- embed_test.go | 91 ------------- encode_test.go | 4 + glide.lock | 35 ++--- glide.yaml | 8 +- keys/keybase.go | 227 +++++++++++++------------------- keys/keybase_test.go | 242 ++++++++++++++++++----------------- keys/keys.go | 32 +++++ keys/mintkey.go | 26 ++++ keys/types.go | 63 +++++---- keys/wire.go | 12 ++ priv_key.go | 88 +++++-------- priv_key_test.go | 32 ++--- privkeyinner_wrapper.go | 62 --------- pub_key.go | 86 +++---------- pub_key_test.go | 4 +- pubkeyinner_wrapper.go | 62 --------- signature.go | 58 +++------ signature_test.go | 132 ++++++------------- signatureinner_wrapper.go | 62 --------- wire.go | 36 ++++++ 25 files changed, 494 insertions(+), 877 deletions(-) rename {nano => _nano}/keys.go (100%) rename {nano => _nano}/keys_test.go (100%) rename {nano => _nano}/sign.go (100%) rename {nano => _nano}/sign_test.go (100%) delete mode 100644 crypto.go delete mode 100644 embed_test.go create mode 100644 keys/keys.go create mode 100644 keys/wire.go delete mode 100644 privkeyinner_wrapper.go delete mode 100644 pubkeyinner_wrapper.go delete mode 100644 signatureinner_wrapper.go create mode 100644 wire.go diff --git a/nano/keys.go b/_nano/keys.go similarity index 100% rename from nano/keys.go rename to _nano/keys.go diff --git a/nano/keys_test.go b/_nano/keys_test.go similarity index 100% rename from nano/keys_test.go rename to _nano/keys_test.go diff --git a/nano/sign.go b/_nano/sign.go similarity index 100% rename from nano/sign.go rename to _nano/sign.go diff --git a/nano/sign_test.go b/_nano/sign_test.go similarity index 100% rename from nano/sign_test.go rename to _nano/sign_test.go diff --git a/crypto.go b/crypto.go deleted file mode 100644 index d9caf1ad9..000000000 --- a/crypto.go +++ /dev/null @@ -1,9 +0,0 @@ -package crypto - -// Types of implementations -const ( - TypeEd25519 = byte(0x01) - TypeSecp256k1 = byte(0x02) - NameEd25519 = "ed25519" - NameSecp256k1 = "secp256k1" -) diff --git a/embed_test.go b/embed_test.go deleted file mode 100644 index e5c37c0c1..000000000 --- a/embed_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package crypto_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - data "github.com/tendermint/go-wire/data" -) - -type PubName struct { - PubNameInner -} - -type PubNameInner interface { - AssertIsPubNameInner() - String() string -} - -func (p PubName) MarshalJSON() ([]byte, error) { - return pubNameMapper.ToJSON(p.PubNameInner) -} - -func (p *PubName) UnmarshalJSON(data []byte) error { - parsed, err := pubNameMapper.FromJSON(data) - if err == nil && parsed != nil { - p.PubNameInner = parsed.(PubNameInner) - } - return err -} - -var pubNameMapper = data.NewMapper(PubName{}). - RegisterImplementation(PubNameFoo{}, "foo", 1). - RegisterImplementation(PubNameBar{}, "bar", 2) - -func (f PubNameFoo) AssertIsPubNameInner() {} -func (f PubNameBar) AssertIsPubNameInner() {} - -//---------------------------------------- - -type PubNameFoo struct { - Name string -} - -func (f PubNameFoo) String() string { return "Foo: " + f.Name } - -type PubNameBar struct { - Age int -} - -func (b PubNameBar) String() string { return fmt.Sprintf("Bar #%d", b.Age) } - -//---------------------------------------- - -// TestEncodeDemo tries the various strategies to encode the objects -func TestEncodeDemo(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - cases := []struct { - in, out PubNameInner - expected string - }{ - {PubName{PubNameFoo{"pub-foo"}}, &PubName{}, "Foo: pub-foo"}, - {PubName{PubNameBar{7}}, &PubName{}, "Bar #7"}, - } - - for i, tc := range cases { - - // Make sure it is proper to start - require.Equal(tc.expected, tc.in.String()) - - // Try to encode as binary - b, err := data.ToWire(tc.in) - if assert.Nil(err, "%d: %#v", i, tc.in) { - err2 := data.FromWire(b, tc.out) - if assert.Nil(err2) { - assert.Equal(tc.expected, tc.out.String()) - } - } - - // Try to encode it as json - j, err := data.ToJSON(tc.in) - if assert.Nil(err, "%d: %#v", i, tc.in) { - err2 := data.FromJSON(j, tc.out) - if assert.Nil(err2) { - assert.Equal(tc.expected, tc.out.String()) - } - } - } -} diff --git a/encode_test.go b/encode_test.go index 947d91901..bcd9e60c2 100644 --- a/encode_test.go +++ b/encode_test.go @@ -1,5 +1,8 @@ package crypto +/* +XXX Needs to be refactored to not use go-wire/data + import ( "fmt" "strings" @@ -179,3 +182,4 @@ func TestEmbededWireEncodings(t *testing.T) { checkWire(t, msg, &msg2, tc.keyType, tc.size) } } +*/ diff --git a/glide.lock b/glide.lock index 5032685c2..c8e47160f 100644 --- a/glide.lock +++ b/glide.lock @@ -1,18 +1,18 @@ -hash: a21061afc44c148eb6bfeb91478b520661f3d086234383a0208d915b0cb058b8 -updated: 2017-12-27T14:29:49.534901894-08:00 +hash: ed34b08bfc24f64edbc1a16ad2e34198afefc0e2dc133be2c92c6f764f953234 +updated: 2018-01-13T18:02:43.833267692-08:00 imports: - name: github.com/btcsuite/btcd - version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e + version: 2e60448ffcc6bf78332d1fe590260095f554dd78 subpackages: - btcec - name: github.com/btcsuite/btcutil - version: 66871daeb12123ece012a9628d2798d01195c4b3 + version: 501929d3d046174c3d39f0ea54ece471aa17238c subpackages: - base58 -- name: github.com/ethanfrey/ledger - version: 5e432577be582bd18a3b4a9cd75dae7a317ade36 -- name: github.com/flynn/hid - version: ed06a31c6245d4552e8dbba7e32e5b010b875d65 +- name: github.com/davecgh/go-spew + version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 + subpackages: + - spew - name: github.com/go-kit/kit version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c subpackages: @@ -32,7 +32,7 @@ imports: - name: github.com/golang/snappy version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/howeyc/crc16 - version: 96a97a1abb579c7ff1a8ffa77f2e72d1c314b57f + version: 2b2a61e366a66d3efb279e46176e7291001e0354 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/kr/logfmt @@ -55,17 +55,14 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/ed25519 - version: 1f52c6f8b8a5c7908aff4497c186af344b428925 + version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 27be46e25124ddf775e23317a83647ce62a93f6b - subpackages: - - data - - data/base58 + version: fde4a0bf4dd4c0ec0df2504f79f23ed7e6b3b452 - name: github.com/tendermint/tmlibs - version: 93c05aa8c06ef38f2b15fcdd1d91eafefda2732d + version: 2bb538b150f197a04a0b969a27e9ea24d35edbc1 subpackages: - common - db @@ -83,10 +80,6 @@ imports: - ripemd160 - salsa20/salsa testImports: -- name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 - subpackages: - - spew - name: github.com/mndrix/btcutil version: d3a63a5752ecf3fbc06bd97365da752111c263df - name: github.com/pmezard/go-difflib @@ -94,11 +87,11 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + version: b91bfb9ebec76498946beb6af7c0230c7cc7ba6c subpackages: - assert - require - name: github.com/tyler-smith/go-bip32 - version: eb790af526c30f23a7c8b00a48e342f9d0bd6386 + version: 2c9cfd17756470a0b7c3e4b7954bae7d11035504 - name: github.com/tyler-smith/go-bip39 version: 8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc diff --git a/glide.yaml b/glide.yaml index f9df5c18d..f92a8c9a4 100644 --- a/glide.yaml +++ b/glide.yaml @@ -19,10 +19,7 @@ import: - package: github.com/tendermint/tmlibs version: sdk2 - package: github.com/tendermint/go-wire - version: develop - subpackages: - - data - - data/base58 + version: sdk2 - package: golang.org/x/crypto subpackages: - blowfish @@ -31,7 +28,8 @@ import: - ripemd160 - package: github.com/pkg/errors - package: github.com/howeyc/crc16 -- package: github.com/ethanfrey/ledger +# Needs refactoring, shouldn't be implementing PrivKey +#- package: github.com/ethanfrey/ledger testImport: - package: github.com/mndrix/btcutil - package: github.com/stretchr/testify diff --git a/keys/keybase.go b/keys/keybase.go index c72518748..88a12000c 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -6,16 +6,10 @@ import ( "github.com/pkg/errors" crypto "github.com/tendermint/go-crypto" - dbm "github.com/tendermint/tmlibs/db" - "github.com/tendermint/go-crypto/keys/words" - "github.com/tendermint/go-crypto/nano" + dbm "github.com/tendermint/tmlibs/db" ) -// XXX Lets use go-crypto/bcrypt and ascii encoding directly in here without -// further wrappers around a store or DB. -// Copy functions from: https://github.com/tendermint/mintkey/blob/master/cmd/mintkey/common.go -// // dbKeybase combines encyption and storage implementation to provide // a full-featured key manager type dbKeybase struct { @@ -32,58 +26,59 @@ func New(db dbm.DB, codec words.Codec) dbKeybase { var _ Keybase = dbKeybase{} -// Create generates a new key and persists it storage, encrypted using the passphrase. -// It returns the generated seedphrase (mnemonic) and the key Info. -// It returns an error if it fails to generate a key for the given algo type, -// or if another key is already stored under the same name. -func (kb dbKeybase) Create(name, passphrase, algo string) (string, Info, error) { +// Create generates a new key and persists it to storage, encrypted +// using the passphrase. It returns the generated seedphrase +// (mnemonic) and the key Info. It returns an error if it fails to +// generate a key for the given algo type, or if another key is +// already stored under the same name. +func (kb dbKeybase) Create(name, passphrase string, algo CryptoAlgo) (Info, string, error) { // NOTE: secret is SHA256 hashed by secp256k1 and ed25519. // 16 byte secret corresponds to 12 BIP39 words. // XXX: Ledgers use 24 words now - should we ? secret := crypto.CRandBytes(16) - key, err := generate(algo, secret) + priv, err := generate(algo, secret) if err != nil { - return "", Info{}, err + return Info{}, "", err } // encrypt and persist the key - public := kb.writeKey(key, name, passphrase) + info := kb.writeKey(priv, name, passphrase) + + // we append the type byte to the serialized secret to help with + // recovery + // ie [secret] = [type] + [secret] + typ := cryptoAlgoToByte(algo) + secret = append([]byte{typ}, secret...) // return the mnemonic phrase words, err := kb.codec.BytesToWords(secret) - seedphrase := strings.Join(words, " ") - return seedphrase, public, err -} - -// Recover converts a seedphrase to a private key and persists it, encrypted with the given passphrase. -// Functions like Create, but seedphrase is input not output. -func (kb dbKeybase) Recover(name, passphrase, algo string, seedphrase string) (Info, error) { - - key, err := kb.SeedToPrivKey(algo, seedphrase) - if err != nil { - return Info{}, err - } - - // Valid seedphrase. Encrypt key and persist to disk. - public := kb.writeKey(key, name, passphrase) - return public, nil + seed := strings.Join(words, " ") + return info, seed, err } -// SeedToPrivKey returns the private key corresponding to a seedphrase -// without persisting the private key. -// TODO: enable the keybase to just hold these in memory so we can sign without persisting (?) -func (kb dbKeybase) SeedToPrivKey(algo, seedphrase string) (crypto.PrivKey, error) { +// Recover converts a seedphrase to a private key and persists it, +// encrypted with the given passphrase. Functions like Create, but +// seedphrase is input not output. +func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { words := strings.Split(strings.TrimSpace(seedphrase), " ") secret, err := kb.codec.WordsToBytes(words) if err != nil { - return crypto.PrivKey{}, err + return Info{}, err } - key, err := generate(algo, secret) + // secret is comprised of the actual secret with the type + // appended. + // ie [secret] = [type] + [secret] + typ, secret := secret[0], secret[1:] + algo := byteToCryptoAlgo(typ) + priv, err := generate(algo, secret) if err != nil { - return crypto.PrivKey{}, err + return Info{}, err } - return key, nil + + // encrypt and persist key. + public := kb.writeKey(priv, name, passphrase) + return public, err } // List returns the keys from storage in alphabetical order. @@ -92,75 +87,56 @@ func (kb dbKeybase) List() ([]Info, error) { iter := kb.db.Iterator(nil, nil) defer iter.Close() for ; iter.Valid(); iter.Next() { - key := iter.Key() - if isPub(key) { - info, err := readInfo(iter.Value()) - if err != nil { - return nil, err - } - res = append(res, info) + // key := iter.Key() + info, err := readInfo(iter.Value()) + if err != nil { + return nil, err } + res = append(res, info) } return res, nil } // Get returns the public information about one key. func (kb dbKeybase) Get(name string) (Info, error) { - bs := kb.db.Get(pubName(name)) + bs := kb.db.Get(infoKey(name)) return readInfo(bs) } // Sign signs the msg with the named key. // It returns an error if the key doesn't exist or the decryption fails. -// TODO: what if leddger fails ? -func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pk crypto.PubKey, err error) { - var key crypto.PrivKey - armorStr := kb.db.Get(privName(name)) - key, err = unarmorDecryptPrivKey(string(armorStr), passphrase) +func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pub crypto.PubKey, err error) { + info, err := kb.Get(name) if err != nil { return } - - sig = key.Sign(msg) - pk = key.PubKey() - return -} - -// Export decodes the private key with the current password, encrypts -// it with a secure one-time password and generates an armored private key -// that can be Imported by another dbKeybase. -// -// This is designed to copy from one device to another, or provide backups -// during version updates. -func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { - armorStr := kb.db.Get(privName(name)) - key, err := unarmorDecryptPrivKey(string(armorStr), oldpass) + priv, err := unarmorDecryptPrivKey(info.PrivKeyArmor, passphrase) if err != nil { - return nil, err + return } + sig = priv.Sign(msg) + pub = priv.PubKey() + return +} - if transferpass == "" { - return key.Bytes(), nil +func (kb dbKeybase) Export(name string) (armor string, err error) { + bz := kb.db.Get(infoKey(name)) + if bz == nil { + return "", errors.New("No key to export with name " + name) } - armorBytes := encryptArmorPrivKey(key, transferpass) - return []byte(armorBytes), nil + return armorInfoBytes(bz), nil } -// Import accepts bytes generated by Export along with the same transferpass. -// If they are valid, it stores the password under the given name with the -// new passphrase. -func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err error) { - var key crypto.PrivKey - if transferpass == "" { - key, err = crypto.PrivKeyFromBytes(data) - } else { - key, err = unarmorDecryptPrivKey(string(data), transferpass) +func (kb dbKeybase) Import(name string, armor string) (err error) { + bz := kb.db.Get(infoKey(name)) + if len(bz) > 0 { + return errors.New("Cannot overwrite data for name " + name) } + infoBytes, err := unarmorInfoBytes(armor) if err != nil { - return err + return } - - kb.writeKey(key, name, newpass) + kb.db.Set(infoKey(name), infoBytes) return nil } @@ -168,80 +144,59 @@ func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err // proper passphrase before deleting it (for security). func (kb dbKeybase) Delete(name, passphrase string) error { // verify we have the proper password before deleting - bs := kb.db.Get(privName(name)) - _, err := unarmorDecryptPrivKey(string(bs), passphrase) + info, err := kb.Get(name) if err != nil { return err } - kb.db.DeleteSync(pubName(name)) - kb.db.DeleteSync(privName(name)) + _, err = unarmorDecryptPrivKey(info.PrivKeyArmor, passphrase) + if err != nil { + return err + } + kb.db.DeleteSync(infoKey(name)) return nil } -// Update changes the passphrase with which an already stored key is encrypted. +// Update changes the passphrase with which an already stored key is +// encrypted. // -// oldpass must be the current passphrase used for encryption, newpass will be -// the only valid passphrase from this time forward. +// oldpass must be the current passphrase used for encryption, +// newpass will be the only valid passphrase from this time forward. func (kb dbKeybase) Update(name, oldpass, newpass string) error { - bs := kb.db.Get(privName(name)) - key, err := unarmorDecryptPrivKey(string(bs), oldpass) + info, err := kb.Get(name) + if err != nil { + return err + } + key, err := unarmorDecryptPrivKey(info.PrivKeyArmor, oldpass) if err != nil { return err } - // Generate the public bytes and the encrypted privkey - public := info(name, key) - private := encryptArmorPrivKey(key, newpass) - - // We must delete first, as Putting over an existing name returns an error. - // Must be done atomically with the write or we could lose the key. - batch := kb.db.NewBatch() - batch.Delete(pubName(name)) - batch.Delete(privName(name)) - batch.Set(pubName(name), public.bytes()) - batch.Set(privName(name), []byte(private)) - batch.Write() - + kb.writeKey(key, name, newpass) return nil } - -//--------------------------------------------------------------------------------------- - func (kb dbKeybase) writeKey(priv crypto.PrivKey, name, passphrase string) Info { - // Generate the public bytes and the encrypted privkey - public := info(name, priv) - private := encryptArmorPrivKey(priv, passphrase) - - // Write them both - kb.db.SetSync(pubName(name), public.bytes()) - kb.db.SetSync(privName(name), []byte(private)) + // generate the encrypted privkey + privArmor := encryptArmorPrivKey(priv, passphrase) + // make Info + info := newInfo(name, priv.PubKey(), privArmor) - return public + // write them both + kb.db.SetSync(infoKey(name), info.bytes()) + return info } -// TODO: use a `type TypeKeyAlgo string` (?) -func generate(algo string, secret []byte) (crypto.PrivKey, error) { +func generate(algo CryptoAlgo, secret []byte) (crypto.PrivKey, error) { switch algo { - case crypto.NameEd25519: - return crypto.GenPrivKeyEd25519FromSecret(secret).Wrap(), nil - case crypto.NameSecp256k1: - return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap(), nil - case nano.NameLedgerEd25519: - return nano.NewPrivKeyLedgerEd25519() + case AlgoEd25519: + return crypto.GenPrivKeyEd25519FromSecret(secret), nil + case AlgoSecp256k1: + return crypto.GenPrivKeySecp256k1FromSecret(secret), nil default: err := errors.Errorf("Cannot generate keys for algorithm: %s", algo) - return crypto.PrivKey{}, err + return nil, err } } -func pubName(name string) []byte { - return []byte(fmt.Sprintf("%s.pub", name)) -} - -func privName(name string) []byte { - return []byte(fmt.Sprintf("%s.priv", name)) -} - -func isPub(name []byte) bool { - return strings.HasSuffix(string(name), ".pub") +func infoKey(name string) []byte { + return []byte(fmt.Sprintf("%s.info", name)) } diff --git a/keys/keybase_test.go b/keys/keybase_test.go index 12e5205b0..84c81c81f 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -2,24 +2,20 @@ package keys_test import ( "fmt" - "os" "testing" - asrt "github.com/stretchr/testify/assert" - rqr "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" - cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" - crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto/keys" "github.com/tendermint/go-crypto/keys/words" - "github.com/tendermint/go-crypto/nano" ) // TestKeyManagement makes sure we can manipulate these keys well func TestKeyManagement(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -27,84 +23,83 @@ func TestKeyManagement(t *testing.T) { words.MustLoadCodec("english"), ) - algo := crypto.NameEd25519 + algo := keys.AlgoEd25519 n1, n2, n3 := "personal", "business", "other" p1, p2 := "1234", "really-secure!@#$" // Check empty state l, err := cstore.List() - require.Nil(err) - assert.Empty(l) + require.Nil(t, err) + assert.Empty(t, l) // create some keys _, err = cstore.Get(n1) - assert.NotNil(err) - _, i, err := cstore.Create(n1, p1, algo) - require.Equal(n1, i.Name) - require.Nil(err) + assert.NotNil(t, err) + i, _, err := cstore.Create(n1, p1, algo) + require.Equal(t, n1, i.Name) + require.Nil(t, err) _, _, err = cstore.Create(n2, p2, algo) - require.Nil(err) + require.Nil(t, err) // we can get these keys i2, err := cstore.Get(n2) - assert.Nil(err) + assert.Nil(t, err) _, err = cstore.Get(n3) - assert.NotNil(err) + assert.NotNil(t, err) // list shows them in order keyS, err := cstore.List() - require.Nil(err) - require.Equal(2, len(keyS)) + require.Nil(t, err) + require.Equal(t, 2, len(keyS)) // note these are in alphabetical order - assert.Equal(n2, keyS[0].Name) - assert.Equal(n1, keyS[1].Name) - assert.Equal(i2.PubKey, keyS[0].PubKey) + assert.Equal(t, n2, keyS[0].Name) + assert.Equal(t, n1, keyS[1].Name) + assert.Equal(t, i2.PubKey, keyS[0].PubKey) // deleting a key removes it err = cstore.Delete("bad name", "foo") - require.NotNil(err) + require.NotNil(t, err) err = cstore.Delete(n1, p1) - require.Nil(err) + require.Nil(t, err) keyS, err = cstore.List() - require.Nil(err) - assert.Equal(1, len(keyS)) + require.Nil(t, err) + assert.Equal(t, 1, len(keyS)) _, err = cstore.Get(n1) - assert.NotNil(err) + assert.NotNil(t, err) // make sure that it only signs with the right password // tx := mock.NewSig([]byte("mytransactiondata")) // err = cstore.Sign(n2, p1, tx) - // assert.NotNil(err) + // assert.NotNil(t, err) // err = cstore.Sign(n2, p2, tx) - // assert.Nil(err, "%+v", err) + // assert.Nil(t, err, "%+v", err) // sigs, err := tx.Signers() - // assert.Nil(err, "%+v", err) - // if assert.Equal(1, len(sigs)) { - // assert.Equal(i2.PubKey, sigs[0]) + // assert.Nil(t, err, "%+v", err) + // if assert.Equal(t, 1, len(sigs)) { + // assert.Equal(t, i2.PubKey, sigs[0]) // } } // TestSignVerify does some detailed checks on how we sign and validate // signatures func TestSignVerify(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), words.MustLoadCodec("english"), ) - algo := crypto.NameSecp256k1 + algo := keys.AlgoSecp256k1 n1, n2 := "some dude", "a dudette" p1, p2 := "1234", "foobar" // create two users and get their info - _, i1, err := cstore.Create(n1, p1, algo) - require.Nil(err) + i1, _, err := cstore.Create(n1, p1, algo) + require.Nil(t, err) - _, i2, err := cstore.Create(n2, p2, algo) - require.Nil(err) + i2, _, err := cstore.Create(n2, p2, algo) + require.Nil(t, err) // let's try to sign some messages d1 := []byte("my first message") @@ -112,20 +107,20 @@ func TestSignVerify(t *testing.T) { // try signing both data with both keys... s11, pub1, err := cstore.Sign(n1, p1, d1) - require.Nil(err) - require.Equal(i1.PubKey, pub1) + require.Nil(t, err) + require.Equal(t, i1.PubKey, pub1) s12, pub1, err := cstore.Sign(n1, p1, d2) - require.Nil(err) - require.Equal(i1.PubKey, pub1) + require.Nil(t, err) + require.Equal(t, i1.PubKey, pub1) s21, pub2, err := cstore.Sign(n2, p2, d1) - require.Nil(err) - require.Equal(i2.PubKey, pub2) + require.Nil(t, err) + require.Equal(t, i2.PubKey, pub2) s22, pub2, err := cstore.Sign(n2, p2, d2) - require.Nil(err) - require.Equal(i2.PubKey, pub2) + require.Nil(t, err) + require.Equal(t, i2.PubKey, pub2) // let's try to validate and make sure it only works when everything is proper cases := []struct { @@ -148,17 +143,17 @@ func TestSignVerify(t *testing.T) { for i, tc := range cases { valid := tc.key.VerifyBytes(tc.data, tc.sig) - assert.Equal(tc.valid, valid, "%d", i) + assert.Equal(t, tc.valid, valid, "%d", i) } } +/* // TestSignWithLedger makes sure we have ledger compatibility with // the crypto store. // // This test will only succeed with a ledger attached to the computer // and the cosmos app open func TestSignWithLedger(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) if os.Getenv("WITH_LEDGER") == "" { t.Skip("Set WITH_LEDGER to run code on real ledger") } @@ -172,19 +167,19 @@ func TestSignWithLedger(t *testing.T) { p := "hard2hack" // create a nano user - _, c, err := cstore.Create(n, p, nano.NameLedgerEd25519) - require.Nil(err, "%+v", err) - assert.Equal(c.Name, n) + c, _, err := cstore.Create(n, p, nano.KeyLedgerEd25519) + require.Nil(t, err, "%+v", err) + assert.Equal(t, c.Key, n) _, ok := c.PubKey.Unwrap().(nano.PubKeyLedgerEd25519) - require.True(ok) + require.True(t, ok) // make sure we can get it back info, err := cstore.Get(n) - require.Nil(err, "%+v", err) - assert.Equal(info.Name, n) + require.Nil(t, err, "%+v", err) + assert.Equal(t, info.Key, n) key := info.PubKey - require.False(key.Empty()) - require.True(key.Equals(c.PubKey)) + require.False(t ,key.Empty()) + require.True(t, key.Equals(c.PubKey)) // let's try to sign some messages d1 := []byte("welcome to cosmos") @@ -192,56 +187,64 @@ func TestSignWithLedger(t *testing.T) { // try signing both data with the ledger... s1, pub, err := cstore.Sign(n, p, d1) - require.Nil(err) - require.Equal(info.PubKey, pub) + require.Nil(t, err) + require.Equal(t, info.PubKey, pub) s2, pub, err := cstore.Sign(n, p, d2) - require.Nil(err) - require.Equal(info.PubKey, pub) + require.Nil(t, err) + require.Equal(t, info.PubKey, pub) // now, let's check those signatures work - assert.True(key.VerifyBytes(d1, s1)) - assert.True(key.VerifyBytes(d2, s2)) + assert.True(t, key.VerifyBytes(d1, s1)) + assert.True(t, key.VerifyBytes(d2, s2)) // and mismatched signatures don't - assert.False(key.VerifyBytes(d1, s2)) + assert.False(t, key.VerifyBytes(d1, s2)) } +*/ -func assertPassword(assert *asrt.Assertions, cstore keys.Keybase, name, pass, badpass string) { +func assertPassword(t *testing.T, cstore keys.Keybase, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) - assert.NotNil(err) + assert.NotNil(t, err) err = cstore.Update(name, pass, pass) - assert.Nil(err, "%+v", err) + assert.Nil(t, err, "%+v", err) } -// TestImportUnencrypted tests accepting raw priv keys bytes as input -func TestImportUnencrypted(t *testing.T) { - require := rqr.New(t) +// TestExportImport tests exporting and importing keys. +func TestExportImport(t *testing.T) { // make the storage with reasonable defaults + db := dbm.NewMemDB() cstore := keys.New( - dbm.NewMemDB(), + db, words.MustLoadCodec("english"), ) - key := crypto.GenPrivKeyEd25519FromSecret(cmn.RandBytes(16)).Wrap() + info, _, err := cstore.Create("john", "passphrase", keys.AlgoEd25519) + assert.Nil(t, err) + assert.Equal(t, info.Name, "john") + addr := info.PubKey.Address() + + john, err := cstore.Get("john") + assert.Nil(t, err) + assert.Equal(t, john.Name, "john") + assert.Equal(t, john.PubKey.Address(), addr) - addr := key.PubKey().Address() - name := "john" - pass := "top-secret" + armor, err := cstore.Export("john") + assert.Nil(t, err) - // import raw bytes - err := cstore.Import(name, pass, "", key.Bytes()) - require.Nil(err, "%+v", err) + err = cstore.Import("john2", armor) + assert.Nil(t, err) - // make sure the address matches - info, err := cstore.Get(name) - require.Nil(err, "%+v", err) - require.EqualValues(addr, info.Address()) + john2, err := cstore.Get("john2") + assert.Nil(t, err) + + assert.Equal(t, john.PubKey.Address(), addr) + assert.Equal(t, john.Name, "john") + assert.Equal(t, john, john2) } // TestAdvancedKeyManagement verifies update, import, export functionality func TestAdvancedKeyManagement(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -249,42 +252,49 @@ func TestAdvancedKeyManagement(t *testing.T) { words.MustLoadCodec("english"), ) - algo := crypto.NameSecp256k1 + algo := keys.AlgoSecp256k1 n1, n2 := "old-name", "new name" - p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$" + p1, p2 := "1234", "foobar" // make sure key works with initial password _, _, err := cstore.Create(n1, p1, algo) - require.Nil(err, "%+v", err) - assertPassword(assert, cstore, n1, p1, p2) + require.Nil(t, err, "%+v", err) + assertPassword(t, cstore, n1, p1, p2) // update password requires the existing password err = cstore.Update(n1, "jkkgkg", p2) - assert.NotNil(err) - assertPassword(assert, cstore, n1, p1, p2) + assert.NotNil(t, err) + assertPassword(t, cstore, n1, p1, p2) // then it changes the password when correct err = cstore.Update(n1, p1, p2) - assert.Nil(err) + assert.Nil(t, err) // p2 is now the proper one! - assertPassword(assert, cstore, n1, p2, p1) + assertPassword(t, cstore, n1, p2, p1) // exporting requires the proper name and passphrase - _, err = cstore.Export(n2, p2, pt) - assert.NotNil(err) - _, err = cstore.Export(n1, p1, pt) - assert.NotNil(err) - exported, err := cstore.Export(n1, p2, pt) - require.Nil(err, "%+v", err) - - // import fails on bad transfer pass - err = cstore.Import(n2, p3, p2, exported) - assert.NotNil(err) + _, err = cstore.Export(n1 + ".notreal") + assert.NotNil(t, err) + _, err = cstore.Export(" " + n1) + assert.NotNil(t, err) + _, err = cstore.Export(n1 + " ") + assert.NotNil(t, err) + _, err = cstore.Export("") + assert.NotNil(t, err) + exported, err := cstore.Export(n1) + require.Nil(t, err, "%+v", err) + + // import succeeds + err = cstore.Import(n2, exported) + assert.Nil(t, err) + + // second import fails + err = cstore.Import(n2, exported) + assert.NotNil(t, err) } // TestSeedPhrase verifies restoring from a seed phrase func TestSeedPhrase(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -292,28 +302,28 @@ func TestSeedPhrase(t *testing.T) { words.MustLoadCodec("english"), ) - algo := crypto.NameEd25519 + algo := keys.AlgoEd25519 n1, n2 := "lost-key", "found-again" p1, p2 := "1234", "foobar" // make sure key works with initial password - seed, info, err := cstore.Create(n1, p1, algo) - require.Nil(err, "%+v", err) - assert.Equal(n1, info.Name) - assert.NotEmpty(seed) + info, seed, err := cstore.Create(n1, p1, algo) + require.Nil(t, err, "%+v", err) + assert.Equal(t, n1, info.Name) + assert.NotEmpty(t, seed) // now, let us delete this key err = cstore.Delete(n1, p1) - require.Nil(err, "%+v", err) + require.Nil(t, err, "%+v", err) _, err = cstore.Get(n1) - require.NotNil(err) + require.NotNil(t, err) // let us re-create it from the seed-phrase - newInfo, err := cstore.Recover(n2, p2, algo, seed) - require.Nil(err, "%+v", err) - assert.Equal(n2, newInfo.Name) - assert.Equal(info.Address(), newInfo.Address()) - assert.Equal(info.PubKey, newInfo.PubKey) + newInfo, err := cstore.Recover(n2, p2, seed) + require.Nil(t, err, "%+v", err) + assert.Equal(t, n2, newInfo.Name) + assert.Equal(t, info.Address(), newInfo.Address()) + assert.Equal(t, info.PubKey, newInfo.PubKey) } func ExampleNew() { @@ -322,11 +332,11 @@ func ExampleNew() { dbm.NewMemDB(), words.MustLoadCodec("english"), ) - ed := crypto.NameEd25519 - sec := crypto.NameSecp256k1 + ed := keys.AlgoEd25519 + sec := keys.AlgoSecp256k1 // Add keys and see they return in alphabetical order - _, bob, err := cstore.Create("Bob", "friend", ed) + bob, _, err := cstore.Create("Bob", "friend", ed) if err != nil { // this should never happen fmt.Println(err) diff --git a/keys/keys.go b/keys/keys.go new file mode 100644 index 000000000..0ed89b3fd --- /dev/null +++ b/keys/keys.go @@ -0,0 +1,32 @@ +package keys + +import "fmt" + +type CryptoAlgo string + +const ( + AlgoEd25519 = CryptoAlgo("ed25519") + AlgoSecp256k1 = CryptoAlgo("secp256k1") +) + +func cryptoAlgoToByte(key CryptoAlgo) byte { + switch key { + case AlgoEd25519: + return 0x01 + case AlgoSecp256k1: + return 0x02 + default: + panic(fmt.Sprintf("Unexpected type key %v", key)) + } +} + +func byteToCryptoAlgo(b byte) CryptoAlgo { + switch b { + case 0x01: + return AlgoEd25519 + case 0x02: + return AlgoSecp256k1 + default: + panic(fmt.Sprintf("Unexpected type byte %X", b)) + } +} diff --git a/keys/mintkey.go b/keys/mintkey.go index d2724d658..73263b83a 100644 --- a/keys/mintkey.go +++ b/keys/mintkey.go @@ -12,8 +12,34 @@ import ( const ( blockTypePrivKey = "TENDERMINT PRIVATE KEY" + blockTypeKeyInfo = "TENDERMINT KEY INFO" ) +func armorInfoBytes(bz []byte) string { + header := map[string]string{ + "type": "Info", + "version": "0.0.0", + } + armorStr := crypto.EncodeArmor(blockTypeKeyInfo, header, bz) + return armorStr +} + +func unarmorInfoBytes(armorStr string) (bz []byte, err error) { + blockType, header, bz, err := crypto.DecodeArmor(armorStr) + if err != nil { + return + } + if blockType != blockTypeKeyInfo { + err = fmt.Errorf("Unrecognized armor type: %v", blockType) + return + } + if header["version"] != "0.0.0" { + err = fmt.Errorf("Unrecognized version: %v", header["version"]) + return + } + return +} + func encryptArmorPrivKey(privKey crypto.PrivKey, passphrase string) string { saltBytes, encBytes := encryptPrivKey(privKey, passphrase) header := map[string]string{ diff --git a/keys/types.go b/keys/types.go index fdb729e0a..16b8f6dd0 100644 --- a/keys/types.go +++ b/keys/types.go @@ -1,15 +1,39 @@ package keys import ( - wire "github.com/tendermint/go-wire" - crypto "github.com/tendermint/go-crypto" ) +// Keybase allows simple CRUD on a keystore, as an aid to signing +type Keybase interface { + // Sign some bytes + Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) + // Create a new keypair + Create(name, passphrase string, algo CryptoAlgo) (info Info, seed string, err error) + // Recover takes a seedphrase and loads in the key + Recover(name, passphrase, seedphrase string) (info Info, erro error) + List() ([]Info, error) + Get(name string) (Info, error) + Update(name, oldpass, newpass string) error + Delete(name, passphrase string) error + + Import(name string, armor string) (err error) + Export(name string) (armor string, err error) +} + // Info is the public information about a key type Info struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + PrivKeyArmor string `json:"privkey.armor"` +} + +func newInfo(name string, pub crypto.PubKey, privArmor string) Info { + return Info{ + Name: name, + PubKey: pub, + PrivKeyArmor: privArmor, + } } // Address is a helper function to calculate the address from the pubkey @@ -18,31 +42,14 @@ func (i Info) Address() []byte { } func (i Info) bytes() []byte { - return wire.BinaryBytes(i) -} - -func readInfo(bs []byte) (info Info, err error) { - err = wire.ReadBinaryBytes(bs, &info) - return -} - -func info(name string, privKey crypto.PrivKey) Info { - return Info{ - Name: name, - PubKey: privKey.PubKey(), + bz, err := cdc.MarshalBinary(i) + if err != nil { + panic(err) } + return bz } -// Keybase allows simple CRUD on a keystore, as an aid to signing -type Keybase interface { - // Sign some bytes - Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) - // Create a new keypair - Create(name, passphrase, algo string) (seedphrase string, _ Info, _ error) - // Recover takes a seedphrase and loads in the key - Recover(name, passphrase, algo, seedphrase string) (Info, error) - List() ([]Info, error) - Get(name string) (Info, error) - Update(name, oldpass, newpass string) error - Delete(name, passphrase string) error +func readInfo(bz []byte) (info Info, err error) { + err = cdc.UnmarshalBinary(bz, &info) + return } diff --git a/keys/wire.go b/keys/wire.go new file mode 100644 index 000000000..65d69ba5e --- /dev/null +++ b/keys/wire.go @@ -0,0 +1,12 @@ +package keys + +import ( + "github.com/tendermint/go-crypto" + "github.com/tendermint/go-wire" +) + +var cdc = wire.NewCodec() + +func init() { + crypto.RegisterWire(cdc) +} diff --git a/priv_key.go b/priv_key.go index 11dcb686f..b86b30f8b 100644 --- a/priv_key.go +++ b/priv_key.go @@ -7,89 +7,60 @@ import ( "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" "github.com/tendermint/go-wire" - data "github.com/tendermint/go-wire/data" . "github.com/tendermint/tmlibs/common" ) func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { - err = wire.ReadBinaryBytes(privKeyBytes, &privKey) - if err == nil { - // add support for a ValidateKey method on PrivKeys - // to make sure they load correctly - val, ok := privKey.Unwrap().(validatable) - if ok { - err = val.ValidateKey() - } - } + err = cdc.UnmarshalBinary(privKeyBytes, &privKey) return } -// validatable is an optional interface for keys that want to -// check integrity -type validatable interface { - ValidateKey() error -} - //---------------------------------------- -// DO NOT USE THIS INTERFACE. -// You probably want to use PrivKey -// +gen wrapper:"PrivKey,Impl[PrivKeyEd25519,PrivKeySecp256k1],ed25519,secp256k1" -type PrivKeyInner interface { - AssertIsPrivKeyInner() +type PrivKey interface { Bytes() []byte Sign(msg []byte) Signature PubKey() PubKey Equals(PrivKey) bool - Wrap() PrivKey } //------------------------------------- -var _ PrivKeyInner = PrivKeyEd25519{} +var _ PrivKey = PrivKeyEd25519{} // Implements PrivKey type PrivKeyEd25519 [64]byte -func (privKey PrivKeyEd25519) AssertIsPrivKeyInner() {} - func (privKey PrivKeyEd25519) Bytes() []byte { - return wire.BinaryBytes(PrivKey{privKey}) + bz, err := cdc.MarshalBinary(privKey) + if err != nil { + panic(err) + } + return bz } func (privKey PrivKeyEd25519) Sign(msg []byte) Signature { privKeyBytes := [64]byte(privKey) signatureBytes := ed25519.Sign(&privKeyBytes, msg) - return SignatureEd25519(*signatureBytes).Wrap() + return SignatureEd25519(*signatureBytes) } func (privKey PrivKeyEd25519) PubKey() PubKey { privKeyBytes := [64]byte(privKey) pubBytes := *ed25519.MakePublicKey(&privKeyBytes) - return PubKeyEd25519(pubBytes).Wrap() + return PubKeyEd25519(pubBytes) } // Equals - you probably don't need to use this. // Runs in constant time based on length of the keys. func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { - if otherEd, ok := other.Unwrap().(PrivKeyEd25519); ok { + if otherEd, ok := other.(PrivKeyEd25519); ok { return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 } else { return false } } -func (p PrivKeyEd25519) MarshalJSON() ([]byte, error) { - return data.Encoder.Marshal(p[:]) -} - -func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error { - var ref []byte - err := data.Encoder.Unmarshal(&ref, enc) - copy(p[:], ref) - return err -} - func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { keyCurve25519 := new([32]byte) privKeyBytes := [64]byte(privKey) @@ -97,16 +68,22 @@ func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { return keyCurve25519 } +/* func (privKey PrivKeyEd25519) String() string { return Fmt("PrivKeyEd25519{*****}") } +*/ // Deterministically generates new priv-key bytes from key. func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { - newBytes := wire.BinarySha256(struct { + bz, err := wire.MarshalBinary(struct { PrivKey [64]byte Index int }{privKey, index}) + if err != nil { + panic(err) + } + newBytes := Sha256(bz) var newKey [64]byte copy(newKey[:], newBytes) return PrivKeyEd25519(newKey) @@ -131,15 +108,17 @@ func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 { //------------------------------------- -var _ PrivKeyInner = PrivKeySecp256k1{} +var _ PrivKey = PrivKeySecp256k1{} // Implements PrivKey type PrivKeySecp256k1 [32]byte -func (privKey PrivKeySecp256k1) AssertIsPrivKeyInner() {} - func (privKey PrivKeySecp256k1) Bytes() []byte { - return wire.BinaryBytes(PrivKey{privKey}) + bz, err := cdc.MarshalBinary(privKey) + if err != nil { + panic(err) + } + return bz } func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature { @@ -148,40 +127,31 @@ func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature { if err != nil { PanicSanity(err) } - return SignatureSecp256k1(sig__.Serialize()).Wrap() + return SignatureSecp256k1(sig__.Serialize()) } func (privKey PrivKeySecp256k1) PubKey() PubKey { _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) var pub PubKeySecp256k1 copy(pub[:], pub__.SerializeCompressed()) - return pub.Wrap() + return pub } // Equals - you probably don't need to use this. // Runs in constant time based on length of the keys. func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { - if otherSecp, ok := other.Unwrap().(PrivKeySecp256k1); ok { + if otherSecp, ok := other.(PrivKeySecp256k1); ok { return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 1 } else { return false } } -func (p PrivKeySecp256k1) MarshalJSON() ([]byte, error) { - return data.Encoder.Marshal(p[:]) -} - -func (p *PrivKeySecp256k1) UnmarshalJSON(enc []byte) error { - var ref []byte - err := data.Encoder.Unmarshal(&ref, enc) - copy(p[:], ref) - return err -} - +/* func (privKey PrivKeySecp256k1) String() string { return Fmt("PrivKeySecp256k1{*****}") } +*/ /* // Deterministically generates new priv-key bytes from key. diff --git a/priv_key_test.go b/priv_key_test.go index 154df5593..3fbfba34d 100644 --- a/priv_key_test.go +++ b/priv_key_test.go @@ -1,42 +1,26 @@ package crypto +/* + import ( "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - wire "github.com/tendermint/go-wire" ) type BadKey struct { PrivKeyEd25519 } -// Wrap fulfils interface for PrivKey struct -func (pk BadKey) Wrap() PrivKey { - return PrivKey{pk} -} - -func (pk BadKey) Bytes() []byte { - return wire.BinaryBytes(pk.Wrap()) -} - -func (pk BadKey) ValidateKey() error { - return fmt.Errorf("fuggly key") -} - -func init() { - PrivKeyMapper. - RegisterImplementation(BadKey{}, "bad", 0x66) -} - func TestReadPrivKey(t *testing.T) { assert, require := assert.New(t), require.New(t) // garbage in, garbage out garbage := []byte("hjgewugfbiewgofwgewr") + XXX This test wants to register BadKey globally to go-crypto, + but we don't want to support that. _, err := PrivKeyFromBytes(garbage) require.Error(err) @@ -47,13 +31,15 @@ func TestReadPrivKey(t *testing.T) { key PrivKey valid bool }{ - {edKey.Wrap(), true}, - {badKey.Wrap(), false}, + {edKey, true}, + {badKey, false}, } for i, tc := range cases { data := tc.key.Bytes() + fmt.Println(">>>", data) key, err := PrivKeyFromBytes(data) + fmt.Printf("!!! %#v\n", key, err) if tc.valid { assert.NoError(err, "%d", i) assert.Equal(tc.key, key, "%d", i) @@ -61,5 +47,5 @@ func TestReadPrivKey(t *testing.T) { assert.Error(err, "%d: %#v", i, key) } } - } +*/ diff --git a/privkeyinner_wrapper.go b/privkeyinner_wrapper.go deleted file mode 100644 index 05ce69672..000000000 --- a/privkeyinner_wrapper.go +++ /dev/null @@ -1,62 +0,0 @@ -// Generated by: main -// TypeWriter: wrapper -// Directive: +gen on PrivKeyInner - -package crypto - -import ( - "github.com/tendermint/go-wire/data" -) - -// Auto-generated adapters for happily unmarshaling interfaces -// Apache License 2.0 -// Copyright (c) 2017 Ethan Frey (ethan.frey@tendermint.com) - -type PrivKey struct { - PrivKeyInner "json:\"unwrap\"" -} - -var PrivKeyMapper = data.NewMapper(PrivKey{}) - -func (h PrivKey) MarshalJSON() ([]byte, error) { - return PrivKeyMapper.ToJSON(h.PrivKeyInner) -} - -func (h *PrivKey) UnmarshalJSON(data []byte) (err error) { - parsed, err := PrivKeyMapper.FromJSON(data) - if err == nil && parsed != nil { - h.PrivKeyInner = parsed.(PrivKeyInner) - } - return err -} - -// Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (h PrivKey) Unwrap() PrivKeyInner { - hi := h.PrivKeyInner - for wrap, ok := hi.(PrivKey); ok; wrap, ok = hi.(PrivKey) { - hi = wrap.PrivKeyInner - } - return hi -} - -func (h PrivKey) Empty() bool { - return h.PrivKeyInner == nil -} - -/*** below are bindings for each implementation ***/ - -func init() { - PrivKeyMapper.RegisterImplementation(PrivKeyEd25519{}, "ed25519", 0x1) -} - -func (hi PrivKeyEd25519) Wrap() PrivKey { - return PrivKey{hi} -} - -func init() { - PrivKeyMapper.RegisterImplementation(PrivKeySecp256k1{}, "secp256k1", 0x2) -} - -func (hi PrivKeySecp256k1) Wrap() PrivKey { - return PrivKey{hi} -} diff --git a/pub_key.go b/pub_key.go index 32c0b3237..8ed1df356 100644 --- a/pub_key.go +++ b/pub_key.go @@ -8,8 +8,6 @@ import ( secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" - "github.com/tendermint/go-wire" - data "github.com/tendermint/go-wire/data" cmn "github.com/tendermint/tmlibs/common" "golang.org/x/crypto/ripemd160" ) @@ -20,56 +18,44 @@ import ( type Address = cmn.HexBytes func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { - if err := wire.ReadBinaryBytes(pubKeyBytes, &pubKey); err != nil { - return PubKey{}, err - } - return pubKey, nil + err = cdc.UnmarshalBinary(pubKeyBytes, &pubKey) + return } //---------------------------------------- -// DO NOT USE THIS INTERFACE. -// You probably want to use PubKey -// +gen wrapper:"PubKey,Impl[PubKeyEd25519,PubKeySecp256k1],ed25519,secp256k1" -type PubKeyInner interface { - AssertIsPubKeyInner() +type PubKey interface { Address() Address Bytes() []byte - KeyString() string VerifyBytes(msg []byte, sig Signature) bool Equals(PubKey) bool - Wrap() PubKey } //------------------------------------- -var _ PubKeyInner = PubKeyEd25519{} +var _ PubKey = PubKeyEd25519{} // Implements PubKeyInner type PubKeyEd25519 [32]byte -func (pubKey PubKeyEd25519) AssertIsPubKeyInner() {} - func (pubKey PubKeyEd25519) Address() Address { - w, n, err := new(bytes.Buffer), new(int), new(error) - wire.WriteBinary(pubKey[:], w, n, err) - if *err != nil { - panic(*err) - } // append type byte - encodedPubkey := append([]byte{TypeEd25519}, w.Bytes()...) hasher := ripemd160.New() - hasher.Write(encodedPubkey) // does not error + hasher.Write(pubKey.Bytes()) // does not error return Address(hasher.Sum(nil)) } func (pubKey PubKeyEd25519) Bytes() []byte { - return wire.BinaryBytes(PubKey{pubKey}) + bz, err := cdc.MarshalBinary(pubKey) + if err != nil { + panic(err) + } + return bz } func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { // make sure we use the same algorithm to sign - sig, ok := sig_.Unwrap().(SignatureEd25519) + sig, ok := sig_.(SignatureEd25519) if !ok { return false } @@ -78,17 +64,6 @@ func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { return ed25519.Verify(&pubKeyBytes, msg, &sigBytes) } -func (p PubKeyEd25519) MarshalJSON() ([]byte, error) { - return data.Encoder.Marshal(p[:]) -} - -func (p *PubKeyEd25519) UnmarshalJSON(enc []byte) error { - var ref []byte - err := data.Encoder.Unmarshal(&ref, enc) - copy(p[:], ref) - return err -} - // For use with golang/crypto/nacl/box // If error, returns nil. func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte { @@ -104,14 +79,8 @@ func (pubKey PubKeyEd25519) String() string { return fmt.Sprintf("PubKeyEd25519{%X}", pubKey[:]) } -// Must return the full bytes in hex. -// Used for map keying, etc. -func (pubKey PubKeyEd25519) KeyString() string { - return fmt.Sprintf("%X", pubKey[:]) -} - func (pubKey PubKeyEd25519) Equals(other PubKey) bool { - if otherEd, ok := other.Unwrap().(PubKeyEd25519); ok { + if otherEd, ok := other.(PubKeyEd25519); ok { return bytes.Equal(pubKey[:], otherEd[:]) } else { return false @@ -120,15 +89,13 @@ func (pubKey PubKeyEd25519) Equals(other PubKey) bool { //------------------------------------- -var _ PubKeyInner = PubKeySecp256k1{} +var _ PubKey = PubKeySecp256k1{} // Implements PubKey. // Compressed pubkey (just the x-cord), // prefixed with 0x02 or 0x03, depending on the y-cord. type PubKeySecp256k1 [33]byte -func (pubKey PubKeySecp256k1) AssertIsPubKeyInner() {} - // Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) func (pubKey PubKeySecp256k1) Address() Address { hasherSHA256 := sha256.New() @@ -141,12 +108,16 @@ func (pubKey PubKeySecp256k1) Address() Address { } func (pubKey PubKeySecp256k1) Bytes() []byte { - return wire.BinaryBytes(PubKey{pubKey}) + bz, err := cdc.MarshalBinary(pubKey) + if err != nil { + panic(err) + } + return bz } func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { // and assert same algorithm to sign and verify - sig, ok := sig_.Unwrap().(SignatureSecp256k1) + sig, ok := sig_.(SignatureSecp256k1) if !ok { return false } @@ -162,29 +133,12 @@ func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { return sig__.Verify(Sha256(msg), pub__) } -func (p PubKeySecp256k1) MarshalJSON() ([]byte, error) { - return data.Encoder.Marshal(p[:]) -} - -func (p *PubKeySecp256k1) UnmarshalJSON(enc []byte) error { - var ref []byte - err := data.Encoder.Unmarshal(&ref, enc) - copy(p[:], ref) - return err -} - func (pubKey PubKeySecp256k1) String() string { return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:]) } -// Must return the full bytes in hex. -// Used for map keying, etc. -func (pubKey PubKeySecp256k1) KeyString() string { - return fmt.Sprintf("%X", pubKey[:]) -} - func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { - if otherSecp, ok := other.Unwrap().(PubKeySecp256k1); ok { + if otherSecp, ok := other.(PubKeySecp256k1); ok { return bytes.Equal(pubKey[:], otherSecp[:]) } else { return false diff --git a/pub_key_test.go b/pub_key_test.go index 95c82534d..29672390b 100644 --- a/pub_key_test.go +++ b/pub_key_test.go @@ -33,7 +33,7 @@ func TestPubKeySecp256k1Address(t *testing.T) { var priv PrivKeySecp256k1 copy(priv[:], privB) - pubT := priv.PubKey().Unwrap().(PubKeySecp256k1) + pubT := priv.PubKey().(PubKeySecp256k1) pub := pubT[:] addr := priv.PubKey().Address() @@ -45,5 +45,5 @@ func TestPubKeySecp256k1Address(t *testing.T) { func TestPubKeyInvalidDataProperReturnsEmpty(t *testing.T) { pk, err := PubKeyFromBytes([]byte("foo")) require.NotNil(t, err, "expecting a non-nil error") - require.True(t, pk.Empty(), "expecting an empty public key on error") + require.Nil(t, pk, "expecting an empty public key on error") } diff --git a/pubkeyinner_wrapper.go b/pubkeyinner_wrapper.go deleted file mode 100644 index 7b36c324d..000000000 --- a/pubkeyinner_wrapper.go +++ /dev/null @@ -1,62 +0,0 @@ -// Generated by: main -// TypeWriter: wrapper -// Directive: +gen on PubKeyInner - -package crypto - -import ( - "github.com/tendermint/go-wire/data" -) - -// Auto-generated adapters for happily unmarshaling interfaces -// Apache License 2.0 -// Copyright (c) 2017 Ethan Frey (ethan.frey@tendermint.com) - -type PubKey struct { - PubKeyInner "json:\"unwrap\"" -} - -var PubKeyMapper = data.NewMapper(PubKey{}) - -func (h PubKey) MarshalJSON() ([]byte, error) { - return PubKeyMapper.ToJSON(h.PubKeyInner) -} - -func (h *PubKey) UnmarshalJSON(data []byte) (err error) { - parsed, err := PubKeyMapper.FromJSON(data) - if err == nil && parsed != nil { - h.PubKeyInner = parsed.(PubKeyInner) - } - return err -} - -// Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (h PubKey) Unwrap() PubKeyInner { - hi := h.PubKeyInner - for wrap, ok := hi.(PubKey); ok; wrap, ok = hi.(PubKey) { - hi = wrap.PubKeyInner - } - return hi -} - -func (h PubKey) Empty() bool { - return h.PubKeyInner == nil -} - -/*** below are bindings for each implementation ***/ - -func init() { - PubKeyMapper.RegisterImplementation(PubKeyEd25519{}, "ed25519", 0x1) -} - -func (hi PubKeyEd25519) Wrap() PubKey { - return PubKey{hi} -} - -func init() { - PubKeyMapper.RegisterImplementation(PubKeySecp256k1{}, "secp256k1", 0x2) -} - -func (hi PubKeySecp256k1) Wrap() PubKey { - return PubKey{hi} -} diff --git a/signature.go b/signature.go index cd40331cf..3a0f6a7a7 100644 --- a/signature.go +++ b/signature.go @@ -4,40 +4,35 @@ import ( "bytes" "fmt" - "github.com/tendermint/go-wire" - data "github.com/tendermint/go-wire/data" . "github.com/tendermint/tmlibs/common" ) -func SignatureFromBytes(sigBytes []byte) (sig Signature, err error) { - err = wire.ReadBinaryBytes(sigBytes, &sig) +func SignatureFromBytes(pubKeyBytes []byte) (pubKey Signature, err error) { + err = cdc.UnmarshalBinary(pubKeyBytes, &pubKey) return } //---------------------------------------- -// DO NOT USE THIS INTERFACE. -// You probably want to use Signature. -// +gen wrapper:"Signature,Impl[SignatureEd25519,SignatureSecp256k1],ed25519,secp256k1" -type SignatureInner interface { - AssertIsSignatureInner() +type Signature interface { Bytes() []byte IsZero() bool Equals(Signature) bool - Wrap() Signature } //------------------------------------- -var _ SignatureInner = SignatureEd25519{} +var _ Signature = SignatureEd25519{} // Implements Signature type SignatureEd25519 [64]byte -func (sig SignatureEd25519) AssertIsSignatureInner() {} - func (sig SignatureEd25519) Bytes() []byte { - return wire.BinaryBytes(Signature{sig}) + bz, err := cdc.MarshalBinary(sig) + if err != nil { + panic(err) + } + return bz } func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } @@ -45,41 +40,32 @@ func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } func (sig SignatureEd25519) Equals(other Signature) bool { - if otherEd, ok := other.Unwrap().(SignatureEd25519); ok { + if otherEd, ok := other.(SignatureEd25519); ok { return bytes.Equal(sig[:], otherEd[:]) } else { return false } } -func (sig SignatureEd25519) MarshalJSON() ([]byte, error) { - return data.Encoder.Marshal(sig[:]) -} - -func (sig *SignatureEd25519) UnmarshalJSON(enc []byte) error { - var ref []byte - err := data.Encoder.Unmarshal(&ref, enc) - copy(sig[:], ref) - return err -} - func SignatureEd25519FromBytes(data []byte) Signature { var sig SignatureEd25519 copy(sig[:], data) - return sig.Wrap() + return sig } //------------------------------------- -var _ SignatureInner = SignatureSecp256k1{} +var _ Signature = SignatureSecp256k1{} // Implements Signature type SignatureSecp256k1 []byte -func (sig SignatureSecp256k1) AssertIsSignatureInner() {} - func (sig SignatureSecp256k1) Bytes() []byte { - return wire.BinaryBytes(Signature{sig}) + bz, err := cdc.MarshalBinary(sig) + if err != nil { + panic(err) + } + return bz } func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } @@ -87,17 +73,9 @@ func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } func (sig SignatureSecp256k1) Equals(other Signature) bool { - if otherSecp, ok := other.Unwrap().(SignatureSecp256k1); ok { + if otherSecp, ok := other.(SignatureSecp256k1); ok { return bytes.Equal(sig[:], otherSecp[:]) } else { return false } } - -func (sig SignatureSecp256k1) MarshalJSON() ([]byte, error) { - return data.Encoder.Marshal(sig) -} - -func (sig *SignatureSecp256k1) UnmarshalJSON(enc []byte) error { - return data.Encoder.Unmarshal((*[]byte)(sig), enc) -} diff --git a/signature_test.go b/signature_test.go index 08e51940b..7bc94e677 100644 --- a/signature_test.go +++ b/signature_test.go @@ -1,13 +1,12 @@ package crypto import ( - "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/ed25519" - data "github.com/tendermint/go-wire/data" + "github.com/tendermint/go-wire" ) func TestSignAndValidateEd25519(t *testing.T) { @@ -22,9 +21,9 @@ func TestSignAndValidateEd25519(t *testing.T) { assert.True(t, pubKey.VerifyBytes(msg, sig)) // Mutate the signature, just one bit. - sigEd := sig.Unwrap().(SignatureEd25519) + sigEd := sig.(SignatureEd25519) sigEd[7] ^= byte(0x01) - sig = sigEd.Wrap() + sig = sigEd assert.False(t, pubKey.VerifyBytes(msg, sig)) } @@ -39,31 +38,28 @@ func TestSignAndValidateSecp256k1(t *testing.T) { assert.True(t, pubKey.VerifyBytes(msg, sig)) // Mutate the signature, just one bit. - sigEd := sig.Unwrap().(SignatureSecp256k1) + sigEd := sig.(SignatureSecp256k1) sigEd[3] ^= byte(0x01) - sig = sigEd.Wrap() + sig = sigEd assert.False(t, pubKey.VerifyBytes(msg, sig)) } func TestSignatureEncodings(t *testing.T) { cases := []struct { - privKey PrivKey - sigSize int - sigType byte - sigName string + privKey PrivKey + sigSize int + sigPrefix wire.PrefixBytes }{ { - privKey: GenPrivKeyEd25519().Wrap(), - sigSize: ed25519.SignatureSize, - sigType: TypeEd25519, - sigName: NameEd25519, + privKey: GenPrivKeyEd25519(), + sigSize: ed25519.SignatureSize, + sigPrefix: [4]byte{0xe4, 0x51, 0x7b, 0xa3}, }, { - privKey: GenPrivKeySecp256k1().Wrap(), - sigSize: 0, // unknown - sigType: TypeSecp256k1, - sigName: NameSecp256k1, + privKey: GenPrivKeySecp256k1(), + sigSize: 0, // unknown + sigPrefix: [4]byte{0x37, 0xb9, 0x21, 0x3e}, }, } @@ -75,91 +71,37 @@ func TestSignatureEncodings(t *testing.T) { sig := tc.privKey.Sign(msg) // store as wire - bin, err := data.ToWire(sig) + bin, err := cdc.MarshalBinary(sig) require.Nil(t, err, "%+v", err) if tc.sigSize != 0 { - assert.Equal(t, tc.sigSize+1, len(bin)) + assert.Equal(t, tc.sigSize+4, len(bin)) } - assert.Equal(t, tc.sigType, bin[0]) + assert.Equal(t, tc.sigPrefix[:], bin[0:4]) // and back - sig2 := Signature{} - err = data.FromWire(bin, &sig2) + sig2 := Signature(nil) + err = cdc.UnmarshalBinary(bin, &sig2) require.Nil(t, err, "%+v", err) assert.EqualValues(t, sig, sig2) assert.True(t, pubKey.VerifyBytes(msg, sig2)) - // store as json - js, err := data.ToJSON(sig) - require.Nil(t, err, "%+v", err) - assert.True(t, strings.Contains(string(js), tc.sigName)) - - // and back - sig3 := Signature{} - err = data.FromJSON(js, &sig3) - require.Nil(t, err, "%+v", err) - assert.EqualValues(t, sig, sig3) - assert.True(t, pubKey.VerifyBytes(msg, sig3)) - - // and make sure we can textify it - text, err := data.ToText(sig) - require.Nil(t, err, "%+v", err) - assert.True(t, strings.HasPrefix(text, tc.sigName)) - } -} - -func TestWrapping(t *testing.T) { - // construct some basic constructs - msg := CRandBytes(128) - priv := GenPrivKeyEd25519() - pub := priv.PubKey() - sig := priv.Sign(msg) - - // do some wrapping - pubs := []PubKey{ - PubKey{nil}, - pub.Wrap(), - pub.Wrap().Wrap().Wrap(), - PubKey{PubKey{PubKey{pub}}}.Wrap(), - } - for _, p := range pubs { - _, ok := p.PubKeyInner.(PubKey) - assert.False(t, ok) - } - - sigs := []Signature{ - Signature{nil}, - sig.Wrap(), - sig.Wrap().Wrap().Wrap(), - Signature{Signature{Signature{sig}}}.Wrap(), - } - for _, s := range sigs { - _, ok := s.SignatureInner.(Signature) - assert.False(t, ok) - } - -} - -func TestPrivKeyEquality(t *testing.T) { - { - privKey := GenPrivKeySecp256k1().Wrap() - privKey2 := GenPrivKeySecp256k1().Wrap() - assert.False(t, privKey.Equals(privKey2)) - assert.False(t, privKey2.Equals(privKey)) - - privKeyCopy := privKey // copy - assert.True(t, privKey.Equals(privKeyCopy)) - assert.True(t, privKeyCopy.Equals(privKey)) - } - - { - privKey := GenPrivKeyEd25519().Wrap() - privKey2 := GenPrivKeyEd25519().Wrap() - assert.False(t, privKey.Equals(privKey2)) - assert.False(t, privKey2.Equals(privKey)) - - privKeyCopy := privKey // copy - assert.True(t, privKey.Equals(privKeyCopy)) - assert.True(t, privKeyCopy.Equals(privKey)) + /* + // store as json + js, err := data.ToJSON(sig) + require.Nil(t, err, "%+v", err) + assert.True(t, strings.Contains(string(js), tc.sigName)) + + // and back + sig3 := Signature{} + err = data.FromJSON(js, &sig3) + require.Nil(t, err, "%+v", err) + assert.EqualValues(t, sig, sig3) + assert.True(t, pubKey.VerifyBytes(msg, sig3)) + + // and make sure we can textify it + text, err := data.ToText(sig) + require.Nil(t, err, "%+v", err) + assert.True(t, strings.HasPrefix(text, tc.sigName)) + */ } } diff --git a/signatureinner_wrapper.go b/signatureinner_wrapper.go deleted file mode 100644 index 1fdd790d6..000000000 --- a/signatureinner_wrapper.go +++ /dev/null @@ -1,62 +0,0 @@ -// Generated by: main -// TypeWriter: wrapper -// Directive: +gen on SignatureInner - -package crypto - -import ( - "github.com/tendermint/go-wire/data" -) - -// Auto-generated adapters for happily unmarshaling interfaces -// Apache License 2.0 -// Copyright (c) 2017 Ethan Frey (ethan.frey@tendermint.com) - -type Signature struct { - SignatureInner "json:\"unwrap\"" -} - -var SignatureMapper = data.NewMapper(Signature{}) - -func (h Signature) MarshalJSON() ([]byte, error) { - return SignatureMapper.ToJSON(h.SignatureInner) -} - -func (h *Signature) UnmarshalJSON(data []byte) (err error) { - parsed, err := SignatureMapper.FromJSON(data) - if err == nil && parsed != nil { - h.SignatureInner = parsed.(SignatureInner) - } - return err -} - -// Unwrap recovers the concrete interface safely (regardless of levels of embeds) -func (h Signature) Unwrap() SignatureInner { - hi := h.SignatureInner - for wrap, ok := hi.(Signature); ok; wrap, ok = hi.(Signature) { - hi = wrap.SignatureInner - } - return hi -} - -func (h Signature) Empty() bool { - return h.SignatureInner == nil -} - -/*** below are bindings for each implementation ***/ - -func init() { - SignatureMapper.RegisterImplementation(SignatureEd25519{}, "ed25519", 0x1) -} - -func (hi SignatureEd25519) Wrap() Signature { - return Signature{hi} -} - -func init() { - SignatureMapper.RegisterImplementation(SignatureSecp256k1{}, "secp256k1", 0x2) -} - -func (hi SignatureSecp256k1) Wrap() Signature { - return Signature{hi} -} diff --git a/wire.go b/wire.go new file mode 100644 index 000000000..18035964f --- /dev/null +++ b/wire.go @@ -0,0 +1,36 @@ +package crypto + +import ( + "github.com/tendermint/go-wire" +) + +var cdc = wire.NewCodec() + +func init() { + // NOTE: It's important that there be no conflicts here, + // as that would change the canonical representations, + // and therefore change the address. + // TODO: Add feature to go-wire to ensure that there + // are no conflicts. + RegisterWire(cdc) +} + +func RegisterWire(cdc *wire.Codec) { + cdc.RegisterInterface((*PubKey)(nil), nil) + cdc.RegisterConcrete(PubKeyEd25519{}, + "com.tendermint.wire.PubKeyEd25519", nil) + cdc.RegisterConcrete(PubKeySecp256k1{}, + "com.tendermint.wire.PubKeySecp256k1", nil) + + cdc.RegisterInterface((*PrivKey)(nil), nil) + cdc.RegisterConcrete(PrivKeyEd25519{}, + "com.tendermint.wire.PrivKeyEd25519", nil) + cdc.RegisterConcrete(PrivKeySecp256k1{}, + "com.tendermint.wire.PrivKeySecp256k1", nil) + + cdc.RegisterInterface((*Signature)(nil), nil) + cdc.RegisterConcrete(SignatureEd25519{}, + "com.tendermint.wire.SignatureKeyEd25519", nil) + cdc.RegisterConcrete(SignatureSecp256k1{}, + "com.tendermint.wire.SignatureKeySecp256k1", nil) +} From 32741be2126500d600cede1e2016bbbe2754cb46 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 14 Jan 2018 17:40:16 -0500 Subject: [PATCH 195/273] update glide for go-wire and tmlibs --- glide.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/glide.lock b/glide.lock index c8e47160f..4cdfefa8c 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: ed34b08bfc24f64edbc1a16ad2e34198afefc0e2dc133be2c92c6f764f953234 -updated: 2018-01-13T18:02:43.833267692-08:00 +updated: 2018-01-14T17:39:01.480031112-05:00 imports: - name: github.com/btcsuite/btcd version: 2e60448ffcc6bf78332d1fe590260095f554dd78 @@ -14,7 +14,7 @@ imports: subpackages: - spew - name: github.com/go-kit/kit - version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c + version: 953e747656a7bbb5e1f998608b460458958b70cc subpackages: - log - log/level @@ -22,7 +22,7 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-stack/stack - version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf + version: 259ab82a6cad3992b4e21ff5cac294ccb06474bc - name: github.com/gogo/protobuf version: 342cbe0a04158f6dcb03ca0079991a51a4248c02 subpackages: @@ -40,7 +40,7 @@ imports: - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/syndtr/goleveldb - version: b89cc31ef7977104127d34c1bd31ebd1a9db2199 + version: 34011bf325bce385408353a30b101fe5e923eb6e subpackages: - leveldb - leveldb/cache @@ -60,15 +60,15 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: fde4a0bf4dd4c0ec0df2504f79f23ed7e6b3b452 + version: b93ebdd4f306833936c243561ec30af3455dc764 - name: github.com/tendermint/tmlibs - version: 2bb538b150f197a04a0b969a27e9ea24d35edbc1 + version: f2bc5432c31974bb3f5b1a80a53c38e37d481b8d subpackages: - common - db - log - name: golang.org/x/crypto - version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 + version: 95a4943f35d008beabde8c11e5075a1b714e6419 subpackages: - bcrypt - blowfish From 12142af1cb4e3479ea4ac98a3171debff87519c6 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 21 Jan 2018 19:03:23 -0800 Subject: [PATCH 196/273] Remove reliance on global wire.Marshal --- glide.lock | 14 +++++++------- priv_key.go | 5 ++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/glide.lock b/glide.lock index 4cdfefa8c..768641d19 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: ed34b08bfc24f64edbc1a16ad2e34198afefc0e2dc133be2c92c6f764f953234 -updated: 2018-01-14T17:39:01.480031112-05:00 +updated: 2018-01-21T19:02:30.081003208-08:00 imports: - name: github.com/btcsuite/btcd version: 2e60448ffcc6bf78332d1fe590260095f554dd78 @@ -14,7 +14,7 @@ imports: subpackages: - spew - name: github.com/go-kit/kit - version: 953e747656a7bbb5e1f998608b460458958b70cc + version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c subpackages: - log - log/level @@ -22,7 +22,7 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-stack/stack - version: 259ab82a6cad3992b4e21ff5cac294ccb06474bc + version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf - name: github.com/gogo/protobuf version: 342cbe0a04158f6dcb03ca0079991a51a4248c02 subpackages: @@ -40,7 +40,7 @@ imports: - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/syndtr/goleveldb - version: 34011bf325bce385408353a30b101fe5e923eb6e + version: b89cc31ef7977104127d34c1bd31ebd1a9db2199 subpackages: - leveldb - leveldb/cache @@ -60,15 +60,15 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: b93ebdd4f306833936c243561ec30af3455dc764 + version: 0cce10e82786f2d501827fbe158747dbc4ceeb43 - name: github.com/tendermint/tmlibs - version: f2bc5432c31974bb3f5b1a80a53c38e37d481b8d + version: 7a52d47a1676a9fe61d07fde0a48a733cce564c6 subpackages: - common - db - log - name: golang.org/x/crypto - version: 95a4943f35d008beabde8c11e5075a1b714e6419 + version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 subpackages: - bcrypt - blowfish diff --git a/priv_key.go b/priv_key.go index b86b30f8b..adacb1379 100644 --- a/priv_key.go +++ b/priv_key.go @@ -6,7 +6,6 @@ import ( secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" - "github.com/tendermint/go-wire" . "github.com/tendermint/tmlibs/common" ) @@ -76,7 +75,7 @@ func (privKey PrivKeyEd25519) String() string { // Deterministically generates new priv-key bytes from key. func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { - bz, err := wire.MarshalBinary(struct { + bz, err := cdc.MarshalBinary(struct { PrivKey [64]byte Index int }{privKey, index}) @@ -156,7 +155,7 @@ func (privKey PrivKeySecp256k1) String() string { /* // Deterministically generates new priv-key bytes from key. func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 { - newBytes := wire.BinarySha256(struct { + newBytes := cdc.BinarySha256(struct { PrivKey [64]byte Index int }{key, index}) From 6b2409f714c7cd8709be64dcdd98e51460335a70 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Fri, 2 Feb 2018 14:12:29 +0100 Subject: [PATCH 197/273] Update go-wire to develop --- glide.lock | 14 +++++++------- glide.yaml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/glide.lock b/glide.lock index 768641d19..1c6825b35 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ -hash: ed34b08bfc24f64edbc1a16ad2e34198afefc0e2dc133be2c92c6f764f953234 -updated: 2018-01-21T19:02:30.081003208-08:00 +hash: fd4a3648af3dd1d49623ce248ba98804bf5a9c6a1bc28d61d93d5e878ccd04d4 +updated: 2018-02-02T14:07:48.239589+01:00 imports: - name: github.com/btcsuite/btcd - version: 2e60448ffcc6bf78332d1fe590260095f554dd78 + version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e subpackages: - btcec - name: github.com/btcsuite/btcutil @@ -55,14 +55,14 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/ed25519 - version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 + version: 1f52c6f8b8a5c7908aff4497c186af344b428925 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 0cce10e82786f2d501827fbe158747dbc4ceeb43 + version: e723d95ac2838b7ae9919ada25004859236c32ff - name: github.com/tendermint/tmlibs - version: 7a52d47a1676a9fe61d07fde0a48a733cce564c6 + version: 95b53c80e1771be6b8c7083771a417e2a888c765 subpackages: - common - db @@ -87,7 +87,7 @@ testImports: subpackages: - difflib - name: github.com/stretchr/testify - version: b91bfb9ebec76498946beb6af7c0230c7cc7ba6c + version: 12b6f73e6084dad08a7c6e575284b177ecafbc71 subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index f92a8c9a4..be471e973 100644 --- a/glide.yaml +++ b/glide.yaml @@ -19,7 +19,7 @@ import: - package: github.com/tendermint/tmlibs version: sdk2 - package: github.com/tendermint/go-wire - version: sdk2 + version: develop - package: golang.org/x/crypto subpackages: - blowfish From 0391e499fb7881b164f70db24ce9f894cb6f5167 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Fri, 2 Feb 2018 18:31:25 +0100 Subject: [PATCH 198/273] Clean up glide.yaml --- glide.lock | 16 ++++++---------- glide.yaml | 25 +++++++++---------------- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/glide.lock b/glide.lock index 1c6825b35..4ffe6a73c 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: fd4a3648af3dd1d49623ce248ba98804bf5a9c6a1bc28d61d93d5e878ccd04d4 -updated: 2018-02-02T14:07:48.239589+01:00 +hash: 1466255448cc0ab79ed6e575df6db01d53895f9e39c141dbb4494fe8cb9ba506 +updated: 2018-02-02T18:29:54.201489+01:00 imports: - name: github.com/btcsuite/btcd version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e @@ -10,11 +10,11 @@ imports: subpackages: - base58 - name: github.com/davecgh/go-spew - version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 + version: 346938d642f2ec3594ed81d874461961cd0faa76 subpackages: - spew - name: github.com/go-kit/kit - version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c + version: 4dc7be5d2d12881735283bcab7352178e190fc71 subpackages: - log - log/level @@ -24,7 +24,7 @@ imports: - name: github.com/go-stack/stack version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf - name: github.com/gogo/protobuf - version: 342cbe0a04158f6dcb03ca0079991a51a4248c02 + version: 1adfc126b41513cc696b209667c8656ea7aac67c subpackages: - gogoproto - proto @@ -62,7 +62,7 @@ imports: - name: github.com/tendermint/go-wire version: e723d95ac2838b7ae9919ada25004859236c32ff - name: github.com/tendermint/tmlibs - version: 95b53c80e1771be6b8c7083771a417e2a888c765 + version: 2e765462234e7749806cd00fa326acc25d704448 subpackages: - common - db @@ -80,8 +80,6 @@ imports: - ripemd160 - salsa20/salsa testImports: -- name: github.com/mndrix/btcutil - version: d3a63a5752ecf3fbc06bd97365da752111c263df - name: github.com/pmezard/go-difflib version: d8ed2627bdf02c080bf22230dbb337003b7aba2d subpackages: @@ -91,7 +89,5 @@ testImports: subpackages: - assert - require -- name: github.com/tyler-smith/go-bip32 - version: 2c9cfd17756470a0b7c3e4b7954bae7d11035504 - name: github.com/tyler-smith/go-bip39 version: 8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc diff --git a/glide.yaml b/glide.yaml index be471e973..09e7c0671 100644 --- a/glide.yaml +++ b/glide.yaml @@ -6,36 +6,29 @@ import: - package: github.com/btcsuite/btcutil subpackages: - base58 -- package: github.com/syndtr/goleveldb - subpackages: - - leveldb - - leveldb/errors - - leveldb/iterator - - leveldb/opt - - leveldb/util +- package: github.com/howeyc/crc16 +- package: github.com/pkg/errors + version: ^0.8.0 - package: github.com/tendermint/ed25519 subpackages: - extra25519 -- package: github.com/tendermint/tmlibs - version: sdk2 - package: github.com/tendermint/go-wire version: develop +- package: github.com/tendermint/tmlibs + version: 2e765462234e7749806cd00fa326acc25d704448 + subpackages: + - common + - db - package: golang.org/x/crypto subpackages: - blowfish - nacl/secretbox - openpgp/armor - ripemd160 -- package: github.com/pkg/errors -- package: github.com/howeyc/crc16 -# Needs refactoring, shouldn't be implementing PrivKey -#- package: github.com/ethanfrey/ledger testImport: -- package: github.com/mndrix/btcutil - package: github.com/stretchr/testify - version: ^1.1.4 + version: ^1.2.1 subpackages: - assert - require -- package: github.com/tyler-smith/go-bip32 - package: github.com/tyler-smith/go-bip39 From 45b71f7d11214c35ae63dfb81f42c0da8db9e69e Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Fri, 2 Feb 2018 18:51:41 +0100 Subject: [PATCH 199/273] Bump tmlibs commit. Needs to be changed to develop as soon as tmlibs PR is merged --- glide.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glide.yaml b/glide.yaml index 09e7c0671..3bf7ad8b4 100644 --- a/glide.yaml +++ b/glide.yaml @@ -15,7 +15,7 @@ import: - package: github.com/tendermint/go-wire version: develop - package: github.com/tendermint/tmlibs - version: 2e765462234e7749806cd00fa326acc25d704448 + version: cbc63518e589d6b0069f9750127fa83dd6ea5ee3 subpackages: - common - db From 9e897ab8b03501fd40d9286112d9b6705131ce40 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 2 Feb 2018 23:34:07 -0500 Subject: [PATCH 200/273] update glide --- glide.lock | 12 ++++++------ glide.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/glide.lock b/glide.lock index 4ffe6a73c..6e712c790 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ -hash: 1466255448cc0ab79ed6e575df6db01d53895f9e39c141dbb4494fe8cb9ba506 -updated: 2018-02-02T18:29:54.201489+01:00 +hash: 95b2c2a089ca7242bc52c3bfe5a0286ae68201197f7f5855dd6e8f2ee3974068 +updated: 2018-02-02T23:14:21.166130626-05:00 imports: - name: github.com/btcsuite/btcd - version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e + version: 2e60448ffcc6bf78332d1fe590260095f554dd78 subpackages: - btcec - name: github.com/btcsuite/btcutil @@ -55,14 +55,14 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/ed25519 - version: 1f52c6f8b8a5c7908aff4497c186af344b428925 + version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: e723d95ac2838b7ae9919ada25004859236c32ff + version: 4c92f560ad0aa4105e19d0ed47cecb630353b57b - name: github.com/tendermint/tmlibs - version: 2e765462234e7749806cd00fa326acc25d704448 + version: 690d6c60701758ab757d11ef674906f64e6b618d subpackages: - common - db diff --git a/glide.yaml b/glide.yaml index 3bf7ad8b4..d99809211 100644 --- a/glide.yaml +++ b/glide.yaml @@ -15,7 +15,7 @@ import: - package: github.com/tendermint/go-wire version: develop - package: github.com/tendermint/tmlibs - version: cbc63518e589d6b0069f9750127fa83dd6ea5ee3 + version: develop subpackages: - common - db From 5a94049dbc076d447df4a9364e0aaf8e7ca2248a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 2 Feb 2018 23:42:22 -0500 Subject: [PATCH 201/273] update glide again --- glide.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index 6e712c790..02ad7f77b 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 95b2c2a089ca7242bc52c3bfe5a0286ae68201197f7f5855dd6e8f2ee3974068 -updated: 2018-02-02T23:14:21.166130626-05:00 +updated: 2018-02-02T23:41:28.391448359-05:00 imports: - name: github.com/btcsuite/btcd version: 2e60448ffcc6bf78332d1fe590260095f554dd78 @@ -60,7 +60,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 4c92f560ad0aa4105e19d0ed47cecb630353b57b + version: dec83f641903b22f039da3974607859715d0377e - name: github.com/tendermint/tmlibs version: 690d6c60701758ab757d11ef674906f64e6b618d subpackages: From 4fc3055dbd17aa1203d0abc64b9293f378da22ec Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 2 Feb 2018 23:50:24 -0500 Subject: [PATCH 202/273] update glide again --- glide.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index 02ad7f77b..6db38099a 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 95b2c2a089ca7242bc52c3bfe5a0286ae68201197f7f5855dd6e8f2ee3974068 -updated: 2018-02-02T23:41:28.391448359-05:00 +updated: 2018-02-02T23:50:03.327504896-05:00 imports: - name: github.com/btcsuite/btcd version: 2e60448ffcc6bf78332d1fe590260095f554dd78 @@ -62,7 +62,7 @@ imports: - name: github.com/tendermint/go-wire version: dec83f641903b22f039da3974607859715d0377e - name: github.com/tendermint/tmlibs - version: 690d6c60701758ab757d11ef674906f64e6b618d + version: 1d7fc78ea171587e9e63da566d3da1b127bfd14c subpackages: - common - db From b6d029050ba0d137d6c69f438d9c00303c584b97 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 25 Feb 2018 08:48:53 -0800 Subject: [PATCH 203/273] Switch to dep from glide for dependency resolution --- Gopkg.lock | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Gopkg.toml | 62 ++++++++++++++++++++ Makefile | 9 ++- 3 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 000000000..6dd1154b1 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,168 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/btcsuite/btcd" + packages = ["btcec"] + revision = "2e60448ffcc6bf78332d1fe590260095f554dd78" + +[[projects]] + branch = "master" + name = "github.com/btcsuite/btcutil" + packages = ["base58"] + revision = "501929d3d046174c3d39f0ea54ece471aa17238c" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/go-kit/kit" + packages = [ + "log", + "log/level", + "log/term" + ] + revision = "4dc7be5d2d12881735283bcab7352178e190fc71" + version = "v0.6.0" + +[[projects]] + name = "github.com/go-logfmt/logfmt" + packages = ["."] + revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" + version = "v0.3.0" + +[[projects]] + name = "github.com/go-stack/stack" + packages = ["."] + revision = "817915b46b97fd7bb80e8ab6b69f01a53ac3eebf" + version = "v1.6.0" + +[[projects]] + name = "github.com/gogo/protobuf" + packages = [ + "gogoproto", + "proto", + "protoc-gen-gogo/descriptor" + ] + revision = "1adfc126b41513cc696b209667c8656ea7aac67c" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "553a641470496b2327abcac10b36396bd98e45c9" + +[[projects]] + branch = "master" + name = "github.com/howeyc/crc16" + packages = ["."] + revision = "2b2a61e366a66d3efb279e46176e7291001e0354" + +[[projects]] + branch = "master" + name = "github.com/jmhodges/levigo" + packages = ["."] + revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" + +[[projects]] + branch = "master" + name = "github.com/kr/logfmt" + packages = ["."] + revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require" + ] + revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" + version = "v1.2.1" + +[[projects]] + name = "github.com/syndtr/goleveldb" + packages = [ + "leveldb", + "leveldb/cache", + "leveldb/comparer", + "leveldb/errors", + "leveldb/filter", + "leveldb/iterator", + "leveldb/journal", + "leveldb/memdb", + "leveldb/opt", + "leveldb/storage", + "leveldb/table", + "leveldb/util" + ] + revision = "b89cc31ef7977104127d34c1bd31ebd1a9db2199" + +[[projects]] + branch = "master" + name = "github.com/tendermint/ed25519" + packages = [ + ".", + "edwards25519", + "extra25519" + ] + revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" + +[[projects]] + branch = "develop" + name = "github.com/tendermint/go-wire" + packages = ["."] + revision = "dec83f641903b22f039da3974607859715d0377e" + +[[projects]] + branch = "develop" + name = "github.com/tendermint/tmlibs" + packages = [ + "common", + "db", + "log" + ] + revision = "1d7fc78ea171587e9e63da566d3da1b127bfd14c" + +[[projects]] + branch = "master" + name = "github.com/tyler-smith/go-bip39" + packages = ["."] + revision = "8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc" + +[[projects]] + name = "golang.org/x/crypto" + packages = [ + "bcrypt", + "blowfish", + "nacl/secretbox", + "openpgp/armor", + "openpgp/errors", + "pbkdf2", + "poly1305", + "ripemd160", + "salsa20/salsa" + ] + revision = "edd5e9b0879d13ee6970a50153d85b8fec9f7686" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "e0628df240b8ceeb91403f5218f5561d8580f15f3d5b0ea0da40710d1cba3707" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 000000000..058eb5838 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,62 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + branch = "master" + name = "github.com/btcsuite/btcutil" + +[[constraint]] + branch = "master" + name = "github.com/howeyc/crc16" + +[[constraint]] + name = "github.com/pkg/errors" + version = "0.8.0" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.1" + +[[constraint]] + branch = "master" + name = "github.com/tendermint/ed25519" + +[[constraint]] + branch = "develop" + name = "github.com/tendermint/go-wire" + +[[constraint]] + branch = "develop" + name = "github.com/tendermint/tmlibs" + +[[constraint]] + branch = "master" + name = "github.com/tyler-smith/go-bip39" + +[prune] + go-tests = true + unused-packages = true diff --git a/Makefile b/Makefile index 19d797f1d..2b7e99c7f 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ GOTOOLS = \ - github.com/Masterminds/glide \ + github.com/golang/dep/cmd/dep \ github.com/jteeuwen/go-bindata/go-bindata # gopkg.in/alecthomas/gometalinter.v2 \ # @@ -43,16 +43,15 @@ update_tools: get_vendor_deps: @rm -rf vendor/ - @echo "--> Running glide install" - @glide install + @echo "--> Running dep ensure" + @dep ensure ######################################## ### Testing test: - go test -p 1 `glide novendor` - + go test -p 1 $(go list ./... | grep -v vendor) ######################################## ### Formatting, linting, and vetting From 3570c2eb9e8c6fef75a416d6f7eb08a075f846b0 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 25 Feb 2018 09:41:32 -0800 Subject: [PATCH 204/273] Fix test in makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2b7e99c7f..b8c95b7df 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ get_vendor_deps: ### Testing test: - go test -p 1 $(go list ./... | grep -v vendor) + go test -p 1 $(shell go list ./... | grep -v vendor) ######################################## ### Formatting, linting, and vetting From 6c6d01b51c56f8b155cf9712e79de8fb12a82803 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 2 Mar 2018 03:08:48 -0500 Subject: [PATCH 205/273] Keybase refactor Same as 788cc0a79256d4fe0448e17a90217acf3d61346b but without the new go-wire --- {nano => _nano}/keys.go | 0 {nano => _nano}/keys_test.go | 0 {nano => _nano}/sign.go | 0 {nano => _nano}/sign_test.go | 0 glide.lock | 32 +++-- glide.yaml | 4 +- keys/keybase.go | 221 +++++++++++++------------------- keys/keybase_test.go | 242 ++++++++++++++++++----------------- keys/keys.go | 32 +++++ keys/mintkey.go | 26 ++++ keys/types.go | 64 +++++---- 11 files changed, 325 insertions(+), 296 deletions(-) rename {nano => _nano}/keys.go (100%) rename {nano => _nano}/keys_test.go (100%) rename {nano => _nano}/sign.go (100%) rename {nano => _nano}/sign_test.go (100%) create mode 100644 keys/keys.go diff --git a/nano/keys.go b/_nano/keys.go similarity index 100% rename from nano/keys.go rename to _nano/keys.go diff --git a/nano/keys_test.go b/_nano/keys_test.go similarity index 100% rename from nano/keys_test.go rename to _nano/keys_test.go diff --git a/nano/sign.go b/_nano/sign.go similarity index 100% rename from nano/sign.go rename to _nano/sign.go diff --git a/nano/sign_test.go b/_nano/sign_test.go similarity index 100% rename from nano/sign_test.go rename to _nano/sign_test.go diff --git a/glide.lock b/glide.lock index 5032685c2..add082c5b 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ -hash: a21061afc44c148eb6bfeb91478b520661f3d086234383a0208d915b0cb058b8 -updated: 2017-12-27T14:29:49.534901894-08:00 +hash: 575a7b42282ded36e66490c44105140387d305b07e8e5a9e8e4b9eeb6f995e66 +updated: 2018-03-02T03:06:22.122862726-05:00 imports: - name: github.com/btcsuite/btcd - version: c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e + version: 50de9da05b50eb15658bb350f6ea24368a111ab7 subpackages: - btcec - name: github.com/btcsuite/btcutil @@ -10,11 +10,9 @@ imports: subpackages: - base58 - name: github.com/ethanfrey/ledger - version: 5e432577be582bd18a3b4a9cd75dae7a317ade36 -- name: github.com/flynn/hid - version: ed06a31c6245d4552e8dbba7e32e5b010b875d65 + version: 23a7bb9d74bc83a862fcb4bddde24215b2295ad9 - name: github.com/go-kit/kit - version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c + version: 4dc7be5d2d12881735283bcab7352178e190fc71 subpackages: - log - log/level @@ -22,9 +20,9 @@ imports: - name: github.com/go-logfmt/logfmt version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 - name: github.com/go-stack/stack - version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf + version: 259ab82a6cad3992b4e21ff5cac294ccb06474bc - name: github.com/gogo/protobuf - version: 342cbe0a04158f6dcb03ca0079991a51a4248c02 + version: 1adfc126b41513cc696b209667c8656ea7aac67c subpackages: - gogoproto - proto @@ -40,7 +38,7 @@ imports: - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/syndtr/goleveldb - version: b89cc31ef7977104127d34c1bd31ebd1a9db2199 + version: 34011bf325bce385408353a30b101fe5e923eb6e subpackages: - leveldb - leveldb/cache @@ -55,23 +53,23 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/ed25519 - version: 1f52c6f8b8a5c7908aff4497c186af344b428925 + version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 subpackages: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 27be46e25124ddf775e23317a83647ce62a93f6b + version: 67ee274c5f9da166622f3b6e6747003b563e3742 subpackages: - data - data/base58 - name: github.com/tendermint/tmlibs - version: 93c05aa8c06ef38f2b15fcdd1d91eafefda2732d + version: 1b9b5652a199ab0be2e781393fb275b66377309d subpackages: - common - db - log - name: golang.org/x/crypto - version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 + version: 1875d0a70c90e57f11972aefd42276df65e895b9 subpackages: - bcrypt - blowfish @@ -84,17 +82,17 @@ imports: - salsa20/salsa testImports: - name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + version: 346938d642f2ec3594ed81d874461961cd0faa76 subpackages: - spew - name: github.com/mndrix/btcutil version: d3a63a5752ecf3fbc06bd97365da752111c263df - name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + version: 792786c7400a136282c1664665ae0a8db921c6c2 subpackages: - difflib - name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + version: 12b6f73e6084dad08a7c6e575284b177ecafbc71 subpackages: - assert - require diff --git a/glide.yaml b/glide.yaml index f9df5c18d..c5ac4992b 100644 --- a/glide.yaml +++ b/glide.yaml @@ -17,9 +17,9 @@ import: subpackages: - extra25519 - package: github.com/tendermint/tmlibs - version: sdk2 + version: master - package: github.com/tendermint/go-wire - version: develop + version: bucky/new-go-wire-api subpackages: - data - data/base58 diff --git a/keys/keybase.go b/keys/keybase.go index c72518748..2c1d64a27 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -6,16 +6,10 @@ import ( "github.com/pkg/errors" crypto "github.com/tendermint/go-crypto" - dbm "github.com/tendermint/tmlibs/db" - "github.com/tendermint/go-crypto/keys/words" - "github.com/tendermint/go-crypto/nano" + dbm "github.com/tendermint/tmlibs/db" ) -// XXX Lets use go-crypto/bcrypt and ascii encoding directly in here without -// further wrappers around a store or DB. -// Copy functions from: https://github.com/tendermint/mintkey/blob/master/cmd/mintkey/common.go -// // dbKeybase combines encyption and storage implementation to provide // a full-featured key manager type dbKeybase struct { @@ -32,58 +26,59 @@ func New(db dbm.DB, codec words.Codec) dbKeybase { var _ Keybase = dbKeybase{} -// Create generates a new key and persists it storage, encrypted using the passphrase. -// It returns the generated seedphrase (mnemonic) and the key Info. -// It returns an error if it fails to generate a key for the given algo type, -// or if another key is already stored under the same name. -func (kb dbKeybase) Create(name, passphrase, algo string) (string, Info, error) { +// Create generates a new key and persists it to storage, encrypted +// using the passphrase. It returns the generated seedphrase +// (mnemonic) and the key Info. It returns an error if it fails to +// generate a key for the given algo type, or if another key is +// already stored under the same name. +func (kb dbKeybase) Create(name, passphrase string, algo CryptoAlgo) (Info, string, error) { // NOTE: secret is SHA256 hashed by secp256k1 and ed25519. // 16 byte secret corresponds to 12 BIP39 words. // XXX: Ledgers use 24 words now - should we ? secret := crypto.CRandBytes(16) - key, err := generate(algo, secret) + priv, err := generate(algo, secret) if err != nil { - return "", Info{}, err + return Info{}, "", err } // encrypt and persist the key - public := kb.writeKey(key, name, passphrase) + info := kb.writeKey(priv, name, passphrase) + + // we append the type byte to the serialized secret to help with + // recovery + // ie [secret] = [type] + [secret] + typ := cryptoAlgoToByte(algo) + secret = append([]byte{typ}, secret...) // return the mnemonic phrase words, err := kb.codec.BytesToWords(secret) - seedphrase := strings.Join(words, " ") - return seedphrase, public, err -} - -// Recover converts a seedphrase to a private key and persists it, encrypted with the given passphrase. -// Functions like Create, but seedphrase is input not output. -func (kb dbKeybase) Recover(name, passphrase, algo string, seedphrase string) (Info, error) { - - key, err := kb.SeedToPrivKey(algo, seedphrase) - if err != nil { - return Info{}, err - } - - // Valid seedphrase. Encrypt key and persist to disk. - public := kb.writeKey(key, name, passphrase) - return public, nil + seed := strings.Join(words, " ") + return info, seed, err } -// SeedToPrivKey returns the private key corresponding to a seedphrase -// without persisting the private key. -// TODO: enable the keybase to just hold these in memory so we can sign without persisting (?) -func (kb dbKeybase) SeedToPrivKey(algo, seedphrase string) (crypto.PrivKey, error) { +// Recover converts a seedphrase to a private key and persists it, +// encrypted with the given passphrase. Functions like Create, but +// seedphrase is input not output. +func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { words := strings.Split(strings.TrimSpace(seedphrase), " ") secret, err := kb.codec.WordsToBytes(words) if err != nil { - return crypto.PrivKey{}, err + return Info{}, err } - key, err := generate(algo, secret) + // secret is comprised of the actual secret with the type + // appended. + // ie [secret] = [type] + [secret] + typ, secret := secret[0], secret[1:] + algo := byteToCryptoAlgo(typ) + priv, err := generate(algo, secret) if err != nil { - return crypto.PrivKey{}, err + return Info{}, err } - return key, nil + + // encrypt and persist key. + public := kb.writeKey(priv, name, passphrase) + return public, err } // List returns the keys from storage in alphabetical order. @@ -92,75 +87,56 @@ func (kb dbKeybase) List() ([]Info, error) { iter := kb.db.Iterator(nil, nil) defer iter.Close() for ; iter.Valid(); iter.Next() { - key := iter.Key() - if isPub(key) { - info, err := readInfo(iter.Value()) - if err != nil { - return nil, err - } - res = append(res, info) + // key := iter.Key() + info, err := readInfo(iter.Value()) + if err != nil { + return nil, err } + res = append(res, info) } return res, nil } // Get returns the public information about one key. func (kb dbKeybase) Get(name string) (Info, error) { - bs := kb.db.Get(pubName(name)) + bs := kb.db.Get(infoKey(name)) return readInfo(bs) } // Sign signs the msg with the named key. // It returns an error if the key doesn't exist or the decryption fails. -// TODO: what if leddger fails ? -func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pk crypto.PubKey, err error) { - var key crypto.PrivKey - armorStr := kb.db.Get(privName(name)) - key, err = unarmorDecryptPrivKey(string(armorStr), passphrase) +func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pub crypto.PubKey, err error) { + info, err := kb.Get(name) if err != nil { return } - - sig = key.Sign(msg) - pk = key.PubKey() - return -} - -// Export decodes the private key with the current password, encrypts -// it with a secure one-time password and generates an armored private key -// that can be Imported by another dbKeybase. -// -// This is designed to copy from one device to another, or provide backups -// during version updates. -func (kb dbKeybase) Export(name, oldpass, transferpass string) ([]byte, error) { - armorStr := kb.db.Get(privName(name)) - key, err := unarmorDecryptPrivKey(string(armorStr), oldpass) + priv, err := unarmorDecryptPrivKey(info.PrivKeyArmor, passphrase) if err != nil { - return nil, err + return } + sig = priv.Sign(msg) + pub = priv.PubKey() + return +} - if transferpass == "" { - return key.Bytes(), nil +func (kb dbKeybase) Export(name string) (armor string, err error) { + bz := kb.db.Get(infoKey(name)) + if bz == nil { + return "", errors.New("No key to export with name " + name) } - armorBytes := encryptArmorPrivKey(key, transferpass) - return []byte(armorBytes), nil + return armorInfoBytes(bz), nil } -// Import accepts bytes generated by Export along with the same transferpass. -// If they are valid, it stores the password under the given name with the -// new passphrase. -func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err error) { - var key crypto.PrivKey - if transferpass == "" { - key, err = crypto.PrivKeyFromBytes(data) - } else { - key, err = unarmorDecryptPrivKey(string(data), transferpass) +func (kb dbKeybase) Import(name string, armor string) (err error) { + bz := kb.db.Get(infoKey(name)) + if len(bz) > 0 { + return errors.New("Cannot overwrite data for name " + name) } + infoBytes, err := unarmorInfoBytes(armor) if err != nil { - return err + return } - - kb.writeKey(key, name, newpass) + kb.db.Set(infoKey(name), infoBytes) return nil } @@ -168,80 +144,59 @@ func (kb dbKeybase) Import(name, newpass, transferpass string, data []byte) (err // proper passphrase before deleting it (for security). func (kb dbKeybase) Delete(name, passphrase string) error { // verify we have the proper password before deleting - bs := kb.db.Get(privName(name)) - _, err := unarmorDecryptPrivKey(string(bs), passphrase) + info, err := kb.Get(name) if err != nil { return err } - kb.db.DeleteSync(pubName(name)) - kb.db.DeleteSync(privName(name)) + _, err = unarmorDecryptPrivKey(info.PrivKeyArmor, passphrase) + if err != nil { + return err + } + kb.db.DeleteSync(infoKey(name)) return nil } -// Update changes the passphrase with which an already stored key is encrypted. +// Update changes the passphrase with which an already stored key is +// encrypted. // -// oldpass must be the current passphrase used for encryption, newpass will be -// the only valid passphrase from this time forward. +// oldpass must be the current passphrase used for encryption, +// newpass will be the only valid passphrase from this time forward. func (kb dbKeybase) Update(name, oldpass, newpass string) error { - bs := kb.db.Get(privName(name)) - key, err := unarmorDecryptPrivKey(string(bs), oldpass) + info, err := kb.Get(name) + if err != nil { + return err + } + key, err := unarmorDecryptPrivKey(info.PrivKeyArmor, oldpass) if err != nil { return err } - // Generate the public bytes and the encrypted privkey - public := info(name, key) - private := encryptArmorPrivKey(key, newpass) - - // We must delete first, as Putting over an existing name returns an error. - // Must be done atomically with the write or we could lose the key. - batch := kb.db.NewBatch() - batch.Delete(pubName(name)) - batch.Delete(privName(name)) - batch.Set(pubName(name), public.bytes()) - batch.Set(privName(name), []byte(private)) - batch.Write() - + kb.writeKey(key, name, newpass) return nil } - -//--------------------------------------------------------------------------------------- - func (kb dbKeybase) writeKey(priv crypto.PrivKey, name, passphrase string) Info { - // Generate the public bytes and the encrypted privkey - public := info(name, priv) - private := encryptArmorPrivKey(priv, passphrase) + // generate the encrypted privkey + privArmor := encryptArmorPrivKey(priv, passphrase) + // make Info + info := newInfo(name, priv.PubKey(), privArmor) - // Write them both - kb.db.SetSync(pubName(name), public.bytes()) - kb.db.SetSync(privName(name), []byte(private)) - - return public + // write them both + kb.db.SetSync(infoKey(name), info.bytes()) + return info } -// TODO: use a `type TypeKeyAlgo string` (?) -func generate(algo string, secret []byte) (crypto.PrivKey, error) { +func generate(algo CryptoAlgo, secret []byte) (crypto.PrivKey, error) { switch algo { - case crypto.NameEd25519: + case AlgoEd25519: return crypto.GenPrivKeyEd25519FromSecret(secret).Wrap(), nil - case crypto.NameSecp256k1: + case AlgoSecp256k1: return crypto.GenPrivKeySecp256k1FromSecret(secret).Wrap(), nil - case nano.NameLedgerEd25519: - return nano.NewPrivKeyLedgerEd25519() default: err := errors.Errorf("Cannot generate keys for algorithm: %s", algo) return crypto.PrivKey{}, err } } -func pubName(name string) []byte { - return []byte(fmt.Sprintf("%s.pub", name)) -} - -func privName(name string) []byte { - return []byte(fmt.Sprintf("%s.priv", name)) -} - -func isPub(name []byte) bool { - return strings.HasSuffix(string(name), ".pub") +func infoKey(name string) []byte { + return []byte(fmt.Sprintf("%s.info", name)) } diff --git a/keys/keybase_test.go b/keys/keybase_test.go index 12e5205b0..84c81c81f 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -2,24 +2,20 @@ package keys_test import ( "fmt" - "os" "testing" - asrt "github.com/stretchr/testify/assert" - rqr "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" - cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" - crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto/keys" "github.com/tendermint/go-crypto/keys/words" - "github.com/tendermint/go-crypto/nano" ) // TestKeyManagement makes sure we can manipulate these keys well func TestKeyManagement(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -27,84 +23,83 @@ func TestKeyManagement(t *testing.T) { words.MustLoadCodec("english"), ) - algo := crypto.NameEd25519 + algo := keys.AlgoEd25519 n1, n2, n3 := "personal", "business", "other" p1, p2 := "1234", "really-secure!@#$" // Check empty state l, err := cstore.List() - require.Nil(err) - assert.Empty(l) + require.Nil(t, err) + assert.Empty(t, l) // create some keys _, err = cstore.Get(n1) - assert.NotNil(err) - _, i, err := cstore.Create(n1, p1, algo) - require.Equal(n1, i.Name) - require.Nil(err) + assert.NotNil(t, err) + i, _, err := cstore.Create(n1, p1, algo) + require.Equal(t, n1, i.Name) + require.Nil(t, err) _, _, err = cstore.Create(n2, p2, algo) - require.Nil(err) + require.Nil(t, err) // we can get these keys i2, err := cstore.Get(n2) - assert.Nil(err) + assert.Nil(t, err) _, err = cstore.Get(n3) - assert.NotNil(err) + assert.NotNil(t, err) // list shows them in order keyS, err := cstore.List() - require.Nil(err) - require.Equal(2, len(keyS)) + require.Nil(t, err) + require.Equal(t, 2, len(keyS)) // note these are in alphabetical order - assert.Equal(n2, keyS[0].Name) - assert.Equal(n1, keyS[1].Name) - assert.Equal(i2.PubKey, keyS[0].PubKey) + assert.Equal(t, n2, keyS[0].Name) + assert.Equal(t, n1, keyS[1].Name) + assert.Equal(t, i2.PubKey, keyS[0].PubKey) // deleting a key removes it err = cstore.Delete("bad name", "foo") - require.NotNil(err) + require.NotNil(t, err) err = cstore.Delete(n1, p1) - require.Nil(err) + require.Nil(t, err) keyS, err = cstore.List() - require.Nil(err) - assert.Equal(1, len(keyS)) + require.Nil(t, err) + assert.Equal(t, 1, len(keyS)) _, err = cstore.Get(n1) - assert.NotNil(err) + assert.NotNil(t, err) // make sure that it only signs with the right password // tx := mock.NewSig([]byte("mytransactiondata")) // err = cstore.Sign(n2, p1, tx) - // assert.NotNil(err) + // assert.NotNil(t, err) // err = cstore.Sign(n2, p2, tx) - // assert.Nil(err, "%+v", err) + // assert.Nil(t, err, "%+v", err) // sigs, err := tx.Signers() - // assert.Nil(err, "%+v", err) - // if assert.Equal(1, len(sigs)) { - // assert.Equal(i2.PubKey, sigs[0]) + // assert.Nil(t, err, "%+v", err) + // if assert.Equal(t, 1, len(sigs)) { + // assert.Equal(t, i2.PubKey, sigs[0]) // } } // TestSignVerify does some detailed checks on how we sign and validate // signatures func TestSignVerify(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), words.MustLoadCodec("english"), ) - algo := crypto.NameSecp256k1 + algo := keys.AlgoSecp256k1 n1, n2 := "some dude", "a dudette" p1, p2 := "1234", "foobar" // create two users and get their info - _, i1, err := cstore.Create(n1, p1, algo) - require.Nil(err) + i1, _, err := cstore.Create(n1, p1, algo) + require.Nil(t, err) - _, i2, err := cstore.Create(n2, p2, algo) - require.Nil(err) + i2, _, err := cstore.Create(n2, p2, algo) + require.Nil(t, err) // let's try to sign some messages d1 := []byte("my first message") @@ -112,20 +107,20 @@ func TestSignVerify(t *testing.T) { // try signing both data with both keys... s11, pub1, err := cstore.Sign(n1, p1, d1) - require.Nil(err) - require.Equal(i1.PubKey, pub1) + require.Nil(t, err) + require.Equal(t, i1.PubKey, pub1) s12, pub1, err := cstore.Sign(n1, p1, d2) - require.Nil(err) - require.Equal(i1.PubKey, pub1) + require.Nil(t, err) + require.Equal(t, i1.PubKey, pub1) s21, pub2, err := cstore.Sign(n2, p2, d1) - require.Nil(err) - require.Equal(i2.PubKey, pub2) + require.Nil(t, err) + require.Equal(t, i2.PubKey, pub2) s22, pub2, err := cstore.Sign(n2, p2, d2) - require.Nil(err) - require.Equal(i2.PubKey, pub2) + require.Nil(t, err) + require.Equal(t, i2.PubKey, pub2) // let's try to validate and make sure it only works when everything is proper cases := []struct { @@ -148,17 +143,17 @@ func TestSignVerify(t *testing.T) { for i, tc := range cases { valid := tc.key.VerifyBytes(tc.data, tc.sig) - assert.Equal(tc.valid, valid, "%d", i) + assert.Equal(t, tc.valid, valid, "%d", i) } } +/* // TestSignWithLedger makes sure we have ledger compatibility with // the crypto store. // // This test will only succeed with a ledger attached to the computer // and the cosmos app open func TestSignWithLedger(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) if os.Getenv("WITH_LEDGER") == "" { t.Skip("Set WITH_LEDGER to run code on real ledger") } @@ -172,19 +167,19 @@ func TestSignWithLedger(t *testing.T) { p := "hard2hack" // create a nano user - _, c, err := cstore.Create(n, p, nano.NameLedgerEd25519) - require.Nil(err, "%+v", err) - assert.Equal(c.Name, n) + c, _, err := cstore.Create(n, p, nano.KeyLedgerEd25519) + require.Nil(t, err, "%+v", err) + assert.Equal(t, c.Key, n) _, ok := c.PubKey.Unwrap().(nano.PubKeyLedgerEd25519) - require.True(ok) + require.True(t, ok) // make sure we can get it back info, err := cstore.Get(n) - require.Nil(err, "%+v", err) - assert.Equal(info.Name, n) + require.Nil(t, err, "%+v", err) + assert.Equal(t, info.Key, n) key := info.PubKey - require.False(key.Empty()) - require.True(key.Equals(c.PubKey)) + require.False(t ,key.Empty()) + require.True(t, key.Equals(c.PubKey)) // let's try to sign some messages d1 := []byte("welcome to cosmos") @@ -192,56 +187,64 @@ func TestSignWithLedger(t *testing.T) { // try signing both data with the ledger... s1, pub, err := cstore.Sign(n, p, d1) - require.Nil(err) - require.Equal(info.PubKey, pub) + require.Nil(t, err) + require.Equal(t, info.PubKey, pub) s2, pub, err := cstore.Sign(n, p, d2) - require.Nil(err) - require.Equal(info.PubKey, pub) + require.Nil(t, err) + require.Equal(t, info.PubKey, pub) // now, let's check those signatures work - assert.True(key.VerifyBytes(d1, s1)) - assert.True(key.VerifyBytes(d2, s2)) + assert.True(t, key.VerifyBytes(d1, s1)) + assert.True(t, key.VerifyBytes(d2, s2)) // and mismatched signatures don't - assert.False(key.VerifyBytes(d1, s2)) + assert.False(t, key.VerifyBytes(d1, s2)) } +*/ -func assertPassword(assert *asrt.Assertions, cstore keys.Keybase, name, pass, badpass string) { +func assertPassword(t *testing.T, cstore keys.Keybase, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) - assert.NotNil(err) + assert.NotNil(t, err) err = cstore.Update(name, pass, pass) - assert.Nil(err, "%+v", err) + assert.Nil(t, err, "%+v", err) } -// TestImportUnencrypted tests accepting raw priv keys bytes as input -func TestImportUnencrypted(t *testing.T) { - require := rqr.New(t) +// TestExportImport tests exporting and importing keys. +func TestExportImport(t *testing.T) { // make the storage with reasonable defaults + db := dbm.NewMemDB() cstore := keys.New( - dbm.NewMemDB(), + db, words.MustLoadCodec("english"), ) - key := crypto.GenPrivKeyEd25519FromSecret(cmn.RandBytes(16)).Wrap() + info, _, err := cstore.Create("john", "passphrase", keys.AlgoEd25519) + assert.Nil(t, err) + assert.Equal(t, info.Name, "john") + addr := info.PubKey.Address() + + john, err := cstore.Get("john") + assert.Nil(t, err) + assert.Equal(t, john.Name, "john") + assert.Equal(t, john.PubKey.Address(), addr) - addr := key.PubKey().Address() - name := "john" - pass := "top-secret" + armor, err := cstore.Export("john") + assert.Nil(t, err) - // import raw bytes - err := cstore.Import(name, pass, "", key.Bytes()) - require.Nil(err, "%+v", err) + err = cstore.Import("john2", armor) + assert.Nil(t, err) - // make sure the address matches - info, err := cstore.Get(name) - require.Nil(err, "%+v", err) - require.EqualValues(addr, info.Address()) + john2, err := cstore.Get("john2") + assert.Nil(t, err) + + assert.Equal(t, john.PubKey.Address(), addr) + assert.Equal(t, john.Name, "john") + assert.Equal(t, john, john2) } // TestAdvancedKeyManagement verifies update, import, export functionality func TestAdvancedKeyManagement(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -249,42 +252,49 @@ func TestAdvancedKeyManagement(t *testing.T) { words.MustLoadCodec("english"), ) - algo := crypto.NameSecp256k1 + algo := keys.AlgoSecp256k1 n1, n2 := "old-name", "new name" - p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$" + p1, p2 := "1234", "foobar" // make sure key works with initial password _, _, err := cstore.Create(n1, p1, algo) - require.Nil(err, "%+v", err) - assertPassword(assert, cstore, n1, p1, p2) + require.Nil(t, err, "%+v", err) + assertPassword(t, cstore, n1, p1, p2) // update password requires the existing password err = cstore.Update(n1, "jkkgkg", p2) - assert.NotNil(err) - assertPassword(assert, cstore, n1, p1, p2) + assert.NotNil(t, err) + assertPassword(t, cstore, n1, p1, p2) // then it changes the password when correct err = cstore.Update(n1, p1, p2) - assert.Nil(err) + assert.Nil(t, err) // p2 is now the proper one! - assertPassword(assert, cstore, n1, p2, p1) + assertPassword(t, cstore, n1, p2, p1) // exporting requires the proper name and passphrase - _, err = cstore.Export(n2, p2, pt) - assert.NotNil(err) - _, err = cstore.Export(n1, p1, pt) - assert.NotNil(err) - exported, err := cstore.Export(n1, p2, pt) - require.Nil(err, "%+v", err) - - // import fails on bad transfer pass - err = cstore.Import(n2, p3, p2, exported) - assert.NotNil(err) + _, err = cstore.Export(n1 + ".notreal") + assert.NotNil(t, err) + _, err = cstore.Export(" " + n1) + assert.NotNil(t, err) + _, err = cstore.Export(n1 + " ") + assert.NotNil(t, err) + _, err = cstore.Export("") + assert.NotNil(t, err) + exported, err := cstore.Export(n1) + require.Nil(t, err, "%+v", err) + + // import succeeds + err = cstore.Import(n2, exported) + assert.Nil(t, err) + + // second import fails + err = cstore.Import(n2, exported) + assert.NotNil(t, err) } // TestSeedPhrase verifies restoring from a seed phrase func TestSeedPhrase(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) // make the storage with reasonable defaults cstore := keys.New( @@ -292,28 +302,28 @@ func TestSeedPhrase(t *testing.T) { words.MustLoadCodec("english"), ) - algo := crypto.NameEd25519 + algo := keys.AlgoEd25519 n1, n2 := "lost-key", "found-again" p1, p2 := "1234", "foobar" // make sure key works with initial password - seed, info, err := cstore.Create(n1, p1, algo) - require.Nil(err, "%+v", err) - assert.Equal(n1, info.Name) - assert.NotEmpty(seed) + info, seed, err := cstore.Create(n1, p1, algo) + require.Nil(t, err, "%+v", err) + assert.Equal(t, n1, info.Name) + assert.NotEmpty(t, seed) // now, let us delete this key err = cstore.Delete(n1, p1) - require.Nil(err, "%+v", err) + require.Nil(t, err, "%+v", err) _, err = cstore.Get(n1) - require.NotNil(err) + require.NotNil(t, err) // let us re-create it from the seed-phrase - newInfo, err := cstore.Recover(n2, p2, algo, seed) - require.Nil(err, "%+v", err) - assert.Equal(n2, newInfo.Name) - assert.Equal(info.Address(), newInfo.Address()) - assert.Equal(info.PubKey, newInfo.PubKey) + newInfo, err := cstore.Recover(n2, p2, seed) + require.Nil(t, err, "%+v", err) + assert.Equal(t, n2, newInfo.Name) + assert.Equal(t, info.Address(), newInfo.Address()) + assert.Equal(t, info.PubKey, newInfo.PubKey) } func ExampleNew() { @@ -322,11 +332,11 @@ func ExampleNew() { dbm.NewMemDB(), words.MustLoadCodec("english"), ) - ed := crypto.NameEd25519 - sec := crypto.NameSecp256k1 + ed := keys.AlgoEd25519 + sec := keys.AlgoSecp256k1 // Add keys and see they return in alphabetical order - _, bob, err := cstore.Create("Bob", "friend", ed) + bob, _, err := cstore.Create("Bob", "friend", ed) if err != nil { // this should never happen fmt.Println(err) diff --git a/keys/keys.go b/keys/keys.go new file mode 100644 index 000000000..0ed89b3fd --- /dev/null +++ b/keys/keys.go @@ -0,0 +1,32 @@ +package keys + +import "fmt" + +type CryptoAlgo string + +const ( + AlgoEd25519 = CryptoAlgo("ed25519") + AlgoSecp256k1 = CryptoAlgo("secp256k1") +) + +func cryptoAlgoToByte(key CryptoAlgo) byte { + switch key { + case AlgoEd25519: + return 0x01 + case AlgoSecp256k1: + return 0x02 + default: + panic(fmt.Sprintf("Unexpected type key %v", key)) + } +} + +func byteToCryptoAlgo(b byte) CryptoAlgo { + switch b { + case 0x01: + return AlgoEd25519 + case 0x02: + return AlgoSecp256k1 + default: + panic(fmt.Sprintf("Unexpected type byte %X", b)) + } +} diff --git a/keys/mintkey.go b/keys/mintkey.go index d2724d658..73263b83a 100644 --- a/keys/mintkey.go +++ b/keys/mintkey.go @@ -12,8 +12,34 @@ import ( const ( blockTypePrivKey = "TENDERMINT PRIVATE KEY" + blockTypeKeyInfo = "TENDERMINT KEY INFO" ) +func armorInfoBytes(bz []byte) string { + header := map[string]string{ + "type": "Info", + "version": "0.0.0", + } + armorStr := crypto.EncodeArmor(blockTypeKeyInfo, header, bz) + return armorStr +} + +func unarmorInfoBytes(armorStr string) (bz []byte, err error) { + blockType, header, bz, err := crypto.DecodeArmor(armorStr) + if err != nil { + return + } + if blockType != blockTypeKeyInfo { + err = fmt.Errorf("Unrecognized armor type: %v", blockType) + return + } + if header["version"] != "0.0.0" { + err = fmt.Errorf("Unrecognized version: %v", header["version"]) + return + } + return +} + func encryptArmorPrivKey(privKey crypto.PrivKey, passphrase string) string { saltBytes, encBytes := encryptPrivKey(privKey, passphrase) header := map[string]string{ diff --git a/keys/types.go b/keys/types.go index fdb729e0a..cec9c36db 100644 --- a/keys/types.go +++ b/keys/types.go @@ -1,15 +1,40 @@ package keys import ( - wire "github.com/tendermint/go-wire" - crypto "github.com/tendermint/go-crypto" + wire "github.com/tendermint/go-wire" ) +// Keybase allows simple CRUD on a keystore, as an aid to signing +type Keybase interface { + // Sign some bytes + Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) + // Create a new keypair + Create(name, passphrase string, algo CryptoAlgo) (info Info, seed string, err error) + // Recover takes a seedphrase and loads in the key + Recover(name, passphrase, seedphrase string) (info Info, erro error) + List() ([]Info, error) + Get(name string) (Info, error) + Update(name, oldpass, newpass string) error + Delete(name, passphrase string) error + + Import(name string, armor string) (err error) + Export(name string) (armor string, err error) +} + // Info is the public information about a key type Info struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + PrivKeyArmor string `json:"privkey.armor"` +} + +func newInfo(name string, pub crypto.PubKey, privArmor string) Info { + return Info{ + Name: name, + PubKey: pub, + PrivKeyArmor: privArmor, + } } // Address is a helper function to calculate the address from the pubkey @@ -18,31 +43,14 @@ func (i Info) Address() []byte { } func (i Info) bytes() []byte { - return wire.BinaryBytes(i) -} - -func readInfo(bs []byte) (info Info, err error) { - err = wire.ReadBinaryBytes(bs, &info) - return -} - -func info(name string, privKey crypto.PrivKey) Info { - return Info{ - Name: name, - PubKey: privKey.PubKey(), + bz, err := wire.MarshalBinary(i) + if err != nil { + panic(err) } + return bz } -// Keybase allows simple CRUD on a keystore, as an aid to signing -type Keybase interface { - // Sign some bytes - Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) - // Create a new keypair - Create(name, passphrase, algo string) (seedphrase string, _ Info, _ error) - // Recover takes a seedphrase and loads in the key - Recover(name, passphrase, algo, seedphrase string) (Info, error) - List() ([]Info, error) - Get(name string) (Info, error) - Update(name, oldpass, newpass string) error - Delete(name, passphrase string) error +func readInfo(bz []byte) (info Info, err error) { + err = wire.UnmarshalBinary(bz, &info) + return } From 3a929316572d6ad9e976b8d00e57c81282aae932 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 2 Mar 2018 10:40:36 -0500 Subject: [PATCH 206/273] changelog, version, glide --- CHANGELOG.md | 18 ++++++++++++++++++ glide.lock | 24 ++++++++++++------------ glide.yaml | 4 ++-- version.go | 2 +- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af0539300..f9fb33eb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## 0.5.0 (March 2, 2017) + +BREAKING CHANGES + +- nano: moved to `_nano` now while we're having build issues +- bcrypt: moved to `keys/bcrypt` +- hd: moved to `keys/hd`; `BTC` added to some function names; other function cleanup +- keys/cryptostore: moved to `keys`, renamed to `keybase`, and completely refactored +- keys: moved BIP39 related code to `keys/words` + +FEATURE + +- `Address` is a type alias for `cmn.HexBytes` + +BUG FIX + +- PrivKey comparisons done in constant time + ## 0.4.1 (October 27, 2017) This release removes support for bcrypt as it was merged too soon without an upgrade plan diff --git a/glide.lock b/glide.lock index add082c5b..48430920f 100644 --- a/glide.lock +++ b/glide.lock @@ -1,16 +1,16 @@ -hash: 575a7b42282ded36e66490c44105140387d305b07e8e5a9e8e4b9eeb6f995e66 -updated: 2018-03-02T03:06:22.122862726-05:00 +hash: 2b121bf7364ed02c60faff6d619a22acb0489d59843be669be3f8823b8658b75 +updated: 2018-03-02T10:39:45.076725737-05:00 imports: - name: github.com/btcsuite/btcd - version: 50de9da05b50eb15658bb350f6ea24368a111ab7 + version: 2be2f12b358dc57d70b8f501b00be450192efbc3 subpackages: - btcec - name: github.com/btcsuite/btcutil - version: 66871daeb12123ece012a9628d2798d01195c4b3 + version: 501929d3d046174c3d39f0ea54ece471aa17238c subpackages: - base58 - name: github.com/ethanfrey/ledger - version: 23a7bb9d74bc83a862fcb4bddde24215b2295ad9 + version: f7f2f056357db77db845a79aa1abdadc3ae66369 - name: github.com/go-kit/kit version: 4dc7be5d2d12881735283bcab7352178e190fc71 subpackages: @@ -30,15 +30,15 @@ imports: - name: github.com/golang/snappy version: 553a641470496b2327abcac10b36396bd98e45c9 - name: github.com/howeyc/crc16 - version: 96a97a1abb579c7ff1a8ffa77f2e72d1c314b57f + version: 2b2a61e366a66d3efb279e46176e7291001e0354 - name: github.com/jmhodges/levigo version: c42d9e0ca023e2198120196f842701bb4c55d7b9 - name: github.com/kr/logfmt version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 - name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d + version: 30136e27e2ac8d167177e8a583aa4c3fea5be833 - name: github.com/syndtr/goleveldb - version: 34011bf325bce385408353a30b101fe5e923eb6e + version: c7a14d4b00e222eab6111b4cd1af829c13f53ec2 subpackages: - leveldb - leveldb/cache @@ -58,7 +58,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 67ee274c5f9da166622f3b6e6747003b563e3742 + version: fa721242b042ecd4c6ed1a934ee740db4f74e45c subpackages: - data - data/base58 @@ -69,7 +69,7 @@ imports: - db - log - name: golang.org/x/crypto - version: 1875d0a70c90e57f11972aefd42276df65e895b9 + version: 91a49db82a88618983a78a06c1cbd4e00ab749ab subpackages: - bcrypt - blowfish @@ -82,7 +82,7 @@ imports: - salsa20/salsa testImports: - name: github.com/davecgh/go-spew - version: 346938d642f2ec3594ed81d874461961cd0faa76 + version: 8991bc29aa16c548c550c7ff78260e27b9ab7c73 subpackages: - spew - name: github.com/mndrix/btcutil @@ -97,6 +97,6 @@ testImports: - assert - require - name: github.com/tyler-smith/go-bip32 - version: eb790af526c30f23a7c8b00a48e342f9d0bd6386 + version: 2c9cfd17756470a0b7c3e4b7954bae7d11035504 - name: github.com/tyler-smith/go-bip39 version: 8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc diff --git a/glide.yaml b/glide.yaml index c5ac4992b..9b1f23a51 100644 --- a/glide.yaml +++ b/glide.yaml @@ -17,9 +17,9 @@ import: subpackages: - extra25519 - package: github.com/tendermint/tmlibs - version: master + version: v0.7.0 - package: github.com/tendermint/go-wire - version: bucky/new-go-wire-api + version: v0.7.3 subpackages: - data - data/base58 diff --git a/version.go b/version.go index c39dd627c..0281a5ea2 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.4.1" +const Version = "0.5.0" From 5e073562648998d31286e27c109b0e0c991e46b0 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 2 Mar 2018 11:43:58 -0500 Subject: [PATCH 207/273] use previously working new go-wire. not bleeding edge --- glide.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glide.lock b/glide.lock index 0a99eb1e3..b97d8bc07 100644 --- a/glide.lock +++ b/glide.lock @@ -60,7 +60,7 @@ imports: - edwards25519 - extra25519 - name: github.com/tendermint/go-wire - version: 3d2fb07b5c65de21d624919c4680b1cd1b2cfe90 + version: dec83f641903b22f039da3974607859715d0377e - name: github.com/tendermint/tmlibs version: 26f2ab65f82cfc6873c312e8030104c47c05f10e subpackages: From f499ce871362f456e127da24fd3dc244dc863f00 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 12 Mar 2018 12:18:30 +0400 Subject: [PATCH 208/273] update go-amino --- Gopkg.lock | 6 +++--- Gopkg.toml | 2 +- README.md | 2 +- _nano/keys.go | 8 ++++---- wire.go => amino.go | 22 +++++++++++----------- encode_test.go | 16 ++++++++-------- glide.lock | 2 +- glide.yaml | 2 +- keys/wire.go | 8 ++++---- signature_test.go | 19 ++++++++++--------- 10 files changed, 44 insertions(+), 43 deletions(-) rename wire.go => amino.go (56%) diff --git a/Gopkg.lock b/Gopkg.lock index 6dd1154b1..b945d9199 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -125,9 +125,9 @@ [[projects]] branch = "develop" - name = "github.com/tendermint/go-wire" + name = "github.com/tendermint/go-amino" packages = ["."] - revision = "dec83f641903b22f039da3974607859715d0377e" + revision = "3b9e2b978447707c255922bc3f87a53d55c400c9" [[projects]] branch = "develop" @@ -163,6 +163,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "e0628df240b8ceeb91403f5218f5561d8580f15f3d5b0ea0da40710d1cba3707" + inputs-digest = "375b661ad202b62c6847981416c03ce0518c33ac293f5f0863b69af04d2af91f" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 058eb5838..84a26764e 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -47,7 +47,7 @@ [[constraint]] branch = "develop" - name = "github.com/tendermint/go-wire" + name = "github.com/tendermint/go-amino" [[constraint]] branch = "develop" diff --git a/README.md b/README.md index da76fe823..3c33532fc 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,4 @@ go-crypto is the cryptographic package adapted for Tendermint's uses ## Importing it -`import "github.com/tendermint/go-crypto"` \ No newline at end of file +`import "github.com/tendermint/go-crypto"` diff --git a/_nano/keys.go b/_nano/keys.go index b50efd7ec..8cf1c3721 100644 --- a/_nano/keys.go +++ b/_nano/keys.go @@ -9,7 +9,7 @@ import ( ledger "github.com/ethanfrey/ledger" crypto "github.com/tendermint/go-crypto" - wire "github.com/tendermint/go-wire" + amino "github.com/tendermint/go-amino" ) //nolint @@ -58,7 +58,7 @@ func signLedger(device *ledger.Ledger, msg []byte) (pub crypto.PubKey, sig crypt // PrivKeyLedgerEd25519 implements PrivKey, calling the ledger nano // we cache the PubKey from the first call to use it later type PrivKeyLedgerEd25519 struct { - // PubKey should be private, but we want to encode it via go-wire + // PubKey should be private, but we want to encode it via go-amino // so we can view the address later, even without having the ledger // attached CachedPubKey crypto.PubKey @@ -97,7 +97,7 @@ func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} // Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify // the same key when we reconnect to a ledger func (pk *PrivKeyLedgerEd25519) Bytes() []byte { - return wire.BinaryBytes(pk.Wrap()) + return amino.BinaryBytes(pk.Wrap()) } // Sign calls the ledger and stores the PubKey for future use @@ -250,7 +250,7 @@ func PubKeyLedgerEd25519FromBytes(key [32]byte) crypto.PubKey { // Bytes fulfils pk Interface - no data, just type info func (pk PubKeyLedgerEd25519) Bytes() []byte { - return wire.BinaryBytes(pk.Wrap()) + return amino.BinaryBytes(pk.Wrap()) } // VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand diff --git a/wire.go b/amino.go similarity index 56% rename from wire.go rename to amino.go index 18035964f..f9d7b9580 100644 --- a/wire.go +++ b/amino.go @@ -1,36 +1,36 @@ package crypto import ( - "github.com/tendermint/go-wire" + amino "github.com/tendermint/go-amino" ) -var cdc = wire.NewCodec() +var cdc = amino.NewCodec() func init() { // NOTE: It's important that there be no conflicts here, // as that would change the canonical representations, // and therefore change the address. - // TODO: Add feature to go-wire to ensure that there + // TODO: Add feature to go-amino to ensure that there // are no conflicts. - RegisterWire(cdc) + RegisterAmino(cdc) } -func RegisterWire(cdc *wire.Codec) { +func RegisterAmino(cdc *amino.Codec) { cdc.RegisterInterface((*PubKey)(nil), nil) cdc.RegisterConcrete(PubKeyEd25519{}, - "com.tendermint.wire.PubKeyEd25519", nil) + "com.tendermint.amino.PubKeyEd25519", nil) cdc.RegisterConcrete(PubKeySecp256k1{}, - "com.tendermint.wire.PubKeySecp256k1", nil) + "com.tendermint.amino.PubKeySecp256k1", nil) cdc.RegisterInterface((*PrivKey)(nil), nil) cdc.RegisterConcrete(PrivKeyEd25519{}, - "com.tendermint.wire.PrivKeyEd25519", nil) + "com.tendermint.amino.PrivKeyEd25519", nil) cdc.RegisterConcrete(PrivKeySecp256k1{}, - "com.tendermint.wire.PrivKeySecp256k1", nil) + "com.tendermint.amino.PrivKeySecp256k1", nil) cdc.RegisterInterface((*Signature)(nil), nil) cdc.RegisterConcrete(SignatureEd25519{}, - "com.tendermint.wire.SignatureKeyEd25519", nil) + "com.tendermint.amino.SignatureKeyEd25519", nil) cdc.RegisterConcrete(SignatureSecp256k1{}, - "com.tendermint.wire.SignatureKeySecp256k1", nil) + "com.tendermint.amino.SignatureKeySecp256k1", nil) } diff --git a/encode_test.go b/encode_test.go index bcd9e60c2..bc3f1a736 100644 --- a/encode_test.go +++ b/encode_test.go @@ -1,7 +1,7 @@ package crypto /* -XXX Needs to be refactored to not use go-wire/data +XXX Needs to be refactored to not use go-amino/data import ( "fmt" @@ -10,15 +10,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - wire "github.com/tendermint/go-wire" - data "github.com/tendermint/go-wire/data" + amino "github.com/tendermint/go-amino" + data "github.com/tendermint/go-amino/data" ) type byter interface { Bytes() []byte } -// go to wire encoding and back +// go to amino encoding and back func checkWire(t *testing.T, in byter, reader interface{}, typ byte, size int) { // test to and from binary bin, err := data.ToWire(in) @@ -55,15 +55,15 @@ func checkJSON(t *testing.T, in interface{}, reader interface{}, typ string) { assert.True(t, strings.Contains(string(js), parts[1])) } -// make sure go-wire json can still figure this out... +// make sure go-amino json can still figure this out... func checkWireJSON(t *testing.T, in interface{}, reader interface{}, typ byte) { // test to and from binary var err error - js := wire.JSONBytes(in) + js := amino.JSONBytes(in) btyp := fmt.Sprintf("[%d,", typ) assert.True(t, strings.HasPrefix(string(js), btyp), string(js), btyp) - wire.ReadJSON(reader, js, &err) + amino.ReadJSON(reader, js, &err) require.Nil(t, err, "%+v", err) } @@ -144,7 +144,7 @@ type SigMessage struct { } func (s SigMessage) Bytes() []byte { - return wire.BinaryBytes(s) + return amino.BinaryBytes(s) } func TestEmbededWireEncodings(t *testing.T) { diff --git a/glide.lock b/glide.lock index b97d8bc07..ff6e97630 100644 --- a/glide.lock +++ b/glide.lock @@ -59,7 +59,7 @@ imports: subpackages: - edwards25519 - extra25519 -- name: github.com/tendermint/go-wire +- name: github.com/tendermint/go-amino version: dec83f641903b22f039da3974607859715d0377e - name: github.com/tendermint/tmlibs version: 26f2ab65f82cfc6873c312e8030104c47c05f10e diff --git a/glide.yaml b/glide.yaml index d99809211..8e8b55b50 100644 --- a/glide.yaml +++ b/glide.yaml @@ -12,7 +12,7 @@ import: - package: github.com/tendermint/ed25519 subpackages: - extra25519 -- package: github.com/tendermint/go-wire +- package: github.com/tendermint/go-amino version: develop - package: github.com/tendermint/tmlibs version: develop diff --git a/keys/wire.go b/keys/wire.go index 65d69ba5e..7deaad673 100644 --- a/keys/wire.go +++ b/keys/wire.go @@ -1,12 +1,12 @@ package keys import ( - "github.com/tendermint/go-crypto" - "github.com/tendermint/go-wire" + amino "github.com/tendermint/go-amino" + crypto "github.com/tendermint/go-crypto" ) -var cdc = wire.NewCodec() +var cdc = amino.NewCodec() func init() { - crypto.RegisterWire(cdc) + crypto.RegisterAmino(cdc) } diff --git a/signature_test.go b/signature_test.go index 7bc94e677..b698e5167 100644 --- a/signature_test.go +++ b/signature_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/ed25519" - "github.com/tendermint/go-wire" + amino "github.com/tendermint/go-amino" ) func TestSignAndValidateEd25519(t *testing.T) { @@ -49,17 +49,17 @@ func TestSignatureEncodings(t *testing.T) { cases := []struct { privKey PrivKey sigSize int - sigPrefix wire.PrefixBytes + sigPrefix amino.PrefixBytes }{ { privKey: GenPrivKeyEd25519(), sigSize: ed25519.SignatureSize, - sigPrefix: [4]byte{0xe4, 0x51, 0x7b, 0xa3}, + sigPrefix: [4]byte{0xc8, 0x5d, 0xf4, 0xba}, }, { privKey: GenPrivKeySecp256k1(), sigSize: 0, // unknown - sigPrefix: [4]byte{0x37, 0xb9, 0x21, 0x3e}, + sigPrefix: [4]byte{0xc6, 0xa0, 0xa, 0x42}, }, } @@ -70,17 +70,18 @@ func TestSignatureEncodings(t *testing.T) { msg := CRandBytes(128) sig := tc.privKey.Sign(msg) - // store as wire - bin, err := cdc.MarshalBinary(sig) + // store as amino + bin, err := cdc.MarshalBinaryBare(sig) require.Nil(t, err, "%+v", err) if tc.sigSize != 0 { - assert.Equal(t, tc.sigSize+4, len(bin)) + // Q: where is 1 byte coming from? + assert.Equal(t, tc.sigSize+amino.PrefixBytesLen+1, len(bin)) } - assert.Equal(t, tc.sigPrefix[:], bin[0:4]) + assert.Equal(t, tc.sigPrefix[:], bin[0:amino.PrefixBytesLen]) // and back sig2 := Signature(nil) - err = cdc.UnmarshalBinary(bin, &sig2) + err = cdc.UnmarshalBinaryBare(bin, &sig2) require.Nil(t, err, "%+v", err) assert.EqualValues(t, sig, sig2) assert.True(t, pubKey.VerifyBytes(msg, sig2)) From 47b8a8864b7e7b63b2d34902cee6e7b5a99466d2 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 12 Mar 2018 12:34:43 +0400 Subject: [PATCH 209/273] remove any mention of glide --- Makefile | 6 ++-- glide.lock | 93 ------------------------------------------------------ glide.yaml | 34 -------------------- 3 files changed, 3 insertions(+), 130 deletions(-) delete mode 100644 glide.lock delete mode 100644 glide.yaml diff --git a/Makefile b/Makefile index b8c95b7df..9ae475983 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ GOTOOLS = \ github.com/golang/dep/cmd/dep \ - github.com/jteeuwen/go-bindata/go-bindata + github.com/jteeuwen/go-bindata/go-bindata # gopkg.in/alecthomas/gometalinter.v2 \ # -GOTOOLS_CHECK = glide go-bindata #gometalinter.v2 +GOTOOLS_CHECK = dep go-bindata #gometalinter.v2 -all: check get_vendor_deps build test install +all: check get_vendor_deps build test install check: check_tools diff --git a/glide.lock b/glide.lock deleted file mode 100644 index ff6e97630..000000000 --- a/glide.lock +++ /dev/null @@ -1,93 +0,0 @@ -hash: 95b2c2a089ca7242bc52c3bfe5a0286ae68201197f7f5855dd6e8f2ee3974068 -updated: 2018-03-02T11:41:11.205350024-05:00 -imports: -- name: github.com/btcsuite/btcd - version: 2be2f12b358dc57d70b8f501b00be450192efbc3 - subpackages: - - btcec -- name: github.com/btcsuite/btcutil - version: 501929d3d046174c3d39f0ea54ece471aa17238c - subpackages: - - base58 -- name: github.com/davecgh/go-spew - version: 346938d642f2ec3594ed81d874461961cd0faa76 - subpackages: - - spew -- name: github.com/go-kit/kit - version: 4dc7be5d2d12881735283bcab7352178e190fc71 - subpackages: - - log - - log/level - - log/term -- name: github.com/go-logfmt/logfmt - version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 -- name: github.com/go-stack/stack - version: 259ab82a6cad3992b4e21ff5cac294ccb06474bc -- name: github.com/gogo/protobuf - version: 1adfc126b41513cc696b209667c8656ea7aac67c - subpackages: - - gogoproto - - proto - - protoc-gen-gogo/descriptor -- name: github.com/golang/snappy - version: 553a641470496b2327abcac10b36396bd98e45c9 -- name: github.com/howeyc/crc16 - version: 2b2a61e366a66d3efb279e46176e7291001e0354 -- name: github.com/jmhodges/levigo - version: c42d9e0ca023e2198120196f842701bb4c55d7b9 -- name: github.com/kr/logfmt - version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 -- name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/syndtr/goleveldb - version: c7a14d4b00e222eab6111b4cd1af829c13f53ec2 - subpackages: - - leveldb - - leveldb/cache - - leveldb/comparer - - leveldb/errors - - leveldb/filter - - leveldb/iterator - - leveldb/journal - - leveldb/memdb - - leveldb/opt - - leveldb/storage - - leveldb/table - - leveldb/util -- name: github.com/tendermint/ed25519 - version: d8387025d2b9d158cf4efb07e7ebf814bcce2057 - subpackages: - - edwards25519 - - extra25519 -- name: github.com/tendermint/go-amino - version: dec83f641903b22f039da3974607859715d0377e -- name: github.com/tendermint/tmlibs - version: 26f2ab65f82cfc6873c312e8030104c47c05f10e - subpackages: - - common - - db - - log -- name: golang.org/x/crypto - version: 91a49db82a88618983a78a06c1cbd4e00ab749ab - subpackages: - - bcrypt - - blowfish - - nacl/secretbox - - openpgp/armor - - openpgp/errors - - pbkdf2 - - poly1305 - - ripemd160 - - salsa20/salsa -testImports: -- name: github.com/pmezard/go-difflib - version: 792786c7400a136282c1664665ae0a8db921c6c2 - subpackages: - - difflib -- name: github.com/stretchr/testify - version: 12b6f73e6084dad08a7c6e575284b177ecafbc71 - subpackages: - - assert - - require -- name: github.com/tyler-smith/go-bip39 - version: 8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc diff --git a/glide.yaml b/glide.yaml deleted file mode 100644 index 8e8b55b50..000000000 --- a/glide.yaml +++ /dev/null @@ -1,34 +0,0 @@ -package: github.com/tendermint/go-crypto -import: -- package: github.com/btcsuite/btcd - subpackages: - - btcec -- package: github.com/btcsuite/btcutil - subpackages: - - base58 -- package: github.com/howeyc/crc16 -- package: github.com/pkg/errors - version: ^0.8.0 -- package: github.com/tendermint/ed25519 - subpackages: - - extra25519 -- package: github.com/tendermint/go-amino - version: develop -- package: github.com/tendermint/tmlibs - version: develop - subpackages: - - common - - db -- package: golang.org/x/crypto - subpackages: - - blowfish - - nacl/secretbox - - openpgp/armor - - ripemd160 -testImport: -- package: github.com/stretchr/testify - version: ^1.2.1 - subpackages: - - assert - - require -- package: github.com/tyler-smith/go-bip39 From 73407e7cff462bf4ffcc44d55a9dd4570dd57fed Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Mon, 12 Mar 2018 12:37:19 +0400 Subject: [PATCH 210/273] add CODEOWNERS file --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..3876c1ac5 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# CODEOWNERS: https://help.github.com/articles/about-codeowners/ + +* @ebuchman @jaekwon From a3800da0a15c8272cbd3c155e024bff28fe9692c Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Fri, 16 Mar 2018 07:01:02 -0700 Subject: [PATCH 211/273] Update Gopkg.lock to use go-amino --- Gopkg.lock | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index b945d9199..6369f55bd 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,9 +2,10 @@ [[projects]] + branch = "master" name = "github.com/btcsuite/btcd" packages = ["btcec"] - revision = "2e60448ffcc6bf78332d1fe590260095f554dd78" + revision = "2be2f12b358dc57d70b8f501b00be450192efbc3" [[projects]] branch = "master" @@ -37,8 +38,8 @@ [[projects]] name = "github.com/go-stack/stack" packages = ["."] - revision = "817915b46b97fd7bb80e8ab6b69f01a53ac3eebf" - version = "v1.6.0" + revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" + version = "v1.7.0" [[projects]] name = "github.com/gogo/protobuf" @@ -96,6 +97,7 @@ version = "v1.2.1" [[projects]] + branch = "master" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -111,7 +113,7 @@ "leveldb/table", "leveldb/util" ] - revision = "b89cc31ef7977104127d34c1bd31ebd1a9db2199" + revision = "169b1b37be738edb2813dab48c97a549bcf99bb5" [[projects]] branch = "master" @@ -137,7 +139,7 @@ "db", "log" ] - revision = "1d7fc78ea171587e9e63da566d3da1b127bfd14c" + revision = "d289c9286e816a37336289a75752752a751bc918" [[projects]] branch = "master" @@ -146,6 +148,7 @@ revision = "8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc" [[projects]] + branch = "master" name = "golang.org/x/crypto" packages = [ "bcrypt", @@ -158,7 +161,7 @@ "ripemd160", "salsa20/salsa" ] - revision = "edd5e9b0879d13ee6970a50153d85b8fec9f7686" + revision = "b4956d363a8b14623cc81db401707679605930a3" [solve-meta] analyzer-name = "dep" From f01046263907258b8d7fc4f91ee0b6138d2c1baf Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 18 Mar 2018 23:45:46 +0100 Subject: [PATCH 212/273] Make concrete registered name be tendermint/* --- amino.go | 12 ++++++------ signature_test.go | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/amino.go b/amino.go index f9d7b9580..89636895a 100644 --- a/amino.go +++ b/amino.go @@ -18,19 +18,19 @@ func init() { func RegisterAmino(cdc *amino.Codec) { cdc.RegisterInterface((*PubKey)(nil), nil) cdc.RegisterConcrete(PubKeyEd25519{}, - "com.tendermint.amino.PubKeyEd25519", nil) + "tendermint/PubKeyEd25519", nil) cdc.RegisterConcrete(PubKeySecp256k1{}, - "com.tendermint.amino.PubKeySecp256k1", nil) + "tendermint/PubKeySecp256k1", nil) cdc.RegisterInterface((*PrivKey)(nil), nil) cdc.RegisterConcrete(PrivKeyEd25519{}, - "com.tendermint.amino.PrivKeyEd25519", nil) + "tendermint/PrivKeyEd25519", nil) cdc.RegisterConcrete(PrivKeySecp256k1{}, - "com.tendermint.amino.PrivKeySecp256k1", nil) + "tendermint/PrivKeySecp256k1", nil) cdc.RegisterInterface((*Signature)(nil), nil) cdc.RegisterConcrete(SignatureEd25519{}, - "com.tendermint.amino.SignatureKeyEd25519", nil) + "tendermint/SignatureKeyEd25519", nil) cdc.RegisterConcrete(SignatureSecp256k1{}, - "com.tendermint.amino.SignatureKeySecp256k1", nil) + "tendermint/SignatureKeySecp256k1", nil) } diff --git a/signature_test.go b/signature_test.go index b698e5167..0ba44ded5 100644 --- a/signature_test.go +++ b/signature_test.go @@ -54,12 +54,12 @@ func TestSignatureEncodings(t *testing.T) { { privKey: GenPrivKeyEd25519(), sigSize: ed25519.SignatureSize, - sigPrefix: [4]byte{0xc8, 0x5d, 0xf4, 0xba}, + sigPrefix: [4]byte{0x3d, 0xa1, 0xdb, 0x2a}, }, { privKey: GenPrivKeySecp256k1(), sigSize: 0, // unknown - sigPrefix: [4]byte{0xc6, 0xa0, 0xa, 0x42}, + sigPrefix: [4]byte{0x16, 0xe1, 0xfe, 0xea}, }, } From a04f2ae5c6ba037014531241ed973116290b029e Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Sun, 25 Mar 2018 07:14:11 +0200 Subject: [PATCH 213/273] tmlibs 0.8.0-dev; canonical concrete names --- CHANGELOG.md | 6 ++++++ Gopkg.lock | 10 +++++----- Gopkg.toml | 12 ++++++------ version.go | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9fb33eb8..1f58e18ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.6.0 (March 2, 2017) + +BREAKING CHANGES + +- Update Amino names from "com.tendermint/..." to "tendermint/" + ## 0.5.0 (March 2, 2017) BREAKING CHANGES diff --git a/Gopkg.lock b/Gopkg.lock index 6369f55bd..03473487d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -126,20 +126,20 @@ revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" [[projects]] - branch = "develop" name = "github.com/tendermint/go-amino" packages = ["."] - revision = "3b9e2b978447707c255922bc3f87a53d55c400c9" + revision = "8b10adccaa7e4c2edc29c7b762169c34f4a36b32" + version = "0.9.1" [[projects]] - branch = "develop" name = "github.com/tendermint/tmlibs" packages = [ "common", "db", "log" ] - revision = "d289c9286e816a37336289a75752752a751bc918" + revision = "e9cf47606cfcbdc28a7c16671b4a70b459e9d4cc" + version = "v0.8.0-dev" [[projects]] branch = "master" @@ -166,6 +166,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "375b661ad202b62c6847981416c03ce0518c33ac293f5f0863b69af04d2af91f" + inputs-digest = "ff08a2810853f018b3ce056747de63fe4c1782268796f457d3fa28305de2bd1d" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 84a26764e..908e48f5f 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -26,12 +26,12 @@ [[constraint]] - branch = "master" name = "github.com/btcsuite/btcutil" + branch = "master" [[constraint]] - branch = "master" name = "github.com/howeyc/crc16" + branch = "master" [[constraint]] name = "github.com/pkg/errors" @@ -42,20 +42,20 @@ version = "1.2.1" [[constraint]] - branch = "master" name = "github.com/tendermint/ed25519" + branch = "master" [[constraint]] - branch = "develop" name = "github.com/tendermint/go-amino" + version = "0.9.1" [[constraint]] - branch = "develop" name = "github.com/tendermint/tmlibs" + version = "0.8.0-dev" [[constraint]] - branch = "master" name = "github.com/tyler-smith/go-bip39" + branch = "master" [prune] go-tests = true diff --git a/version.go b/version.go index 0281a5ea2..f641e03a3 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.5.0" +const Version = "0.6.0" From 0d4436dea7592f48bdbaefc4af90756cf58ddacd Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 26 Mar 2018 10:41:04 +0200 Subject: [PATCH 214/273] Use MarshalBinaryBare; Fix encode_test; Bump version --- Gopkg.lock | 6 +- Gopkg.toml | 2 +- encode_test.go | 172 ++++++++++++------------------------------------- keys/types.go | 4 +- priv_key.go | 8 +-- pub_key.go | 6 +- signature.go | 6 +- version.go | 2 +- 8 files changed, 58 insertions(+), 148 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 03473487d..bfe089b72 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -128,8 +128,8 @@ [[projects]] name = "github.com/tendermint/go-amino" packages = ["."] - revision = "8b10adccaa7e4c2edc29c7b762169c34f4a36b32" - version = "0.9.1" + revision = "f55c3351f30e5987500020631f00e87a035ed415" + version = "0.9.3" [[projects]] name = "github.com/tendermint/tmlibs" @@ -166,6 +166,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "ff08a2810853f018b3ce056747de63fe4c1782268796f457d3fa28305de2bd1d" + inputs-digest = "9748e96106582387ac49df1db8e4456bd51c8e9362c86992d6ce7011c1783f55" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 908e48f5f..a7f84bb59 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -47,7 +47,7 @@ [[constraint]] name = "github.com/tendermint/go-amino" - version = "0.9.1" + version = "0.9.3" [[constraint]] name = "github.com/tendermint/tmlibs" diff --git a/encode_test.go b/encode_test.go index bc3f1a736..d9332238e 100644 --- a/encode_test.go +++ b/encode_test.go @@ -1,185 +1,95 @@ package crypto -/* -XXX Needs to be refactored to not use go-amino/data - import ( - "fmt" - "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - amino "github.com/tendermint/go-amino" - data "github.com/tendermint/go-amino/data" ) type byter interface { Bytes() []byte } -// go to amino encoding and back -func checkWire(t *testing.T, in byter, reader interface{}, typ byte, size int) { - // test to and from binary - bin, err := data.ToWire(in) +func checkAminoBinary(t *testing.T, src byter, dst interface{}, size int) { + // Marshal to binary bytes. + bz, err := cdc.MarshalBinaryBare(src) require.Nil(t, err, "%+v", err) - assert.Equal(t, typ, bin[0]) - // make sure this is compatible with current (Bytes()) encoding - assert.Equal(t, in.Bytes(), bin) - // make sure we have the expected length - assert.Equal(t, size, len(bin)) - - err = data.FromWire(bin, reader) + // Make sure this is compatible with current (Bytes()) encoding. + assert.Equal(t, src.Bytes(), bz, "Amino binary vs Bytes() mismatch") + // Make sure we have the expected length. + assert.Equal(t, size, len(bz), "Amino binary size mismatch") + // Unmarshal. + err = cdc.UnmarshalBinaryBare(bz, dst) require.Nil(t, err, "%+v", err) } -// go to json encoding and back -func checkJSON(t *testing.T, in interface{}, reader interface{}, typ string) { - // test to and from binary - js, err := data.ToJSON(in) - require.Nil(t, err, "%+v", err) - styp := `"` + typ + `"` - assert.True(t, strings.Contains(string(js), styp)) - - err = data.FromJSON(js, reader) +func checkAminoJSON(t *testing.T, src interface{}, dst interface{}, isNil bool) { + // Marshal to JSON bytes. + js, err := cdc.MarshalJSON(src) require.Nil(t, err, "%+v", err) - - // also check text format - text, err := data.ToText(in) - require.Nil(t, err, "%+v", err) - parts := strings.Split(text, ":") - require.Equal(t, 2, len(parts)) - // make sure the first part is the typ string - assert.Equal(t, typ, parts[0]) - // and the data is also present in the json - assert.True(t, strings.Contains(string(js), parts[1])) -} - -// make sure go-amino json can still figure this out... -func checkWireJSON(t *testing.T, in interface{}, reader interface{}, typ byte) { - // test to and from binary - var err error - js := amino.JSONBytes(in) - btyp := fmt.Sprintf("[%d,", typ) - assert.True(t, strings.HasPrefix(string(js), btyp), string(js), btyp) - - amino.ReadJSON(reader, js, &err) + if isNil { + assert.Equal(t, string(js), `null`) + } else { + assert.Contains(t, string(js), `"type":`) + assert.Contains(t, string(js), `"value":`) + } + // Unmarshal. + err = cdc.UnmarshalJSON(js, dst) require.Nil(t, err, "%+v", err) } func TestKeyEncodings(t *testing.T) { cases := []struct { privKey PrivKey - keyType byte - keyName string // 1 (type byte) + size of byte array privSize, pubSize int }{ { - privKey: GenPrivKeyEd25519().Wrap(), - keyType: TypeEd25519, - keyName: NameEd25519, - privSize: 65, - pubSize: 33, + privKey: GenPrivKeyEd25519(), + privSize: 69, + pubSize: 37, }, { - privKey: GenPrivKeySecp256k1().Wrap(), - keyType: TypeSecp256k1, - keyName: NameSecp256k1, - privSize: 33, - pubSize: 34, + privKey: GenPrivKeySecp256k1(), + privSize: 37, + pubSize: 38, }, } for _, tc := range cases { - // check (de/en)codings of private key - var priv2, priv3, priv4 PrivKey - checkWire(t, tc.privKey, &priv2, tc.keyType, tc.privSize) + // Check (de/en)codings of PrivKeys. + var priv2, priv3 PrivKey + checkAminoBinary(t, tc.privKey, &priv2, tc.privSize) assert.EqualValues(t, tc.privKey, priv2) - checkJSON(t, tc.privKey, &priv3, tc.keyName) + checkAminoJSON(t, tc.privKey, &priv3, false) // TODO also check Prefix bytes. assert.EqualValues(t, tc.privKey, priv3) - checkWireJSON(t, tc.privKey, &priv4, tc.keyType) - assert.EqualValues(t, tc.privKey, priv4) - // check (de/en)codings of public key + // Check (de/en)codings of PubKeys. pubKey := tc.privKey.PubKey() - var pub2, pub3, pub4 PubKey - checkWire(t, pubKey, &pub2, tc.keyType, tc.pubSize) + var pub2, pub3 PubKey + checkAminoBinary(t, pubKey, &pub2, tc.pubSize) assert.EqualValues(t, pubKey, pub2) - checkJSON(t, pubKey, &pub3, tc.keyName) + checkAminoJSON(t, pubKey, &pub3, false) // TODO also check Prefix bytes. assert.EqualValues(t, pubKey, pub3) - checkWireJSON(t, pubKey, &pub4, tc.keyType) - assert.EqualValues(t, pubKey, pub4) } } -func toFromJSON(t *testing.T, in interface{}, recvr interface{}) { - js, err := data.ToJSON(in) - require.Nil(t, err, "%+v", err) - err = data.FromJSON(js, recvr) - require.Nil(t, err, "%+v", err) -} - func TestNilEncodings(t *testing.T) { - // make sure sigs are okay with nil + + // Check nil Signature. var a, b Signature - toFromJSON(t, a, &b) + checkAminoJSON(t, &a, &b, true) assert.EqualValues(t, a, b) - // make sure sigs are okay with nil + // Check nil PubKey. var c, d PubKey - toFromJSON(t, c, &d) + checkAminoJSON(t, &c, &d, true) assert.EqualValues(t, c, d) - // make sure sigs are okay with nil + // Check nil PrivKey. var e, f PrivKey - toFromJSON(t, e, &f) + checkAminoJSON(t, &e, &f, true) assert.EqualValues(t, e, f) } - -type SigMessage struct { - Key PubKey - Sig Signature -} - -func (s SigMessage) Bytes() []byte { - return amino.BinaryBytes(s) -} - -func TestEmbededWireEncodings(t *testing.T) { - cases := []struct { - privKey PrivKey - keyType byte - keyName string - size int // pub + sig size - }{ - { - privKey: GenPrivKeyEd25519().Wrap(), - keyType: TypeEd25519, - keyName: NameEd25519, - size: 2 + 32 + 64, - }, - // { - // privKey: GenPrivKeySecp256k1().Wrap(), - // keyType: TypeSecp256k1, - // keyName: NameSecp256k1, - // size: 2 + 33 + 72, // ugh, either 72 or 73 depending.... - // }, - } - - payload := randBytes(20) - for i, tc := range cases { - pubKey := tc.privKey.PubKey() - sig := tc.privKey.Sign(payload) - assert.True(t, pubKey.VerifyBytes(payload, sig), "%d", i) - - msg := SigMessage{ - Key: pubKey, - Sig: sig, - } - var msg2 SigMessage - checkWire(t, msg, &msg2, tc.keyType, tc.size) - } -} -*/ diff --git a/keys/types.go b/keys/types.go index 16b8f6dd0..40751ad77 100644 --- a/keys/types.go +++ b/keys/types.go @@ -42,7 +42,7 @@ func (i Info) Address() []byte { } func (i Info) bytes() []byte { - bz, err := cdc.MarshalBinary(i) + bz, err := cdc.MarshalBinaryBare(i) if err != nil { panic(err) } @@ -50,6 +50,6 @@ func (i Info) bytes() []byte { } func readInfo(bz []byte) (info Info, err error) { - err = cdc.UnmarshalBinary(bz, &info) + err = cdc.UnmarshalBinaryBare(bz, &info) return } diff --git a/priv_key.go b/priv_key.go index adacb1379..61d373f60 100644 --- a/priv_key.go +++ b/priv_key.go @@ -10,7 +10,7 @@ import ( ) func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { - err = cdc.UnmarshalBinary(privKeyBytes, &privKey) + err = cdc.UnmarshalBinaryBare(privKeyBytes, &privKey) return } @@ -31,7 +31,7 @@ var _ PrivKey = PrivKeyEd25519{} type PrivKeyEd25519 [64]byte func (privKey PrivKeyEd25519) Bytes() []byte { - bz, err := cdc.MarshalBinary(privKey) + bz, err := cdc.MarshalBinaryBare(privKey) if err != nil { panic(err) } @@ -75,7 +75,7 @@ func (privKey PrivKeyEd25519) String() string { // Deterministically generates new priv-key bytes from key. func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { - bz, err := cdc.MarshalBinary(struct { + bz, err := cdc.MarshalBinaryBare(struct { PrivKey [64]byte Index int }{privKey, index}) @@ -113,7 +113,7 @@ var _ PrivKey = PrivKeySecp256k1{} type PrivKeySecp256k1 [32]byte func (privKey PrivKeySecp256k1) Bytes() []byte { - bz, err := cdc.MarshalBinary(privKey) + bz, err := cdc.MarshalBinaryBare(privKey) if err != nil { panic(err) } diff --git a/pub_key.go b/pub_key.go index 8ed1df356..9be64acdf 100644 --- a/pub_key.go +++ b/pub_key.go @@ -18,7 +18,7 @@ import ( type Address = cmn.HexBytes func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { - err = cdc.UnmarshalBinary(pubKeyBytes, &pubKey) + err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) return } @@ -46,7 +46,7 @@ func (pubKey PubKeyEd25519) Address() Address { } func (pubKey PubKeyEd25519) Bytes() []byte { - bz, err := cdc.MarshalBinary(pubKey) + bz, err := cdc.MarshalBinaryBare(pubKey) if err != nil { panic(err) } @@ -108,7 +108,7 @@ func (pubKey PubKeySecp256k1) Address() Address { } func (pubKey PubKeySecp256k1) Bytes() []byte { - bz, err := cdc.MarshalBinary(pubKey) + bz, err := cdc.MarshalBinaryBare(pubKey) if err != nil { panic(err) } diff --git a/signature.go b/signature.go index 3a0f6a7a7..cfe927137 100644 --- a/signature.go +++ b/signature.go @@ -8,7 +8,7 @@ import ( ) func SignatureFromBytes(pubKeyBytes []byte) (pubKey Signature, err error) { - err = cdc.UnmarshalBinary(pubKeyBytes, &pubKey) + err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) return } @@ -28,7 +28,7 @@ var _ Signature = SignatureEd25519{} type SignatureEd25519 [64]byte func (sig SignatureEd25519) Bytes() []byte { - bz, err := cdc.MarshalBinary(sig) + bz, err := cdc.MarshalBinaryBare(sig) if err != nil { panic(err) } @@ -61,7 +61,7 @@ var _ Signature = SignatureSecp256k1{} type SignatureSecp256k1 []byte func (sig SignatureSecp256k1) Bytes() []byte { - bz, err := cdc.MarshalBinary(sig) + bz, err := cdc.MarshalBinaryBare(sig) if err != nil { panic(err) } diff --git a/version.go b/version.go index f641e03a3..9c51b256f 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.6.0" +const Version = "0.6.1" From 5d5f580f49ca66c13400938c64334186068c8b7c Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 26 Mar 2018 10:44:04 +0200 Subject: [PATCH 215/273] Update changelog for v0.6.1 --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f58e18ca..8f72be957 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,18 @@ # Changelog -## 0.6.0 (March 2, 2017) +## 0.6.1 (March 26, 2018) + +BREAKING CHANGES + +- Encoding uses MarshalBinaryBare rather than MarshalBinary (which auto-length-prefixes) for pub/priv/sig. + +## 0.6.0 (March 2, 2018) BREAKING CHANGES - Update Amino names from "com.tendermint/..." to "tendermint/" -## 0.5.0 (March 2, 2017) +## 0.5.0 (March 2, 2018) BREAKING CHANGES From 7fb3f704b38492fb24cc6f807baee524ef7f4f8d Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Mon, 26 Mar 2018 10:59:10 +0200 Subject: [PATCH 216/273] Update README with examples; Add signature test --- README.md | 15 +++++++++++++++ encode_test.go | 18 ++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3c33532fc..785e887b8 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,18 @@ go-crypto is the cryptographic package adapted for Tendermint's uses ## Importing it `import "github.com/tendermint/go-crypto"` + +## Binary encoding + +go-crypto `.Bytes()` uses Amino:binary encoding, but Amino:JSON is also supported. + +```go +Example Amino:JSON encodings: + +crypto.PrivKeyEd25519 - {"type":"954568A3288910","value":"EVkqJO/jIXp3rkASXfh9YnyToYXRXhBr6g9cQVxPFnQBP/5povV4HTjvsy530kybxKHwEi85iU8YL0qQhSYVoQ=="} +crypto.SignatureEd25519 - {"type":"6BF5903DA1DB28","value":"77sQNZOrf7ltExpf7AV1WaYPCHbyRLgjBsoWVzcduuLk+jIGmYk+s5R6Emm29p12HeiNAuhUJgdFGmwkpeGJCA=="} +crypto.PubKeyEd25519 - {"type":"AC26791624DE60","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="} +crypto.PrivKeySecp256k1 - {"type":"019E82E1B0F798","value":"zx4Pnh67N+g2V+5vZbQzEyRerX9c4ccNZOVzM9RvJ0Y="} +crypto.SignatureSecp256k1 - {"type":"6D1EA416E1FEE8","value":"MEUCIQCIg5TqS1l7I+MKTrSPIuUN2+4m5tA29dcauqn3NhEJ2wIgICaZ+lgRc5aOTVahU/XoLopXKn8BZcl0bnuYWLvohR8="} +crypto.PubKeySecp256k1 - {"type":"F8CCEAEB5AE980","value":"A8lPKJXcNl5VHt1FK8a244K9EJuS4WX1hFBnwisi0IJx"} +``` diff --git a/encode_test.go b/encode_test.go index d9332238e..0bd450829 100644 --- a/encode_test.go +++ b/encode_test.go @@ -18,7 +18,9 @@ func checkAminoBinary(t *testing.T, src byter, dst interface{}, size int) { // Make sure this is compatible with current (Bytes()) encoding. assert.Equal(t, src.Bytes(), bz, "Amino binary vs Bytes() mismatch") // Make sure we have the expected length. - assert.Equal(t, size, len(bz), "Amino binary size mismatch") + if size != -1 { + assert.Equal(t, size, len(bz), "Amino binary size mismatch") + } // Unmarshal. err = cdc.UnmarshalBinaryBare(bz, dst) require.Nil(t, err, "%+v", err) @@ -41,9 +43,8 @@ func checkAminoJSON(t *testing.T, src interface{}, dst interface{}, isNil bool) func TestKeyEncodings(t *testing.T) { cases := []struct { - privKey PrivKey - // 1 (type byte) + size of byte array - privSize, pubSize int + privKey PrivKey + privSize, pubSize int // binary sizes }{ { privKey: GenPrivKeyEd25519(), @@ -58,6 +59,7 @@ func TestKeyEncodings(t *testing.T) { } for _, tc := range cases { + // Check (de/en)codings of PrivKeys. var priv2, priv3 PrivKey checkAminoBinary(t, tc.privKey, &priv2, tc.privSize) @@ -65,6 +67,14 @@ func TestKeyEncodings(t *testing.T) { checkAminoJSON(t, tc.privKey, &priv3, false) // TODO also check Prefix bytes. assert.EqualValues(t, tc.privKey, priv3) + // Check (de/en)codings of Signatures. + var sig1, sig2, sig3 Signature + sig1 = tc.privKey.Sign([]byte("something")) + checkAminoBinary(t, sig1, &sig2, -1) // Siganture size changes for Secp anyways. + assert.EqualValues(t, sig1, sig2) + checkAminoJSON(t, sig1, &sig3, false) // TODO also check Prefix bytes. + assert.EqualValues(t, sig1, sig3) + // Check (de/en)codings of PubKeys. pubKey := tc.privKey.PubKey() var pub2, pub3 PubKey From 9c02c8ce933cc67b3e7241f6d6d44c9bcfff3485 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 4 Apr 2018 23:25:14 +0100 Subject: [PATCH 217/273] Add import/export of public keys #79 --- keys/keybase.go | 47 +++++++++++++++++++++++++++++++++++ keys/keybase_test.go | 59 ++++++++++++++++++++++++++++++++++++++++++-- keys/mintkey.go | 26 +++++++++++++++---- keys/types.go | 2 ++ 4 files changed, 127 insertions(+), 7 deletions(-) diff --git a/keys/keybase.go b/keys/keybase.go index 88a12000c..5c7b64723 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -110,6 +110,10 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signat if err != nil { return } + if info.PrivKeyArmor == "" { + err = fmt.Errorf("private key not available") + return + } priv, err := unarmorDecryptPrivKey(info.PrivKeyArmor, passphrase) if err != nil { return @@ -127,6 +131,22 @@ func (kb dbKeybase) Export(name string) (armor string, err error) { return armorInfoBytes(bz), nil } +// ExportPubKey returns public keys in ASCII armored format. +func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) { + bz := kb.db.Get(infoKey(name)) + if bz == nil { + return "", errors.New("No key to export with name " + name) + } + info, err := readInfo(bz) + if err != nil { + return + } + return armorPubKeyBytes(info.PubKey.Bytes()), nil +} + +// ExportPubKey imports ASCII-armored public keys. +// Store a new Info object holding a public key only, i.e. it will +// not be possible to sign with it as it lacks the secret key. func (kb dbKeybase) Import(name string, armor string) (err error) { bz := kb.db.Get(infoKey(name)) if len(bz) > 0 { @@ -140,6 +160,23 @@ func (kb dbKeybase) Import(name string, armor string) (err error) { return nil } +func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) { + bz := kb.db.Get(infoKey(name)) + if len(bz) > 0 { + return errors.New("Cannot overwrite data for name " + name) + } + pubBytes, err := unarmorPubKeyBytes(armor) + if err != nil { + return + } + pubKey, err := crypto.PubKeyFromBytes(pubBytes) + if err != nil { + return + } + kb.writePubKey(pubKey, name) + return +} + // Delete removes key forever, but we must present the // proper passphrase before deleting it (for security). func (kb dbKeybase) Delete(name, passphrase string) error { @@ -174,6 +211,16 @@ func (kb dbKeybase) Update(name, oldpass, newpass string) error { kb.writeKey(key, name, newpass) return nil } + +func (kb dbKeybase) writePubKey(pub crypto.PubKey, name string) Info { + // make Info + info := newInfo(name, pub, "") + + // write them both + kb.db.SetSync(infoKey(name), info.bytes()) + return info +} + func (kb dbKeybase) writeKey(priv crypto.PrivKey, name, passphrase string) Info { // generate the encrypted privkey privArmor := encryptArmorPrivKey(priv, passphrase) diff --git a/keys/keybase_test.go b/keys/keybase_test.go index 84c81c81f..aaf3b92fb 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -91,8 +91,8 @@ func TestSignVerify(t *testing.T) { ) algo := keys.AlgoSecp256k1 - n1, n2 := "some dude", "a dudette" - p1, p2 := "1234", "foobar" + n1, n2, n3 := "some dude", "a dudette", "dude-ish" + p1, p2, p3 := "1234", "foobar", "foobar" // create two users and get their info i1, _, err := cstore.Create(n1, p1, algo) @@ -101,9 +101,18 @@ func TestSignVerify(t *testing.T) { i2, _, err := cstore.Create(n2, p2, algo) require.Nil(t, err) + // Import a public key + armor, err := cstore.ExportPubKey(n2) + require.Nil(t, err) + cstore.ImportPubKey(n3, armor) + i3, err := cstore.Get(n3) + require.Nil(t, err) + require.Equal(t, i3.PrivKeyArmor, "") + // let's try to sign some messages d1 := []byte("my first message") d2 := []byte("some other important info!") + d3 := []byte("feels like I forgot something...") // try signing both data with both keys... s11, pub1, err := cstore.Sign(n1, p1, d1) @@ -145,6 +154,10 @@ func TestSignVerify(t *testing.T) { valid := tc.key.VerifyBytes(tc.data, tc.sig) assert.Equal(t, tc.valid, valid, "%d", i) } + + // Now try to sign data with a secret-less key + _, _, err = cstore.Sign(n3, p3, d3) + assert.NotNil(t, err) } /* @@ -243,6 +256,48 @@ func TestExportImport(t *testing.T) { assert.Equal(t, john, john2) } +func TestExportImportPubKey(t *testing.T) { + // make the storage with reasonable defaults + db := dbm.NewMemDB() + cstore := keys.New( + db, + words.MustLoadCodec("english"), + ) + + // Create a private-public key pair and ensure consistency + info, _, err := cstore.Create("john", "passphrase", keys.AlgoEd25519) + assert.Nil(t, err) + assert.NotEqual(t, info.PrivKeyArmor, "") + assert.Equal(t, info.Name, "john") + addr := info.PubKey.Address() + john, err := cstore.Get("john") + assert.Nil(t, err) + assert.Equal(t, john.Name, "john") + assert.Equal(t, john.PubKey.Address(), addr) + + // Export the public key only + armor, err := cstore.ExportPubKey("john") + assert.Nil(t, err) + // Import it under a different name + err = cstore.ImportPubKey("john-pubkey-only", armor) + assert.Nil(t, err) + // Ensure consistency + john2, err := cstore.Get("john-pubkey-only") + assert.Nil(t, err) + assert.Equal(t, john2.PrivKeyArmor, "") + // Compare the public keys + assert.True(t, john.PubKey.Equals(john2.PubKey)) + // Ensure the original key hasn't changed + john, err = cstore.Get("john") + assert.Nil(t, err) + assert.Equal(t, john.PubKey.Address(), addr) + assert.Equal(t, john.Name, "john") + + // Ensure keys cannot be overwritten + err = cstore.ImportPubKey("john-pubkey-only", armor) + assert.NotNil(t, err) +} + // TestAdvancedKeyManagement verifies update, import, export functionality func TestAdvancedKeyManagement(t *testing.T) { diff --git a/keys/mintkey.go b/keys/mintkey.go index 73263b83a..264a9747d 100644 --- a/keys/mintkey.go +++ b/keys/mintkey.go @@ -13,24 +13,40 @@ import ( const ( blockTypePrivKey = "TENDERMINT PRIVATE KEY" blockTypeKeyInfo = "TENDERMINT KEY INFO" + blockTypePubKey = "TENDERMINT PUBLIC KEY" ) func armorInfoBytes(bz []byte) string { + return armorBytes(bz, blockTypeKeyInfo) +} + +func armorPubKeyBytes(bz []byte) string { + return armorBytes(bz, blockTypePubKey) +} + +func armorBytes(bz []byte, blockType string) string { header := map[string]string{ "type": "Info", "version": "0.0.0", } - armorStr := crypto.EncodeArmor(blockTypeKeyInfo, header, bz) - return armorStr + return crypto.EncodeArmor(blockType, header, bz) } func unarmorInfoBytes(armorStr string) (bz []byte, err error) { - blockType, header, bz, err := crypto.DecodeArmor(armorStr) + return unarmorBytes(armorStr, blockTypeKeyInfo) +} + +func unarmorPubKeyBytes(armorStr string) (bz []byte, err error) { + return unarmorBytes(armorStr, blockTypePubKey) +} + +func unarmorBytes(armorStr, blockType string) (bz []byte, err error) { + bType, header, bz, err := crypto.DecodeArmor(armorStr) if err != nil { return } - if blockType != blockTypeKeyInfo { - err = fmt.Errorf("Unrecognized armor type: %v", blockType) + if bType != blockType { + err = fmt.Errorf("Unrecognized armor type %q, expected: %q", bType, blockType) return } if header["version"] != "0.0.0" { diff --git a/keys/types.go b/keys/types.go index 40751ad77..e1df644ab 100644 --- a/keys/types.go +++ b/keys/types.go @@ -18,7 +18,9 @@ type Keybase interface { Delete(name, passphrase string) error Import(name string, armor string) (err error) + ImportPubKey(name string, armor string) (err error) Export(name string) (armor string, err error) + ExportPubKey(name string) (armor string, err error) } // Info is the public information about a key From 105847b7dd804b297a03959d356dba458f608932 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 5 Apr 2018 08:13:13 +0100 Subject: [PATCH 218/273] Fix comments --- keys/keybase.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/keys/keybase.go b/keys/keybase.go index 5c7b64723..876eef8f5 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -132,6 +132,8 @@ func (kb dbKeybase) Export(name string) (armor string, err error) { } // ExportPubKey returns public keys in ASCII armored format. +// Retrieve a Info object by its name and return the public key in +// a portable format. func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) { bz := kb.db.Get(infoKey(name)) if bz == nil { @@ -144,9 +146,6 @@ func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) { return armorPubKeyBytes(info.PubKey.Bytes()), nil } -// ExportPubKey imports ASCII-armored public keys. -// Store a new Info object holding a public key only, i.e. it will -// not be possible to sign with it as it lacks the secret key. func (kb dbKeybase) Import(name string, armor string) (err error) { bz := kb.db.Get(infoKey(name)) if len(bz) > 0 { @@ -160,6 +159,9 @@ func (kb dbKeybase) Import(name string, armor string) (err error) { return nil } +// ExportPubKey imports ASCII-armored public keys. +// Store a new Info object holding a public key only, i.e. it will +// not be possible to sign with it as it lacks the secret key. func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) { bz := kb.db.Get(infoKey(name)) if len(bz) > 0 { From 915416979bf70efa4bcbf1c6cd5d64c5fff9fc19 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 9 Apr 2018 16:21:58 +0300 Subject: [PATCH 219/273] update for latest amino. bump version --- CHANGELOG.md | 6 ++++++ Gopkg.lock | 14 +++++++------- Gopkg.toml | 4 ++-- version.go | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f72be957..91dcfab52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.6.2 (April 9, 2018) + +IMPROVEMENTS + +- Update for latest go-amino + ## 0.6.1 (March 26, 2018) BREAKING CHANGES diff --git a/Gopkg.lock b/Gopkg.lock index bfe089b72..f52af5591 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -113,7 +113,7 @@ "leveldb/table", "leveldb/util" ] - revision = "169b1b37be738edb2813dab48c97a549bcf99bb5" + revision = "714f901b98fdb3aa954b4193d8cbd64a28d80cad" [[projects]] branch = "master" @@ -128,8 +128,8 @@ [[projects]] name = "github.com/tendermint/go-amino" packages = ["."] - revision = "f55c3351f30e5987500020631f00e87a035ed415" - version = "0.9.3" + revision = "42246108ff925a457fb709475070a03dfd3e2b5c" + version = "0.9.6" [[projects]] name = "github.com/tendermint/tmlibs" @@ -138,8 +138,8 @@ "db", "log" ] - revision = "e9cf47606cfcbdc28a7c16671b4a70b459e9d4cc" - version = "v0.8.0-dev" + revision = "2e24b64fc121dcdf1cabceab8dc2f7257675483c" + version = "v0.8.1" [[projects]] branch = "master" @@ -161,11 +161,11 @@ "ripemd160", "salsa20/salsa" ] - revision = "b4956d363a8b14623cc81db401707679605930a3" + revision = "b2aa35443fbc700ab74c586ae79b81c171851023" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "9748e96106582387ac49df1db8e4456bd51c8e9362c86992d6ce7011c1783f55" + inputs-digest = "f9ccfa2cadfcbfb43bf729b871a0ad2f8d4f4acb118cd859e6faf9b24842b840" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index a7f84bb59..4ccb8c07d 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -47,11 +47,11 @@ [[constraint]] name = "github.com/tendermint/go-amino" - version = "0.9.3" + version = "0.9.6" [[constraint]] name = "github.com/tendermint/tmlibs" - version = "0.8.0-dev" + version = "0.8.1" [[constraint]] name = "github.com/tyler-smith/go-bip39" diff --git a/version.go b/version.go index 9c51b256f..aac87c4f3 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.6.1" +const Version = "0.6.2" From ad837a8183fcfe84248cc3a92157fb463b2d7b09 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sat, 5 May 2018 19:17:21 -0400 Subject: [PATCH 220/273] fix ed25519 Generate --- priv_key.go | 7 ++++--- priv_key_test.go | 16 +++++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/priv_key.go b/priv_key.go index 61d373f60..82e1cfced 100644 --- a/priv_key.go +++ b/priv_key.go @@ -83,9 +83,10 @@ func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { panic(err) } newBytes := Sha256(bz) - var newKey [64]byte - copy(newKey[:], newBytes) - return PrivKeyEd25519(newKey) + newKey := new([64]byte) + copy(newKey[:32], newBytes) + ed25519.MakePublicKey(newKey) + return PrivKeyEd25519(*newKey) } func GenPrivKeyEd25519() PrivKeyEd25519 { diff --git a/priv_key_test.go b/priv_key_test.go index 3fbfba34d..6abe36ac5 100644 --- a/priv_key_test.go +++ b/priv_key_test.go @@ -1,15 +1,21 @@ -package crypto - -/* +package crypto_test import ( - "fmt" "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + crypto "github.com/tendermint/go-crypto" ) +func TestGeneratePrivKey(t *testing.T) { + testPriv := crypto.GenPrivKeyEd25519() + testGenerate := testPriv.Generate(1) + signBytes := []byte("something to sign") + assert.True(t, testGenerate.PubKey().VerifyBytes(signBytes, testGenerate.Sign(signBytes))) +} + +/* + type BadKey struct { PrivKeyEd25519 } From 94ce56d243e02cbfab1dfc1868a06a79cb07a0e4 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 9 May 2018 11:48:46 +0100 Subject: [PATCH 221/273] Use constant-time comparator (sublte.ConstantTimeCompare) to compare signatures prevents potential signature forgery resolves #91 --- signature.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/signature.go b/signature.go index cfe927137..4f55420c5 100644 --- a/signature.go +++ b/signature.go @@ -1,9 +1,10 @@ package crypto import ( - "bytes" "fmt" + "crypto/subtle" + . "github.com/tendermint/tmlibs/common" ) @@ -41,7 +42,7 @@ func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fing func (sig SignatureEd25519) Equals(other Signature) bool { if otherEd, ok := other.(SignatureEd25519); ok { - return bytes.Equal(sig[:], otherEd[:]) + return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 1 } else { return false } @@ -74,7 +75,7 @@ func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fi func (sig SignatureSecp256k1) Equals(other Signature) bool { if otherSecp, ok := other.(SignatureSecp256k1); ok { - return bytes.Equal(sig[:], otherSecp[:]) + return subtle.ConstantTimeCompare(sig[:], otherSecp[:]) == 1 } else { return false } From 3477dd7a9042e04517d79d0eb153f8fe715c3786 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 9 May 2018 14:30:17 +0100 Subject: [PATCH 222/273] safer PRNG seeding: hash concatenation of fresh seedBytes with current seedBytes --- random.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/random.go b/random.go index 46754219d..66da035a9 100644 --- a/random.go +++ b/random.go @@ -4,6 +4,7 @@ import ( "crypto/aes" "crypto/cipher" crand "crypto/rand" + "crypto/sha256" "encoding/hex" "io" "sync" @@ -72,8 +73,12 @@ type randInfo struct { func (ri *randInfo) MixEntropy(seedBytes []byte) { ri.mtx.Lock() defer ri.mtx.Unlock() - // Make new ri.seedBytes - hashBytes := Sha256(seedBytes) + // Make new ri.seedBytes using passed seedBytes and current ri.seedBytes: + // ri.seedBytes = sha256( seedBytes || ri.seedBytes ) + h := sha256.New() + h.Write(seedBytes) + h.Write(ri.seedBytes[:]) + hashBytes := h.Sum(nil) hashBytes32 := [32]byte{} copy(hashBytes32[:], hashBytes) ri.seedBytes = xorBytes32(ri.seedBytes, hashBytes32) From 35cf21c6ebdad9632414d3f244824302b2717e56 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 9 May 2018 13:48:21 -0700 Subject: [PATCH 223/273] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 785e887b8..4a524c014 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,10 @@ go-crypto is the cryptographic package adapted for Tendermint's uses ## Binary encoding +For Binary encoding, please refer to the [Tendermint encoding spec](https://github.com/tendermint/tendermint/blob/develop/docs/specification/new-spec/encoding.md). + +## JSON Encoding + go-crypto `.Bytes()` uses Amino:binary encoding, but Amino:JSON is also supported. ```go From 43570388a9dbb56e098bb30ff61d4b0d8795ae09 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Wed, 9 May 2018 13:48:49 -0700 Subject: [PATCH 224/273] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 785e887b8..4a524c014 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,10 @@ go-crypto is the cryptographic package adapted for Tendermint's uses ## Binary encoding +For Binary encoding, please refer to the [Tendermint encoding spec](https://github.com/tendermint/tendermint/blob/develop/docs/specification/new-spec/encoding.md). + +## JSON Encoding + go-crypto `.Bytes()` uses Amino:binary encoding, but Amino:JSON is also supported. ```go From 1c8dffaa282ba9ebfe597e38f9849bc70f40efe5 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Sun, 13 May 2018 11:06:20 -0400 Subject: [PATCH 225/273] Initial implementation of xchacha20poly1035 aead --- xchacha20poly1035/xchachapoly.go | 237 +++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 xchacha20poly1035/xchachapoly.go diff --git a/xchacha20poly1035/xchachapoly.go b/xchacha20poly1035/xchachapoly.go new file mode 100644 index 000000000..b9d823414 --- /dev/null +++ b/xchacha20poly1035/xchachapoly.go @@ -0,0 +1,237 @@ +package xchacha20poly1305 + +import ( + "crypto/cipher" + "encoding/binary" + "errors" + + "golang.org/x/crypto/chacha20poly1305" +) + +var sigma = [4]uint32{0x61707865, 0x3320646e, 0x79622d32, 0x6b206574} + +type xchacha20poly1305 struct { + key [KeySize]byte +} + +const ( + // KeySize is the size of the key used by this AEAD, in bytes. + KeySize = 32 + // NonceSize is the size of the nonce used with this AEAD, in bytes. + NonceSize = 24 +) + +//New xChaChapoly1305 AEAD with 24 byte nonces +func New(key []byte) (cipher.AEAD, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20poly1305: bad key length") + } + ret := new(xchacha20poly1305) + copy(ret.key[:], key) + return ret, nil + +} +func (c *xchacha20poly1305) NonceSize() int { + return NonceSize +} + +func (c *xchacha20poly1305) Overhead() int { + return 16 +} + +func (c *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != NonceSize { + panic("chacha20poly1305: bad nonce length passed to Seal") + } + + if uint64(len(plaintext)) > (1<<38)-64 { + panic("chacha20poly1305: plaintext too large") + } + + var subKey [KeySize]byte + var hNonce [16]byte + var subNonce [chacha20poly1305.NonceSize]byte + copy(hNonce[:], nonce[:16]) + + HChaCha20(&subKey, &hNonce, &c.key) + + chacha20poly1305, _ := chacha20poly1305.New(subKey[:]) + + copy(subNonce[4:], nonce[16:]) + + return chacha20poly1305.Seal(dst, subNonce[:], plaintext, additionalData) +} + +func (c *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != NonceSize { + panic("chacha20poly1305: bad nonce length passed to Open") + } + if uint64(len(ciphertext)) > (1<<38)-48 { + panic("chacha20poly1305: ciphertext too large") + } + var subKey [KeySize]byte + var hNonce [16]byte + var subNonce [chacha20poly1305.NonceSize]byte + copy(hNonce[:], nonce[:16]) + + HChaCha20(&subKey, &hNonce, &c.key) + + chacha20poly1305, _ := chacha20poly1305.New(subKey[:]) + + copy(subNonce[4:], nonce[16:]) + + return chacha20poly1305.Open(dst, subNonce[:], ciphertext, additionalData) +} + +// The MIT License (MIT) + +// Copyright (c) 2016 Andreas Auernhammer + +// 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. + +// HChaCha20 generates 32 pseudo-random bytes from a 128 bit nonce and a 256 bit secret key. +// It can be used as a key-derivation-function (KDF). +func HChaCha20(out *[32]byte, nonce *[16]byte, key *[32]byte) { hChaCha20Generic(out, nonce, key) } + +func hChaCha20Generic(out *[32]byte, nonce *[16]byte, key *[32]byte) { + v00 := sigma[0] + v01 := sigma[1] + v02 := sigma[2] + v03 := sigma[3] + v04 := binary.LittleEndian.Uint32(key[0:]) + v05 := binary.LittleEndian.Uint32(key[4:]) + v06 := binary.LittleEndian.Uint32(key[8:]) + v07 := binary.LittleEndian.Uint32(key[12:]) + v08 := binary.LittleEndian.Uint32(key[16:]) + v09 := binary.LittleEndian.Uint32(key[20:]) + v10 := binary.LittleEndian.Uint32(key[24:]) + v11 := binary.LittleEndian.Uint32(key[28:]) + v12 := binary.LittleEndian.Uint32(nonce[0:]) + v13 := binary.LittleEndian.Uint32(nonce[4:]) + v14 := binary.LittleEndian.Uint32(nonce[8:]) + v15 := binary.LittleEndian.Uint32(nonce[12:]) + + for i := 0; i < 20; i += 2 { + v00 += v04 + v12 ^= v00 + v12 = (v12 << 16) | (v12 >> 16) + v08 += v12 + v04 ^= v08 + v04 = (v04 << 12) | (v04 >> 20) + v00 += v04 + v12 ^= v00 + v12 = (v12 << 8) | (v12 >> 24) + v08 += v12 + v04 ^= v08 + v04 = (v04 << 7) | (v04 >> 25) + v01 += v05 + v13 ^= v01 + v13 = (v13 << 16) | (v13 >> 16) + v09 += v13 + v05 ^= v09 + v05 = (v05 << 12) | (v05 >> 20) + v01 += v05 + v13 ^= v01 + v13 = (v13 << 8) | (v13 >> 24) + v09 += v13 + v05 ^= v09 + v05 = (v05 << 7) | (v05 >> 25) + v02 += v06 + v14 ^= v02 + v14 = (v14 << 16) | (v14 >> 16) + v10 += v14 + v06 ^= v10 + v06 = (v06 << 12) | (v06 >> 20) + v02 += v06 + v14 ^= v02 + v14 = (v14 << 8) | (v14 >> 24) + v10 += v14 + v06 ^= v10 + v06 = (v06 << 7) | (v06 >> 25) + v03 += v07 + v15 ^= v03 + v15 = (v15 << 16) | (v15 >> 16) + v11 += v15 + v07 ^= v11 + v07 = (v07 << 12) | (v07 >> 20) + v03 += v07 + v15 ^= v03 + v15 = (v15 << 8) | (v15 >> 24) + v11 += v15 + v07 ^= v11 + v07 = (v07 << 7) | (v07 >> 25) + v00 += v05 + v15 ^= v00 + v15 = (v15 << 16) | (v15 >> 16) + v10 += v15 + v05 ^= v10 + v05 = (v05 << 12) | (v05 >> 20) + v00 += v05 + v15 ^= v00 + v15 = (v15 << 8) | (v15 >> 24) + v10 += v15 + v05 ^= v10 + v05 = (v05 << 7) | (v05 >> 25) + v01 += v06 + v12 ^= v01 + v12 = (v12 << 16) | (v12 >> 16) + v11 += v12 + v06 ^= v11 + v06 = (v06 << 12) | (v06 >> 20) + v01 += v06 + v12 ^= v01 + v12 = (v12 << 8) | (v12 >> 24) + v11 += v12 + v06 ^= v11 + v06 = (v06 << 7) | (v06 >> 25) + v02 += v07 + v13 ^= v02 + v13 = (v13 << 16) | (v13 >> 16) + v08 += v13 + v07 ^= v08 + v07 = (v07 << 12) | (v07 >> 20) + v02 += v07 + v13 ^= v02 + v13 = (v13 << 8) | (v13 >> 24) + v08 += v13 + v07 ^= v08 + v07 = (v07 << 7) | (v07 >> 25) + v03 += v04 + v14 ^= v03 + v14 = (v14 << 16) | (v14 >> 16) + v09 += v14 + v04 ^= v09 + v04 = (v04 << 12) | (v04 >> 20) + v03 += v04 + v14 ^= v03 + v14 = (v14 << 8) | (v14 >> 24) + v09 += v14 + v04 ^= v09 + v04 = (v04 << 7) | (v04 >> 25) + } + + binary.LittleEndian.PutUint32(out[0:], v00) + binary.LittleEndian.PutUint32(out[4:], v01) + binary.LittleEndian.PutUint32(out[8:], v02) + binary.LittleEndian.PutUint32(out[12:], v03) + binary.LittleEndian.PutUint32(out[16:], v12) + binary.LittleEndian.PutUint32(out[20:], v13) + binary.LittleEndian.PutUint32(out[24:], v14) + binary.LittleEndian.PutUint32(out[28:], v15) +} From 1c9ff46e98df9e76d4b9a160c4635d72afd12f04 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 30 Apr 2018 16:42:11 +0200 Subject: [PATCH 226/273] Ledger integration, WIP --- Gopkg.lock | 14 ++- Gopkg.toml | 4 + _nano/keys.go | 294 --------------------------------------------- _nano/keys_test.go | 142 ---------------------- _nano/sign.go | 63 ---------- _nano/sign_test.go | 160 ------------------------ amino.go | 2 + ledger.go | 154 ++++++++++++++++++++++++ ledger_test.go | 72 +++++++++++ signature.go | 6 + 10 files changed, 251 insertions(+), 660 deletions(-) delete mode 100644 _nano/keys.go delete mode 100644 _nano/keys_test.go delete mode 100644 _nano/sign.go delete mode 100644 _nano/sign_test.go create mode 100644 ledger.go create mode 100644 ledger_test.go diff --git a/Gopkg.lock b/Gopkg.lock index f52af5591..fbfaa63fa 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,12 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + name = "github.com/brejski/hid" + packages = ["."] + revision = "06112dcfcc50a7e0e4fd06e17f9791e788fdaafc" + [[projects]] branch = "master" name = "github.com/btcsuite/btcd" @@ -147,6 +153,12 @@ packages = ["."] revision = "8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc" +[[projects]] + branch = "master" + name = "github.com/zondax/ledger-goclient" + packages = ["."] + revision = "0eb48e14b06efd0354c2e0e18f15db121c64b9b8" + [[projects]] branch = "master" name = "golang.org/x/crypto" @@ -166,6 +178,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "f9ccfa2cadfcbfb43bf729b871a0ad2f8d4f4acb118cd859e6faf9b24842b840" + inputs-digest = "f3cfb54414cb9d59bab79226c7778673e7ac5b7a464baf9b2ea76c1f2563631e" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 4ccb8c07d..3737ec5f9 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -57,6 +57,10 @@ name = "github.com/tyler-smith/go-bip39" branch = "master" +[[constraint]] + name = "github.com/zondax/ledger-goclient" + branch = "master" + [prune] go-tests = true unused-packages = true diff --git a/_nano/keys.go b/_nano/keys.go deleted file mode 100644 index 8cf1c3721..000000000 --- a/_nano/keys.go +++ /dev/null @@ -1,294 +0,0 @@ -package nano - -import ( - "bytes" - "encoding/hex" - - "github.com/pkg/errors" - - ledger "github.com/ethanfrey/ledger" - - crypto "github.com/tendermint/go-crypto" - amino "github.com/tendermint/go-amino" -) - -//nolint -const ( - NameLedgerEd25519 = "ledger-ed25519" - TypeLedgerEd25519 = 0x10 - - // Timeout is the number of seconds to wait for a response from the ledger - // if eg. waiting for user confirmation on button push - Timeout = 20 -) - -var device *ledger.Ledger - -// getLedger gets a copy of the device, and caches it -func getLedger() (*ledger.Ledger, error) { - var err error - if device == nil { - device, err = ledger.FindLedger() - } - return device, err -} - -func signLedger(device *ledger.Ledger, msg []byte) (pub crypto.PubKey, sig crypto.Signature, err error) { - var resp []byte - - packets := generateSignRequests(msg) - for _, pack := range packets { - resp, err = device.Exchange(pack, Timeout) - if err != nil { - return pub, sig, err - } - } - - // the last call is the result we want and needs to be parsed - key, bsig, err := parseDigest(resp) - if err != nil { - return pub, sig, err - } - - var b [32]byte - copy(b[:], key) - return PubKeyLedgerEd25519FromBytes(b), crypto.SignatureEd25519FromBytes(bsig), nil -} - -// PrivKeyLedgerEd25519 implements PrivKey, calling the ledger nano -// we cache the PubKey from the first call to use it later -type PrivKeyLedgerEd25519 struct { - // PubKey should be private, but we want to encode it via go-amino - // so we can view the address later, even without having the ledger - // attached - CachedPubKey crypto.PubKey -} - -// NewPrivKeyLedgerEd25519 will generate a new key and store the -// public key for later use. -func NewPrivKeyLedgerEd25519() (crypto.PrivKey, error) { - var pk PrivKeyLedgerEd25519 - // getPubKey will cache the pubkey for later use, - // this allows us to return an error early if the ledger - // is not plugged in - _, err := pk.getPubKey() - return pk.Wrap(), err -} - -// ValidateKey allows us to verify the sanity of a key -// after loading it from disk -func (pk *PrivKeyLedgerEd25519) ValidateKey() error { - // getPubKey will return an error if the ledger is not - // properly set up... - pub, err := pk.forceGetPubKey() - if err != nil { - return err - } - // verify this matches cached address - if !pub.Equals(pk.CachedPubKey) { - return errors.New("ledger doesn't match cached key") - } - return nil -} - -// AssertIsPrivKeyInner fulfils PrivKey Interface -func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} - -// Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify -// the same key when we reconnect to a ledger -func (pk *PrivKeyLedgerEd25519) Bytes() []byte { - return amino.BinaryBytes(pk.Wrap()) -} - -// Sign calls the ledger and stores the PubKey for future use -// -// XXX/TODO: panics if there is an error communicating with the ledger. -// -// Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, -// returning an error, so this should only trigger if the privkey is held -// in memory for a while before use. -func (pk *PrivKeyLedgerEd25519) Sign(msg []byte) crypto.Signature { - // oh, I wish there was better error handling - dev, err := getLedger() - if err != nil { - panic(err) - } - - pub, sig, err := signLedger(dev, msg) - if err != nil { - panic(err) - } - - // if we have no pubkey yet, store it for future queries - if pk.CachedPubKey.Empty() { - pk.CachedPubKey = pub - } else if !pk.CachedPubKey.Equals(pub) { - panic("signed with a different key than stored") - } - return sig -} - -// PubKey returns the stored PubKey -// TODO: query the ledger if not there, once it is not volatile -func (pk *PrivKeyLedgerEd25519) PubKey() crypto.PubKey { - key, err := pk.getPubKey() - if err != nil { - panic(err) - } - return key -} - -// getPubKey reads the pubkey from cache or from the ledger itself -// since this involves IO, it may return an error, which is not exposed -// in the PubKey interface, so this function allows better error handling -func (pk *PrivKeyLedgerEd25519) getPubKey() (key crypto.PubKey, err error) { - // if we have no pubkey, set it - if pk.CachedPubKey.Empty() { - pk.CachedPubKey, err = pk.forceGetPubKey() - } - return pk.CachedPubKey, err -} - -// forceGetPubKey is like getPubKey but ignores any cached key -// and ensures we get it from the ledger itself. -func (pk *PrivKeyLedgerEd25519) forceGetPubKey() (key crypto.PubKey, err error) { - dev, err := getLedger() - if err != nil { - return key, errors.New("Can't connect to ledger device") - } - key, _, err = signLedger(dev, []byte{0}) - if err != nil { - return key, errors.New("Please open cosmos app on the ledger") - } - return key, err -} - -// Equals fulfils PrivKey Interface - makes sure both keys refer to the -// same -func (pk *PrivKeyLedgerEd25519) Equals(other crypto.PrivKey) bool { - if ledger, ok := other.Unwrap().(*PrivKeyLedgerEd25519); ok { - return pk.CachedPubKey.Equals(ledger.CachedPubKey) - } - return false -} - -// MockPrivKeyLedgerEd25519 behaves as the ledger, but stores a pre-packaged call-response -// for use in test cases -type MockPrivKeyLedgerEd25519 struct { - Msg []byte - Pub [KeyLength]byte - Sig [SigLength]byte -} - -// NewMockKey returns -func NewMockKey(msg, pubkey, sig string) (pk MockPrivKeyLedgerEd25519) { - var err error - pk.Msg, err = hex.DecodeString(msg) - if err != nil { - panic(err) - } - - bpk, err := hex.DecodeString(pubkey) - if err != nil { - panic(err) - } - bsig, err := hex.DecodeString(sig) - if err != nil { - panic(err) - } - - copy(pk.Pub[:], bpk) - copy(pk.Sig[:], bsig) - return pk -} - -var _ crypto.PrivKeyInner = MockPrivKeyLedgerEd25519{} - -// AssertIsPrivKeyInner fulfils PrivKey Interface -func (pk MockPrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} - -// Bytes fulfils PrivKey Interface - not supported -func (pk MockPrivKeyLedgerEd25519) Bytes() []byte { - return nil -} - -// Sign returns a real SignatureLedger, if the msg matches what we expect -func (pk MockPrivKeyLedgerEd25519) Sign(msg []byte) crypto.Signature { - if !bytes.Equal(pk.Msg, msg) { - panic("Mock key is for different msg") - } - return crypto.SignatureEd25519(pk.Sig).Wrap() -} - -// PubKey returns a real PubKeyLedgerEd25519, that will verify this signature -func (pk MockPrivKeyLedgerEd25519) PubKey() crypto.PubKey { - return PubKeyLedgerEd25519FromBytes(pk.Pub) -} - -// Equals compares that two Mocks have the same data -func (pk MockPrivKeyLedgerEd25519) Equals(other crypto.PrivKey) bool { - if mock, ok := other.Unwrap().(MockPrivKeyLedgerEd25519); ok { - return bytes.Equal(mock.Pub[:], pk.Pub[:]) && - bytes.Equal(mock.Sig[:], pk.Sig[:]) && - bytes.Equal(mock.Msg, pk.Msg) - } - return false -} - -//////////////////////////////////////////// -// pubkey - -// PubKeyLedgerEd25519 works like a normal Ed25519 except a hash before the verify bytes -type PubKeyLedgerEd25519 struct { - crypto.PubKeyEd25519 -} - -// PubKeyLedgerEd25519FromBytes creates a PubKey from the raw bytes -func PubKeyLedgerEd25519FromBytes(key [32]byte) crypto.PubKey { - return PubKeyLedgerEd25519{crypto.PubKeyEd25519(key)}.Wrap() -} - -// Bytes fulfils pk Interface - no data, just type info -func (pk PubKeyLedgerEd25519) Bytes() []byte { - return amino.BinaryBytes(pk.Wrap()) -} - -// VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand -func (pk PubKeyLedgerEd25519) VerifyBytes(msg []byte, sig crypto.Signature) bool { - hmsg := hashMsg(msg) - return pk.PubKeyEd25519.VerifyBytes(hmsg, sig) -} - -// Equals implements PubKey interface -func (pk PubKeyLedgerEd25519) Equals(other crypto.PubKey) bool { - if ledger, ok := other.Unwrap().(PubKeyLedgerEd25519); ok { - return pk.PubKeyEd25519.Equals(ledger.PubKeyEd25519.Wrap()) - } - return false -} - -/*** registration with go-data ***/ - -func init() { - crypto.PrivKeyMapper. - RegisterImplementation(&PrivKeyLedgerEd25519{}, NameLedgerEd25519, TypeLedgerEd25519). - RegisterImplementation(MockPrivKeyLedgerEd25519{}, "mock-ledger", 0x11) - - crypto.PubKeyMapper. - RegisterImplementation(PubKeyLedgerEd25519{}, NameLedgerEd25519, TypeLedgerEd25519) -} - -// Wrap fulfils interface for PrivKey struct -func (pk *PrivKeyLedgerEd25519) Wrap() crypto.PrivKey { - return crypto.PrivKey{PrivKeyInner: pk} -} - -// Wrap fulfils interface for PrivKey struct -func (pk MockPrivKeyLedgerEd25519) Wrap() crypto.PrivKey { - return crypto.PrivKey{PrivKeyInner: pk} -} - -// Wrap fulfils interface for PubKey struct -func (pk PubKeyLedgerEd25519) Wrap() crypto.PubKey { - return crypto.PubKey{PubKeyInner: pk} -} diff --git a/_nano/keys_test.go b/_nano/keys_test.go deleted file mode 100644 index fda096e29..000000000 --- a/_nano/keys_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package nano - -import ( - "encoding/hex" - "os" - "testing" - - asrt "github.com/stretchr/testify/assert" - rqr "github.com/stretchr/testify/require" - - crypto "github.com/tendermint/go-crypto" -) - -func TestLedgerKeys(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - cases := []struct { - msg, pubkey, sig string - valid bool - }{ - 0: { - msg: "F00D", - pubkey: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", - sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", - valid: true, - }, - 1: { - msg: "DEADBEEF", - pubkey: "0C45ADC887A5463F668533443C829ED13EA8E2E890C778957DC28DB9D2AD5A6C", - sig: "00ED74EED8FDAC7988A14BF6BC222120CBAC249D569AF4C2ADABFC86B792F97DF73C4919BE4B6B0ACB53547273BF29FBF0A9E0992FFAB6CB6C9B09311FC86A00", - valid: true, - }, - 2: { - msg: "1234567890AA", - pubkey: "598FC1F0C76363D14D7480736DEEF390D85863360F075792A6975EFA149FD7EA", - sig: "59AAB7D7BDC4F936B6415DE672A8B77FA6B8B3451CD95B3A631F31F9A05DAEEE5E7E4F89B64DDEBB5F63DC042CA13B8FCB8185F82AD7FD5636FFDA6B0DC9570B", - valid: true, - }, - 3: { - msg: "1234432112344321", - pubkey: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: true, - }, - 4: { - msg: "12344321123443", - pubkey: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - 5: { - msg: "1234432112344321", - pubkey: "459E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - 6: { - msg: "1234432112344321", - pubkey: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "716B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - } - - for i, tc := range cases { - bmsg, err := hex.DecodeString(tc.msg) - require.NoError(err, "%d", i) - - priv := NewMockKey(tc.msg, tc.pubkey, tc.sig) - pub := priv.PubKey() - sig := priv.Sign(bmsg) - - valid := pub.VerifyBytes(bmsg, sig) - assert.Equal(tc.valid, valid, "%d", i) - } -} - -func TestRealLedger(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - if os.Getenv("WITH_LEDGER") == "" { - t.Skip("Set WITH_LEDGER to run code on real ledger") - } - msg := []byte("kuhehfeohg") - - priv, err := NewPrivKeyLedgerEd25519() - require.Nil(err, "%+v", err) - pub := priv.PubKey() - sig := priv.Sign(msg) - - valid := pub.VerifyBytes(msg, sig) - assert.True(valid) - - // now, let's serialize the key and make sure it still works - bs := priv.Bytes() - priv2, err := crypto.PrivKeyFromBytes(bs) - require.Nil(err, "%+v", err) - - // make sure we get the same pubkey when we load from disk - pub2 := priv2.PubKey() - require.Equal(pub, pub2) - - // signing with the loaded key should match the original pubkey - sig = priv2.Sign(msg) - valid = pub.VerifyBytes(msg, sig) - assert.True(valid) - - // make sure pubkeys serialize properly as well - bs = pub.Bytes() - bpub, err := crypto.PubKeyFromBytes(bs) - require.NoError(err) - assert.Equal(pub, bpub) -} - -// TestRealLedgerErrorHandling calls. These tests assume -// the ledger is not plugged in.... -func TestRealLedgerErrorHandling(t *testing.T) { - require := rqr.New(t) - - if os.Getenv("WITH_LEDGER") != "" { - t.Skip("Skipping on WITH_LEDGER as it tests unplugged cases") - } - - // first, try to generate a key, must return an error - // (no panic) - _, err := NewPrivKeyLedgerEd25519() - require.Error(err) - - led := PrivKeyLedgerEd25519{} // empty - // or with some pub key - ed := crypto.GenPrivKeyEd25519() - led2 := PrivKeyLedgerEd25519{CachedPubKey: ed.PubKey()} - - // loading these should return errors - bs := led.Bytes() - _, err = crypto.PrivKeyFromBytes(bs) - require.Error(err) - - bs = led2.Bytes() - _, err = crypto.PrivKeyFromBytes(bs) - require.Error(err) -} diff --git a/_nano/sign.go b/_nano/sign.go deleted file mode 100644 index c40801583..000000000 --- a/_nano/sign.go +++ /dev/null @@ -1,63 +0,0 @@ -package nano - -import ( - "bytes" - "crypto/sha512" - - "github.com/pkg/errors" -) - -const ( - App = 0x80 - Init = 0x00 - Update = 0x01 - Digest = 0x02 - MaxChunk = 253 - KeyLength = 32 - SigLength = 64 -) - -var separator = []byte{0, 0xCA, 0xFE, 0} - -func generateSignRequests(payload []byte) [][]byte { - // nice one-shot - digest := []byte{App, Digest} - if len(payload) < MaxChunk { - return [][]byte{append(digest, payload...)} - } - - // large payload is multi-chunk - result := [][]byte{{App, Init}} - update := []byte{App, Update} - for len(payload) > MaxChunk { - msg := append(update, payload[:MaxChunk]...) - payload = payload[MaxChunk:] - result = append(result, msg) - } - result = append(result, append(update, payload...)) - result = append(result, digest) - return result -} - -func parseDigest(resp []byte) (key, sig []byte, err error) { - if resp[0] != App || resp[1] != Digest { - return nil, nil, errors.New("Invalid header") - } - resp = resp[2:] - if len(resp) != KeyLength+SigLength+len(separator) { - return nil, nil, errors.Errorf("Incorrect length: %d", len(resp)) - } - - key, resp = resp[:KeyLength], resp[KeyLength:] - if !bytes.Equal(separator, resp[:len(separator)]) { - return nil, nil, errors.New("Cannot find 0xCAFE") - } - - sig = resp[len(separator):] - return key, sig, nil -} - -func hashMsg(data []byte) []byte { - res := sha512.Sum512(data) - return res[:] -} diff --git a/_nano/sign_test.go b/_nano/sign_test.go deleted file mode 100644 index 18e4e0d0b..000000000 --- a/_nano/sign_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package nano - -import ( - "encoding/hex" - "testing" - - "github.com/pkg/errors" - asrt "github.com/stretchr/testify/assert" - rqr "github.com/stretchr/testify/require" - - crypto "github.com/tendermint/go-crypto" -) - -func parseEdKey(data []byte) (key crypto.PubKey, err error) { - ed := crypto.PubKeyEd25519{} - if len(data) < len(ed) { - return key, errors.Errorf("Key length too short: %d", len(data)) - } - copy(ed[:], data) - return ed.Wrap(), nil -} - -func parseSig(data []byte) (key crypto.Signature, err error) { - ed := crypto.SignatureEd25519{} - if len(data) < len(ed) { - return key, errors.Errorf("Sig length too short: %d", len(data)) - } - copy(ed[:], data) - return ed.Wrap(), nil -} - -func TestParseDigest(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - cases := []struct { - output string - key string - sig string - valid bool - }{ - { - output: "80028E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C9300CAFE00787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", - key: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", - sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", - valid: true, - }, - { - output: "800235467890876543525437890796574535467890", - key: "", - sig: "", - valid: false, - }, - } - - for i, tc := range cases { - msg, err := hex.DecodeString(tc.output) - require.Nil(err, "%d: %+v", i, err) - - lKey, lSig, err := parseDigest(msg) - if !tc.valid { - assert.NotNil(err, "%d", i) - } else if assert.Nil(err, "%d: %+v", i, err) { - key, err := hex.DecodeString(tc.key) - require.Nil(err, "%d: %+v", i, err) - sig, err := hex.DecodeString(tc.sig) - require.Nil(err, "%d: %+v", i, err) - - assert.Equal(key, lKey, "%d", i) - assert.Equal(sig, lSig, "%d", i) - } - } -} - -type cryptoCase struct { - msg string - key string - sig string - valid bool -} - -func toBytes(c cryptoCase) (msg, key, sig []byte, err error) { - msg, err = hex.DecodeString(c.msg) - if err != nil { - return - } - key, err = hex.DecodeString(c.key) - if err != nil { - return - } - sig, err = hex.DecodeString(c.sig) - return -} - -func TestCryptoConvert(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - cases := []cryptoCase{ - 0: { - msg: "F00D", - key: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", - sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", - valid: true, - }, - 1: { - msg: "DEADBEEF", - key: "0C45ADC887A5463F668533443C829ED13EA8E2E890C778957DC28DB9D2AD5A6C", - sig: "00ED74EED8FDAC7988A14BF6BC222120CBAC249D569AF4C2ADABFC86B792F97DF73C4919BE4B6B0ACB53547273BF29FBF0A9E0992FFAB6CB6C9B09311FC86A00", - valid: true, - }, - 2: { - msg: "1234567890AA", - key: "598FC1F0C76363D14D7480736DEEF390D85863360F075792A6975EFA149FD7EA", - sig: "59AAB7D7BDC4F936B6415DE672A8B77FA6B8B3451CD95B3A631F31F9A05DAEEE5E7E4F89B64DDEBB5F63DC042CA13B8FCB8185F82AD7FD5636FFDA6B0DC9570B", - valid: true, - }, - 3: { - msg: "1234432112344321", - key: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: true, - }, - 4: { - msg: "12344321123443", - key: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - 5: { - msg: "1234432112344321", - key: "459E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - 6: { - msg: "1234432112344321", - key: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "716B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - } - - for i, tc := range cases { - msg, key, sig, err := toBytes(tc) - require.Nil(err, "%d: %+v", i, err) - - pk, err := parseEdKey(key) - require.Nil(err, "%d: %+v", i, err) - psig, err := parseSig(sig) - require.Nil(err, "%d: %+v", i, err) - - // it is not the signature of the message itself - valid := pk.VerifyBytes(msg, psig) - assert.False(valid, "%d", i) - - // but rather of the hash of the msg - hmsg := hashMsg(msg) - valid = pk.VerifyBytes(hmsg, psig) - assert.Equal(tc.valid, valid, "%d", i) - } -} diff --git a/amino.go b/amino.go index 89636895a..2af765434 100644 --- a/amino.go +++ b/amino.go @@ -27,6 +27,8 @@ func RegisterAmino(cdc *amino.Codec) { "tendermint/PrivKeyEd25519", nil) cdc.RegisterConcrete(PrivKeySecp256k1{}, "tendermint/PrivKeySecp256k1", nil) + cdc.RegisterConcrete(PrivKeyLedgerSecp256k1{}, + "tendermint/PrivKeyLedgerSecp256k1", nil) cdc.RegisterInterface((*Signature)(nil), nil) cdc.RegisterConcrete(SignatureEd25519{}, diff --git a/ledger.go b/ledger.go new file mode 100644 index 000000000..0fe4b7d39 --- /dev/null +++ b/ledger.go @@ -0,0 +1,154 @@ +package crypto + +import ( + "github.com/pkg/errors" + + // secp256k1 "github.com/btcsuite/btcd/btcec" + ledger "github.com/zondax/ledger-goclient" +) + +var device *ledger.Ledger + +// getLedger gets a copy of the device, and caches it +func getLedger() (*ledger.Ledger, error) { + var err error + if device == nil { + device, err = ledger.FindLedger() + } + return device, err +} + +func signLedger(device *ledger.Ledger, msg []byte) (pub PubKey, sig Signature, err error) { + bsig, err := device.Sign(msg) + if err != nil { + return pub, sig, err + } + key, err := device.GetPublicKey() + if err != nil { + return pub, sig, err + } + var p PubKeySecp256k1 + copy(p[:], key) + return p, SignatureSecp256k1FromBytes(bsig), nil +} + +// PrivKeyLedgerSecp256k1 implements PrivKey, calling the ledger nano +// we cache the PubKey from the first call to use it later +type PrivKeyLedgerSecp256k1 struct { + // PubKey should be private, but we want to encode it via go-amino + // so we can view the address later, even without having the ledger + // attached + CachedPubKey PubKey +} + +// NewPrivKeyLedgerSecp256k1 will generate a new key and store the +// public key for later use. +func NewPrivKeyLedgerSecp256k1() (PrivKey, error) { + var pk PrivKeyLedgerSecp256k1 + // getPubKey will cache the pubkey for later use, + // this allows us to return an error early if the ledger + // is not plugged in + _, err := pk.getPubKey() + return &pk, err +} + +// ValidateKey allows us to verify the sanity of a key +// after loading it from disk +func (pk PrivKeyLedgerSecp256k1) ValidateKey() error { + // getPubKey will return an error if the ledger is not + // properly set up... + pub, err := pk.forceGetPubKey() + if err != nil { + return err + } + // verify this matches cached address + if !pub.Equals(pk.CachedPubKey) { + return errors.New("ledger doesn't match cached key") + } + return nil +} + +// AssertIsPrivKeyInner fulfils PrivKey Interface +func (pk *PrivKeyLedgerSecp256k1) AssertIsPrivKeyInner() {} + +// Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify +// the same key when we reconnect to a ledger +func (pk PrivKeyLedgerSecp256k1) Bytes() []byte { + bin, err := cdc.MarshalBinaryBare(pk) + if err != nil { + panic(err) + } + return bin +} + +// Sign calls the ledger and stores the PubKey for future use +// +// XXX/TODO: panics if there is an error communicating with the ledger. +// +// Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, +// returning an error, so this should only trigger if the privkey is held +// in memory for a while before use. +func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) Signature { + // oh, I wish there was better error handling + dev, err := getLedger() + if err != nil { + panic(err) + } + + pub, sig, err := signLedger(dev, msg) + if err != nil { + panic(err) + } + + // if we have no pubkey yet, store it for future queries + if pk.CachedPubKey == nil { + pk.CachedPubKey = pub + } else if !pk.CachedPubKey.Equals(pub) { + panic("signed with a different key than stored") + } + return sig +} + +// PubKey returns the stored PubKey +// TODO: query the ledger if not there, once it is not volatile +func (pk PrivKeyLedgerSecp256k1) PubKey() PubKey { + key, err := pk.getPubKey() + if err != nil { + panic(err) + } + return key +} + +// getPubKey reads the pubkey from cache or from the ledger itself +// since this involves IO, it may return an error, which is not exposed +// in the PubKey interface, so this function allows better error handling +func (pk PrivKeyLedgerSecp256k1) getPubKey() (key PubKey, err error) { + // if we have no pubkey, set it + if pk.CachedPubKey == nil { + pk.CachedPubKey, err = pk.forceGetPubKey() + } + return pk.CachedPubKey, err +} + +// forceGetPubKey is like getPubKey but ignores any cached key +// and ensures we get it from the ledger itself. +func (pk PrivKeyLedgerSecp256k1) forceGetPubKey() (key PubKey, err error) { + dev, err := getLedger() + if err != nil { + return key, errors.New("Can't connect to ledger device") + } + key, _, err = signLedger(dev, []byte{0}) + if err != nil { + return key, errors.New("Please open cosmos app on the ledger") + } + return key, err +} + +// Equals fulfils PrivKey Interface - makes sure both keys refer to the +// same +func (pk PrivKeyLedgerSecp256k1) Equals(other PrivKey) bool { + if ledger, ok := other.(*PrivKeyLedgerSecp256k1); ok { + return pk.CachedPubKey.Equals(ledger.CachedPubKey) + } + return false +} diff --git a/ledger_test.go b/ledger_test.go new file mode 100644 index 000000000..848c2cece --- /dev/null +++ b/ledger_test.go @@ -0,0 +1,72 @@ +package crypto + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestRealLedger(t *testing.T) { + + if os.Getenv("WITH_LEDGER") == "" { + t.Skip("Set WITH_LEDGER to run code on real ledger") + } + msg := []byte("kuhehfeohg") + + priv, err := NewPrivKeyLedgerSecp256k1() + require.Nil(t, err, "%+v", err) + pub := priv.PubKey() + sig := priv.Sign(msg) + + valid := pub.VerifyBytes(msg, sig) + assert.True(t, valid) + + // now, let's serialize the key and make sure it still works + bs := priv.Bytes() + priv2, err := PrivKeyFromBytes(bs) + require.Nil(t, err, "%+v", err) + + // make sure we get the same pubkey when we load from disk + pub2 := priv2.PubKey() + require.Equal(t, pub, pub2) + + // signing with the loaded key should match the original pubkey + sig = priv2.Sign(msg) + valid = pub.VerifyBytes(msg, sig) + assert.True(t, valid) + + // make sure pubkeys serialize properly as well + bs = pub.Bytes() + bpub, err := PubKeyFromBytes(bs) + require.NoError(t, err) + assert.Equal(t, pub, bpub) +} + +// TestRealLedgerErrorHandling calls. These tests assume +// the ledger is not plugged in.... +func TestRealLedgerErrorHandling(t *testing.T) { + if os.Getenv("WITH_LEDGER") != "" { + t.Skip("Skipping on WITH_LEDGER as it tests unplugged cases") + } + + // first, try to generate a key, must return an error + // (no panic) + _, err := NewPrivKeyLedgerSecp256k1() + require.Error(t, err) + + led := PrivKeyLedgerSecp256k1{} // empty + // or with some pub key + ed := GenPrivKeySecp256k1() + led2 := PrivKeyLedgerSecp256k1{CachedPubKey: ed.PubKey()} + + // loading these should return errors + bs := led.Bytes() + _, err = PrivKeyFromBytes(bs) + require.Error(t, err) + + bs = led2.Bytes() + _, err = PrivKeyFromBytes(bs) + require.Error(t, err) +} diff --git a/signature.go b/signature.go index cfe927137..8bf151b41 100644 --- a/signature.go +++ b/signature.go @@ -79,3 +79,9 @@ func (sig SignatureSecp256k1) Equals(other Signature) bool { return false } } + +func SignatureSecp256k1FromBytes(data []byte) Signature { + var sig SignatureSecp256k1 + copy(sig[:], data) + return sig +} From 065c3943b1918e9bcbd55ede1df3ee6392552d41 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 30 Apr 2018 16:49:11 +0200 Subject: [PATCH 227/273] Fix no-Ledger testcase --- ledger_test.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/ledger_test.go b/ledger_test.go index 848c2cece..7b2b4ea1e 100644 --- a/ledger_test.go +++ b/ledger_test.go @@ -55,18 +55,4 @@ func TestRealLedgerErrorHandling(t *testing.T) { // (no panic) _, err := NewPrivKeyLedgerSecp256k1() require.Error(t, err) - - led := PrivKeyLedgerSecp256k1{} // empty - // or with some pub key - ed := GenPrivKeySecp256k1() - led2 := PrivKeyLedgerSecp256k1{CachedPubKey: ed.PubKey()} - - // loading these should return errors - bs := led.Bytes() - _, err = PrivKeyFromBytes(bs) - require.Error(t, err) - - bs = led2.Bytes() - _, err = PrivKeyFromBytes(bs) - require.Error(t, err) } From e25a64fdf1e4aae53ad5e2780d0b4cc56eedaae6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 30 Apr 2018 19:34:19 +0200 Subject: [PATCH 228/273] Fix testcases, all looks OK --- ledger.go | 9 ++++++--- signature.go | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ledger.go b/ledger.go index 0fe4b7d39..b2b06415d 100644 --- a/ledger.go +++ b/ledger.go @@ -3,7 +3,7 @@ package crypto import ( "github.com/pkg/errors" - // secp256k1 "github.com/btcsuite/btcd/btcec" + secp256k1 "github.com/btcsuite/btcd/btcec" ledger "github.com/zondax/ledger-goclient" ) @@ -23,13 +23,16 @@ func signLedger(device *ledger.Ledger, msg []byte) (pub PubKey, sig Signature, e if err != nil { return pub, sig, err } + sig = SignatureSecp256k1FromBytes(bsig) key, err := device.GetPublicKey() if err != nil { return pub, sig, err } var p PubKeySecp256k1 - copy(p[:], key) - return p, SignatureSecp256k1FromBytes(bsig), nil + // Reserialize in the 33-byte compressed format + cmp, err := secp256k1.ParsePubKey(key[:], secp256k1.S256()) + copy(p[:], cmp.SerializeCompressed()) + return p, sig, nil } // PrivKeyLedgerSecp256k1 implements PrivKey, calling the ledger nano diff --git a/signature.go b/signature.go index 8bf151b41..a364dc7fb 100644 --- a/signature.go +++ b/signature.go @@ -81,7 +81,7 @@ func (sig SignatureSecp256k1) Equals(other Signature) bool { } func SignatureSecp256k1FromBytes(data []byte) Signature { - var sig SignatureSecp256k1 + sig := make(SignatureSecp256k1, len(data)) copy(sig[:], data) return sig } From 391936b7346a116053b301fd6c74ace17eac4d75 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 2 May 2018 17:10:32 +0200 Subject: [PATCH 229/273] Prevent unnecessary signatures, improve error messages --- ledger.go | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/ledger.go b/ledger.go index b2b06415d..18fdf478e 100644 --- a/ledger.go +++ b/ledger.go @@ -18,21 +18,25 @@ func getLedger() (*ledger.Ledger, error) { return device, err } -func signLedger(device *ledger.Ledger, msg []byte) (pub PubKey, sig Signature, err error) { - bsig, err := device.Sign(msg) - if err != nil { - return pub, sig, err - } - sig = SignatureSecp256k1FromBytes(bsig) +func pubkeyLedger(device *ledger.Ledger) (pub PubKey, err error) { key, err := device.GetPublicKey() if err != nil { - return pub, sig, err + return pub, err } var p PubKeySecp256k1 // Reserialize in the 33-byte compressed format cmp, err := secp256k1.ParsePubKey(key[:], secp256k1.S256()) copy(p[:], cmp.SerializeCompressed()) - return p, sig, nil + return pub, err +} + +func signLedger(device *ledger.Ledger, msg []byte) (sig Signature, err error) { + bsig, err := device.Sign(msg) + if err != nil { + return sig, err + } + sig = SignatureSecp256k1FromBytes(bsig) + return sig, nil } // PrivKeyLedgerSecp256k1 implements PrivKey, calling the ledger nano @@ -66,7 +70,7 @@ func (pk PrivKeyLedgerSecp256k1) ValidateKey() error { } // verify this matches cached address if !pub.Equals(pk.CachedPubKey) { - return errors.New("ledger doesn't match cached key") + return errors.New("Cached key does not match retrieved key") } return nil } @@ -98,7 +102,12 @@ func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) Signature { panic(err) } - pub, sig, err := signLedger(dev, msg) + sig, err := signLedger(dev, msg) + if err != nil { + panic(err) + } + + pub, err := pubkeyLedger(dev) if err != nil { panic(err) } @@ -107,7 +116,7 @@ func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) Signature { if pk.CachedPubKey == nil { pk.CachedPubKey = pub } else if !pk.CachedPubKey.Equals(pub) { - panic("signed with a different key than stored") + panic("Stored key does not match signing key") } return sig } @@ -138,11 +147,11 @@ func (pk PrivKeyLedgerSecp256k1) getPubKey() (key PubKey, err error) { func (pk PrivKeyLedgerSecp256k1) forceGetPubKey() (key PubKey, err error) { dev, err := getLedger() if err != nil { - return key, errors.New("Can't connect to ledger device") + return key, errors.New("Cannot connect to Ledger device") } - key, _, err = signLedger(dev, []byte{0}) + key, err = pubkeyLedger(dev) if err != nil { - return key, errors.New("Please open cosmos app on the ledger") + return key, errors.New("Please open Cosmos app on the Ledger device") } return key, err } From 86b09b0cd7c3a7b6a4ce825564ede75a80d5605b Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 3 May 2018 06:26:58 +0200 Subject: [PATCH 230/273] Bugfix --- ledger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ledger.go b/ledger.go index 18fdf478e..4effa2590 100644 --- a/ledger.go +++ b/ledger.go @@ -27,7 +27,7 @@ func pubkeyLedger(device *ledger.Ledger) (pub PubKey, err error) { // Reserialize in the 33-byte compressed format cmp, err := secp256k1.ParsePubKey(key[:], secp256k1.S256()) copy(p[:], cmp.SerializeCompressed()) - return pub, err + return p, err } func signLedger(device *ledger.Ledger, msg []byte) (sig Signature, err error) { From 49e03fb481075d3f8d601dfc73e9f34ff8edd9d6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 10 May 2018 01:41:15 +0200 Subject: [PATCH 231/273] Update dependency versions --- Gopkg.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index fbfaa63fa..3e44587e1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -11,7 +11,7 @@ branch = "master" name = "github.com/btcsuite/btcd" packages = ["btcec"] - revision = "2be2f12b358dc57d70b8f501b00be450192efbc3" + revision = "675abc5df3c5531bc741b56a765e35623459da6d" [[projects]] branch = "master" @@ -119,7 +119,7 @@ "leveldb/table", "leveldb/util" ] - revision = "714f901b98fdb3aa954b4193d8cbd64a28d80cad" + revision = "ae970a0732be3a1f5311da86118d37b9f4bd2a5a" [[projects]] branch = "master" @@ -134,8 +134,8 @@ [[projects]] name = "github.com/tendermint/go-amino" packages = ["."] - revision = "42246108ff925a457fb709475070a03dfd3e2b5c" - version = "0.9.6" + revision = "ed62928576cfcaf887209dc96142cd79cdfff389" + version = "0.9.9" [[projects]] name = "github.com/tendermint/tmlibs" @@ -144,8 +144,8 @@ "db", "log" ] - revision = "2e24b64fc121dcdf1cabceab8dc2f7257675483c" - version = "v0.8.1" + revision = "d94e312673e16a11ea55d742cefb3e331228f898" + version = "v0.8.2" [[projects]] branch = "master" @@ -157,7 +157,7 @@ branch = "master" name = "github.com/zondax/ledger-goclient" packages = ["."] - revision = "0eb48e14b06efd0354c2e0e18f15db121c64b9b8" + revision = "a242cfad962597a588288f99fa3425a01a820295" [[projects]] branch = "master" @@ -173,7 +173,7 @@ "ripemd160", "salsa20/salsa" ] - revision = "b2aa35443fbc700ab74c586ae79b81c171851023" + revision = "2d027ae1dddd4694d54f7a8b6cbe78dca8720226" [solve-meta] analyzer-name = "dep" From 337ad8e594d31a16449cf2756ed33ba959ea3964 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 10 May 2018 02:03:28 +0200 Subject: [PATCH 232/273] Update to new Ledger API in progress --- ledger.go | 19 +++++++++++-------- ledger_test.go | 7 +++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ledger.go b/ledger.go index 4effa2590..d44b2dab9 100644 --- a/ledger.go +++ b/ledger.go @@ -9,6 +9,8 @@ import ( var device *ledger.Ledger +type DerivationPath = []uint32 + // getLedger gets a copy of the device, and caches it func getLedger() (*ledger.Ledger, error) { var err error @@ -18,8 +20,8 @@ func getLedger() (*ledger.Ledger, error) { return device, err } -func pubkeyLedger(device *ledger.Ledger) (pub PubKey, err error) { - key, err := device.GetPublicKey() +func pubkeyLedger(device *ledger.Ledger, path DerivationPath) (pub PubKey, err error) { + key, err := device.GetPublicKeySECP256K1(path) if err != nil { return pub, err } @@ -30,8 +32,8 @@ func pubkeyLedger(device *ledger.Ledger) (pub PubKey, err error) { return p, err } -func signLedger(device *ledger.Ledger, msg []byte) (sig Signature, err error) { - bsig, err := device.Sign(msg) +func signLedger(device *ledger.Ledger, path DerivationPath, msg []byte) (sig Signature, err error) { + bsig, err := device.SignSECP256K1(path, msg) if err != nil { return sig, err } @@ -46,11 +48,12 @@ type PrivKeyLedgerSecp256k1 struct { // so we can view the address later, even without having the ledger // attached CachedPubKey PubKey + Path DerivationPath } // NewPrivKeyLedgerSecp256k1 will generate a new key and store the // public key for later use. -func NewPrivKeyLedgerSecp256k1() (PrivKey, error) { +func NewPrivKeyLedgerSecp256k1(path DerivationPath) (PrivKey, error) { var pk PrivKeyLedgerSecp256k1 // getPubKey will cache the pubkey for later use, // this allows us to return an error early if the ledger @@ -102,12 +105,12 @@ func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) Signature { panic(err) } - sig, err := signLedger(dev, msg) + sig, err := signLedger(dev, pk.Path, msg) if err != nil { panic(err) } - pub, err := pubkeyLedger(dev) + pub, err := pubkeyLedger(dev, pk.Path) if err != nil { panic(err) } @@ -149,7 +152,7 @@ func (pk PrivKeyLedgerSecp256k1) forceGetPubKey() (key PubKey, err error) { if err != nil { return key, errors.New("Cannot connect to Ledger device") } - key, err = pubkeyLedger(dev) + key, err = pubkeyLedger(dev, pk.Path) if err != nil { return key, errors.New("Please open Cosmos app on the Ledger device") } diff --git a/ledger_test.go b/ledger_test.go index 7b2b4ea1e..1c193b5f1 100644 --- a/ledger_test.go +++ b/ledger_test.go @@ -15,7 +15,9 @@ func TestRealLedger(t *testing.T) { } msg := []byte("kuhehfeohg") - priv, err := NewPrivKeyLedgerSecp256k1() + path := DerivationPath{44, 60, 0, 0, 0} + + priv, err := NewPrivKeyLedgerSecp256k1(path) require.Nil(t, err, "%+v", err) pub := priv.PubKey() sig := priv.Sign(msg) @@ -53,6 +55,7 @@ func TestRealLedgerErrorHandling(t *testing.T) { // first, try to generate a key, must return an error // (no panic) - _, err := NewPrivKeyLedgerSecp256k1() + path := DerivationPath{44, 60, 0, 0, 0} + _, err := NewPrivKeyLedgerSecp256k1(path) require.Error(t, err) } From e6d0ade0e1a8315613e026fe64b006f24f58beab Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 14 May 2018 15:33:10 +0200 Subject: [PATCH 233/273] Update to latest upstream, debugging information --- Gopkg.lock | 6 +++--- ledger.go | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 3e44587e1..d65f87b68 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -119,7 +119,7 @@ "leveldb/table", "leveldb/util" ] - revision = "ae970a0732be3a1f5311da86118d37b9f4bd2a5a" + revision = "9637fa0b2f0db13c99d899b91007edb7df4610b7" [[projects]] branch = "master" @@ -157,7 +157,7 @@ branch = "master" name = "github.com/zondax/ledger-goclient" packages = ["."] - revision = "a242cfad962597a588288f99fa3425a01a820295" + revision = "5b2fe84d3139027c29bd8f0c054ed9444f8a7622" [[projects]] branch = "master" @@ -173,7 +173,7 @@ "ripemd160", "salsa20/salsa" ] - revision = "2d027ae1dddd4694d54f7a8b6cbe78dca8720226" + revision = "034e5325b6ab92faa14d15c30e86919e911cf8e0" [solve-meta] analyzer-name = "dep" diff --git a/ledger.go b/ledger.go index d44b2dab9..a9bc1d975 100644 --- a/ledger.go +++ b/ledger.go @@ -1,6 +1,7 @@ package crypto import ( + "fmt" "github.com/pkg/errors" secp256k1 "github.com/btcsuite/btcd/btcec" @@ -23,7 +24,7 @@ func getLedger() (*ledger.Ledger, error) { func pubkeyLedger(device *ledger.Ledger, path DerivationPath) (pub PubKey, err error) { key, err := device.GetPublicKeySECP256K1(path) if err != nil { - return pub, err + return pub, fmt.Errorf("Error fetching public key: %v", err) } var p PubKeySecp256k1 // Reserialize in the 33-byte compressed format @@ -55,6 +56,7 @@ type PrivKeyLedgerSecp256k1 struct { // public key for later use. func NewPrivKeyLedgerSecp256k1(path DerivationPath) (PrivKey, error) { var pk PrivKeyLedgerSecp256k1 + pk.Path = path // getPubKey will cache the pubkey for later use, // this allows us to return an error early if the ledger // is not plugged in @@ -150,11 +152,11 @@ func (pk PrivKeyLedgerSecp256k1) getPubKey() (key PubKey, err error) { func (pk PrivKeyLedgerSecp256k1) forceGetPubKey() (key PubKey, err error) { dev, err := getLedger() if err != nil { - return key, errors.New("Cannot connect to Ledger device") + return key, errors.New(fmt.Sprintf("Cannot connect to Ledger device - error: %v", err)) } key, err = pubkeyLedger(dev, pk.Path) if err != nil { - return key, errors.New("Please open Cosmos app on the Ledger device") + return key, errors.New(fmt.Sprintf("Please open Cosmos app on the Ledger device - error: %v", err)) } return key, err } From aa2b6b546f85a625fd06f511421d36b2f579fa3e Mon Sep 17 00:00:00 2001 From: Liamsi Date: Tue, 15 May 2018 11:39:48 +0100 Subject: [PATCH 234/273] Remove outdated non-building code in _nano --- _nano/keys.go | 294 --------------------------------------------- _nano/keys_test.go | 142 ---------------------- _nano/sign.go | 63 ---------- _nano/sign_test.go | 160 ------------------------ 4 files changed, 659 deletions(-) delete mode 100644 _nano/keys.go delete mode 100644 _nano/keys_test.go delete mode 100644 _nano/sign.go delete mode 100644 _nano/sign_test.go diff --git a/_nano/keys.go b/_nano/keys.go deleted file mode 100644 index 8cf1c3721..000000000 --- a/_nano/keys.go +++ /dev/null @@ -1,294 +0,0 @@ -package nano - -import ( - "bytes" - "encoding/hex" - - "github.com/pkg/errors" - - ledger "github.com/ethanfrey/ledger" - - crypto "github.com/tendermint/go-crypto" - amino "github.com/tendermint/go-amino" -) - -//nolint -const ( - NameLedgerEd25519 = "ledger-ed25519" - TypeLedgerEd25519 = 0x10 - - // Timeout is the number of seconds to wait for a response from the ledger - // if eg. waiting for user confirmation on button push - Timeout = 20 -) - -var device *ledger.Ledger - -// getLedger gets a copy of the device, and caches it -func getLedger() (*ledger.Ledger, error) { - var err error - if device == nil { - device, err = ledger.FindLedger() - } - return device, err -} - -func signLedger(device *ledger.Ledger, msg []byte) (pub crypto.PubKey, sig crypto.Signature, err error) { - var resp []byte - - packets := generateSignRequests(msg) - for _, pack := range packets { - resp, err = device.Exchange(pack, Timeout) - if err != nil { - return pub, sig, err - } - } - - // the last call is the result we want and needs to be parsed - key, bsig, err := parseDigest(resp) - if err != nil { - return pub, sig, err - } - - var b [32]byte - copy(b[:], key) - return PubKeyLedgerEd25519FromBytes(b), crypto.SignatureEd25519FromBytes(bsig), nil -} - -// PrivKeyLedgerEd25519 implements PrivKey, calling the ledger nano -// we cache the PubKey from the first call to use it later -type PrivKeyLedgerEd25519 struct { - // PubKey should be private, but we want to encode it via go-amino - // so we can view the address later, even without having the ledger - // attached - CachedPubKey crypto.PubKey -} - -// NewPrivKeyLedgerEd25519 will generate a new key and store the -// public key for later use. -func NewPrivKeyLedgerEd25519() (crypto.PrivKey, error) { - var pk PrivKeyLedgerEd25519 - // getPubKey will cache the pubkey for later use, - // this allows us to return an error early if the ledger - // is not plugged in - _, err := pk.getPubKey() - return pk.Wrap(), err -} - -// ValidateKey allows us to verify the sanity of a key -// after loading it from disk -func (pk *PrivKeyLedgerEd25519) ValidateKey() error { - // getPubKey will return an error if the ledger is not - // properly set up... - pub, err := pk.forceGetPubKey() - if err != nil { - return err - } - // verify this matches cached address - if !pub.Equals(pk.CachedPubKey) { - return errors.New("ledger doesn't match cached key") - } - return nil -} - -// AssertIsPrivKeyInner fulfils PrivKey Interface -func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} - -// Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify -// the same key when we reconnect to a ledger -func (pk *PrivKeyLedgerEd25519) Bytes() []byte { - return amino.BinaryBytes(pk.Wrap()) -} - -// Sign calls the ledger and stores the PubKey for future use -// -// XXX/TODO: panics if there is an error communicating with the ledger. -// -// Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, -// returning an error, so this should only trigger if the privkey is held -// in memory for a while before use. -func (pk *PrivKeyLedgerEd25519) Sign(msg []byte) crypto.Signature { - // oh, I wish there was better error handling - dev, err := getLedger() - if err != nil { - panic(err) - } - - pub, sig, err := signLedger(dev, msg) - if err != nil { - panic(err) - } - - // if we have no pubkey yet, store it for future queries - if pk.CachedPubKey.Empty() { - pk.CachedPubKey = pub - } else if !pk.CachedPubKey.Equals(pub) { - panic("signed with a different key than stored") - } - return sig -} - -// PubKey returns the stored PubKey -// TODO: query the ledger if not there, once it is not volatile -func (pk *PrivKeyLedgerEd25519) PubKey() crypto.PubKey { - key, err := pk.getPubKey() - if err != nil { - panic(err) - } - return key -} - -// getPubKey reads the pubkey from cache or from the ledger itself -// since this involves IO, it may return an error, which is not exposed -// in the PubKey interface, so this function allows better error handling -func (pk *PrivKeyLedgerEd25519) getPubKey() (key crypto.PubKey, err error) { - // if we have no pubkey, set it - if pk.CachedPubKey.Empty() { - pk.CachedPubKey, err = pk.forceGetPubKey() - } - return pk.CachedPubKey, err -} - -// forceGetPubKey is like getPubKey but ignores any cached key -// and ensures we get it from the ledger itself. -func (pk *PrivKeyLedgerEd25519) forceGetPubKey() (key crypto.PubKey, err error) { - dev, err := getLedger() - if err != nil { - return key, errors.New("Can't connect to ledger device") - } - key, _, err = signLedger(dev, []byte{0}) - if err != nil { - return key, errors.New("Please open cosmos app on the ledger") - } - return key, err -} - -// Equals fulfils PrivKey Interface - makes sure both keys refer to the -// same -func (pk *PrivKeyLedgerEd25519) Equals(other crypto.PrivKey) bool { - if ledger, ok := other.Unwrap().(*PrivKeyLedgerEd25519); ok { - return pk.CachedPubKey.Equals(ledger.CachedPubKey) - } - return false -} - -// MockPrivKeyLedgerEd25519 behaves as the ledger, but stores a pre-packaged call-response -// for use in test cases -type MockPrivKeyLedgerEd25519 struct { - Msg []byte - Pub [KeyLength]byte - Sig [SigLength]byte -} - -// NewMockKey returns -func NewMockKey(msg, pubkey, sig string) (pk MockPrivKeyLedgerEd25519) { - var err error - pk.Msg, err = hex.DecodeString(msg) - if err != nil { - panic(err) - } - - bpk, err := hex.DecodeString(pubkey) - if err != nil { - panic(err) - } - bsig, err := hex.DecodeString(sig) - if err != nil { - panic(err) - } - - copy(pk.Pub[:], bpk) - copy(pk.Sig[:], bsig) - return pk -} - -var _ crypto.PrivKeyInner = MockPrivKeyLedgerEd25519{} - -// AssertIsPrivKeyInner fulfils PrivKey Interface -func (pk MockPrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} - -// Bytes fulfils PrivKey Interface - not supported -func (pk MockPrivKeyLedgerEd25519) Bytes() []byte { - return nil -} - -// Sign returns a real SignatureLedger, if the msg matches what we expect -func (pk MockPrivKeyLedgerEd25519) Sign(msg []byte) crypto.Signature { - if !bytes.Equal(pk.Msg, msg) { - panic("Mock key is for different msg") - } - return crypto.SignatureEd25519(pk.Sig).Wrap() -} - -// PubKey returns a real PubKeyLedgerEd25519, that will verify this signature -func (pk MockPrivKeyLedgerEd25519) PubKey() crypto.PubKey { - return PubKeyLedgerEd25519FromBytes(pk.Pub) -} - -// Equals compares that two Mocks have the same data -func (pk MockPrivKeyLedgerEd25519) Equals(other crypto.PrivKey) bool { - if mock, ok := other.Unwrap().(MockPrivKeyLedgerEd25519); ok { - return bytes.Equal(mock.Pub[:], pk.Pub[:]) && - bytes.Equal(mock.Sig[:], pk.Sig[:]) && - bytes.Equal(mock.Msg, pk.Msg) - } - return false -} - -//////////////////////////////////////////// -// pubkey - -// PubKeyLedgerEd25519 works like a normal Ed25519 except a hash before the verify bytes -type PubKeyLedgerEd25519 struct { - crypto.PubKeyEd25519 -} - -// PubKeyLedgerEd25519FromBytes creates a PubKey from the raw bytes -func PubKeyLedgerEd25519FromBytes(key [32]byte) crypto.PubKey { - return PubKeyLedgerEd25519{crypto.PubKeyEd25519(key)}.Wrap() -} - -// Bytes fulfils pk Interface - no data, just type info -func (pk PubKeyLedgerEd25519) Bytes() []byte { - return amino.BinaryBytes(pk.Wrap()) -} - -// VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand -func (pk PubKeyLedgerEd25519) VerifyBytes(msg []byte, sig crypto.Signature) bool { - hmsg := hashMsg(msg) - return pk.PubKeyEd25519.VerifyBytes(hmsg, sig) -} - -// Equals implements PubKey interface -func (pk PubKeyLedgerEd25519) Equals(other crypto.PubKey) bool { - if ledger, ok := other.Unwrap().(PubKeyLedgerEd25519); ok { - return pk.PubKeyEd25519.Equals(ledger.PubKeyEd25519.Wrap()) - } - return false -} - -/*** registration with go-data ***/ - -func init() { - crypto.PrivKeyMapper. - RegisterImplementation(&PrivKeyLedgerEd25519{}, NameLedgerEd25519, TypeLedgerEd25519). - RegisterImplementation(MockPrivKeyLedgerEd25519{}, "mock-ledger", 0x11) - - crypto.PubKeyMapper. - RegisterImplementation(PubKeyLedgerEd25519{}, NameLedgerEd25519, TypeLedgerEd25519) -} - -// Wrap fulfils interface for PrivKey struct -func (pk *PrivKeyLedgerEd25519) Wrap() crypto.PrivKey { - return crypto.PrivKey{PrivKeyInner: pk} -} - -// Wrap fulfils interface for PrivKey struct -func (pk MockPrivKeyLedgerEd25519) Wrap() crypto.PrivKey { - return crypto.PrivKey{PrivKeyInner: pk} -} - -// Wrap fulfils interface for PubKey struct -func (pk PubKeyLedgerEd25519) Wrap() crypto.PubKey { - return crypto.PubKey{PubKeyInner: pk} -} diff --git a/_nano/keys_test.go b/_nano/keys_test.go deleted file mode 100644 index fda096e29..000000000 --- a/_nano/keys_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package nano - -import ( - "encoding/hex" - "os" - "testing" - - asrt "github.com/stretchr/testify/assert" - rqr "github.com/stretchr/testify/require" - - crypto "github.com/tendermint/go-crypto" -) - -func TestLedgerKeys(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - cases := []struct { - msg, pubkey, sig string - valid bool - }{ - 0: { - msg: "F00D", - pubkey: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", - sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", - valid: true, - }, - 1: { - msg: "DEADBEEF", - pubkey: "0C45ADC887A5463F668533443C829ED13EA8E2E890C778957DC28DB9D2AD5A6C", - sig: "00ED74EED8FDAC7988A14BF6BC222120CBAC249D569AF4C2ADABFC86B792F97DF73C4919BE4B6B0ACB53547273BF29FBF0A9E0992FFAB6CB6C9B09311FC86A00", - valid: true, - }, - 2: { - msg: "1234567890AA", - pubkey: "598FC1F0C76363D14D7480736DEEF390D85863360F075792A6975EFA149FD7EA", - sig: "59AAB7D7BDC4F936B6415DE672A8B77FA6B8B3451CD95B3A631F31F9A05DAEEE5E7E4F89B64DDEBB5F63DC042CA13B8FCB8185F82AD7FD5636FFDA6B0DC9570B", - valid: true, - }, - 3: { - msg: "1234432112344321", - pubkey: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: true, - }, - 4: { - msg: "12344321123443", - pubkey: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - 5: { - msg: "1234432112344321", - pubkey: "459E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - 6: { - msg: "1234432112344321", - pubkey: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "716B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - } - - for i, tc := range cases { - bmsg, err := hex.DecodeString(tc.msg) - require.NoError(err, "%d", i) - - priv := NewMockKey(tc.msg, tc.pubkey, tc.sig) - pub := priv.PubKey() - sig := priv.Sign(bmsg) - - valid := pub.VerifyBytes(bmsg, sig) - assert.Equal(tc.valid, valid, "%d", i) - } -} - -func TestRealLedger(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - if os.Getenv("WITH_LEDGER") == "" { - t.Skip("Set WITH_LEDGER to run code on real ledger") - } - msg := []byte("kuhehfeohg") - - priv, err := NewPrivKeyLedgerEd25519() - require.Nil(err, "%+v", err) - pub := priv.PubKey() - sig := priv.Sign(msg) - - valid := pub.VerifyBytes(msg, sig) - assert.True(valid) - - // now, let's serialize the key and make sure it still works - bs := priv.Bytes() - priv2, err := crypto.PrivKeyFromBytes(bs) - require.Nil(err, "%+v", err) - - // make sure we get the same pubkey when we load from disk - pub2 := priv2.PubKey() - require.Equal(pub, pub2) - - // signing with the loaded key should match the original pubkey - sig = priv2.Sign(msg) - valid = pub.VerifyBytes(msg, sig) - assert.True(valid) - - // make sure pubkeys serialize properly as well - bs = pub.Bytes() - bpub, err := crypto.PubKeyFromBytes(bs) - require.NoError(err) - assert.Equal(pub, bpub) -} - -// TestRealLedgerErrorHandling calls. These tests assume -// the ledger is not plugged in.... -func TestRealLedgerErrorHandling(t *testing.T) { - require := rqr.New(t) - - if os.Getenv("WITH_LEDGER") != "" { - t.Skip("Skipping on WITH_LEDGER as it tests unplugged cases") - } - - // first, try to generate a key, must return an error - // (no panic) - _, err := NewPrivKeyLedgerEd25519() - require.Error(err) - - led := PrivKeyLedgerEd25519{} // empty - // or with some pub key - ed := crypto.GenPrivKeyEd25519() - led2 := PrivKeyLedgerEd25519{CachedPubKey: ed.PubKey()} - - // loading these should return errors - bs := led.Bytes() - _, err = crypto.PrivKeyFromBytes(bs) - require.Error(err) - - bs = led2.Bytes() - _, err = crypto.PrivKeyFromBytes(bs) - require.Error(err) -} diff --git a/_nano/sign.go b/_nano/sign.go deleted file mode 100644 index c40801583..000000000 --- a/_nano/sign.go +++ /dev/null @@ -1,63 +0,0 @@ -package nano - -import ( - "bytes" - "crypto/sha512" - - "github.com/pkg/errors" -) - -const ( - App = 0x80 - Init = 0x00 - Update = 0x01 - Digest = 0x02 - MaxChunk = 253 - KeyLength = 32 - SigLength = 64 -) - -var separator = []byte{0, 0xCA, 0xFE, 0} - -func generateSignRequests(payload []byte) [][]byte { - // nice one-shot - digest := []byte{App, Digest} - if len(payload) < MaxChunk { - return [][]byte{append(digest, payload...)} - } - - // large payload is multi-chunk - result := [][]byte{{App, Init}} - update := []byte{App, Update} - for len(payload) > MaxChunk { - msg := append(update, payload[:MaxChunk]...) - payload = payload[MaxChunk:] - result = append(result, msg) - } - result = append(result, append(update, payload...)) - result = append(result, digest) - return result -} - -func parseDigest(resp []byte) (key, sig []byte, err error) { - if resp[0] != App || resp[1] != Digest { - return nil, nil, errors.New("Invalid header") - } - resp = resp[2:] - if len(resp) != KeyLength+SigLength+len(separator) { - return nil, nil, errors.Errorf("Incorrect length: %d", len(resp)) - } - - key, resp = resp[:KeyLength], resp[KeyLength:] - if !bytes.Equal(separator, resp[:len(separator)]) { - return nil, nil, errors.New("Cannot find 0xCAFE") - } - - sig = resp[len(separator):] - return key, sig, nil -} - -func hashMsg(data []byte) []byte { - res := sha512.Sum512(data) - return res[:] -} diff --git a/_nano/sign_test.go b/_nano/sign_test.go deleted file mode 100644 index 18e4e0d0b..000000000 --- a/_nano/sign_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package nano - -import ( - "encoding/hex" - "testing" - - "github.com/pkg/errors" - asrt "github.com/stretchr/testify/assert" - rqr "github.com/stretchr/testify/require" - - crypto "github.com/tendermint/go-crypto" -) - -func parseEdKey(data []byte) (key crypto.PubKey, err error) { - ed := crypto.PubKeyEd25519{} - if len(data) < len(ed) { - return key, errors.Errorf("Key length too short: %d", len(data)) - } - copy(ed[:], data) - return ed.Wrap(), nil -} - -func parseSig(data []byte) (key crypto.Signature, err error) { - ed := crypto.SignatureEd25519{} - if len(data) < len(ed) { - return key, errors.Errorf("Sig length too short: %d", len(data)) - } - copy(ed[:], data) - return ed.Wrap(), nil -} - -func TestParseDigest(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - cases := []struct { - output string - key string - sig string - valid bool - }{ - { - output: "80028E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C9300CAFE00787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", - key: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", - sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", - valid: true, - }, - { - output: "800235467890876543525437890796574535467890", - key: "", - sig: "", - valid: false, - }, - } - - for i, tc := range cases { - msg, err := hex.DecodeString(tc.output) - require.Nil(err, "%d: %+v", i, err) - - lKey, lSig, err := parseDigest(msg) - if !tc.valid { - assert.NotNil(err, "%d", i) - } else if assert.Nil(err, "%d: %+v", i, err) { - key, err := hex.DecodeString(tc.key) - require.Nil(err, "%d: %+v", i, err) - sig, err := hex.DecodeString(tc.sig) - require.Nil(err, "%d: %+v", i, err) - - assert.Equal(key, lKey, "%d", i) - assert.Equal(sig, lSig, "%d", i) - } - } -} - -type cryptoCase struct { - msg string - key string - sig string - valid bool -} - -func toBytes(c cryptoCase) (msg, key, sig []byte, err error) { - msg, err = hex.DecodeString(c.msg) - if err != nil { - return - } - key, err = hex.DecodeString(c.key) - if err != nil { - return - } - sig, err = hex.DecodeString(c.sig) - return -} - -func TestCryptoConvert(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - cases := []cryptoCase{ - 0: { - msg: "F00D", - key: "8E8754F012C2FDB492183D41437FD837CB81D8BBE731924E2E0DAF43FD3F2C93", - sig: "787DC03E9E4EE05983E30BAE0DEFB8DB0671DBC2F5874AC93F8D8CA4018F7A42D6F9A9BCEADB422AC8E27CEE9CA205A0B88D22CD686F0A43EB806E8190A3C400", - valid: true, - }, - 1: { - msg: "DEADBEEF", - key: "0C45ADC887A5463F668533443C829ED13EA8E2E890C778957DC28DB9D2AD5A6C", - sig: "00ED74EED8FDAC7988A14BF6BC222120CBAC249D569AF4C2ADABFC86B792F97DF73C4919BE4B6B0ACB53547273BF29FBF0A9E0992FFAB6CB6C9B09311FC86A00", - valid: true, - }, - 2: { - msg: "1234567890AA", - key: "598FC1F0C76363D14D7480736DEEF390D85863360F075792A6975EFA149FD7EA", - sig: "59AAB7D7BDC4F936B6415DE672A8B77FA6B8B3451CD95B3A631F31F9A05DAEEE5E7E4F89B64DDEBB5F63DC042CA13B8FCB8185F82AD7FD5636FFDA6B0DC9570B", - valid: true, - }, - 3: { - msg: "1234432112344321", - key: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: true, - }, - 4: { - msg: "12344321123443", - key: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - 5: { - msg: "1234432112344321", - key: "459E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "616B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - 6: { - msg: "1234432112344321", - key: "359E0636E780457294CCA5D2D84DB190C3EDBD6879729C10D3963DEA1D5D8120", - sig: "716B44EC7A65E7C719C170D669A47DE80C6AC0BB13FBCC89230976F9CC14D4CF9ECF26D4AFBB9FFF625599F1FF6F78EDA15E9F6B6BDCE07CFE9D8C407AC45208", - valid: false, - }, - } - - for i, tc := range cases { - msg, key, sig, err := toBytes(tc) - require.Nil(err, "%d: %+v", i, err) - - pk, err := parseEdKey(key) - require.Nil(err, "%d: %+v", i, err) - psig, err := parseSig(sig) - require.Nil(err, "%d: %+v", i, err) - - // it is not the signature of the message itself - valid := pk.VerifyBytes(msg, psig) - assert.False(valid, "%d", i) - - // but rather of the hash of the msg - hmsg := hashMsg(msg) - valid = pk.VerifyBytes(hmsg, psig) - assert.Equal(tc.valid, valid, "%d", i) - } -} From 91361407192ed45b390c9d111e87fe5b54c6281b Mon Sep 17 00:00:00 2001 From: Liamsi Date: Tue, 15 May 2018 12:07:05 +0100 Subject: [PATCH 235/273] get rid of go-bindata dependency in Makefile; hardcode its output instead --- Makefile | 18 +++++++++--------- keys/words/wordlist/wordlist.go | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 9ae475983..68fb8344c 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,8 @@ GOTOOLS = \ github.com/golang/dep/cmd/dep \ - github.com/jteeuwen/go-bindata/go-bindata # gopkg.in/alecthomas/gometalinter.v2 \ - # -GOTOOLS_CHECK = dep go-bindata #gometalinter.v2 + +GOTOOLS_CHECK = dep #gometalinter.v2 all: check get_vendor_deps build test install @@ -13,12 +12,13 @@ check: check_tools ######################################## ### Build -wordlist: - # Generating wordlist.go... - go-bindata -ignore ".*\.go" -o keys/words/wordlist/wordlist.go -pkg "wordlist" keys/words/wordlist/... +# Command to generate the workd list (kept here for documentation purposes only): +# wordlist: + # Generating wordlist.go ... + # go-bindata -ignore ".*\.go" -o keys/words/wordlist/wordlist.go -pkg "wordlist" keys/words/wordlist/... -build: wordlist - # Nothing else to build! +#build: wordlist +# # Nothing else to build! install: # Nothing to install! @@ -96,4 +96,4 @@ metalinter_all: # To avoid unintended conflicts with file names, always add to .PHONY # unless there is a reason not to. # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONEY: check wordlist build install check_tools get_tools update_tools get_vendor_deps test fmt metalinter metalinter_all +.PHONEY: check build install check_tools get_tools update_tools get_vendor_deps test fmt metalinter metalinter_all diff --git a/keys/words/wordlist/wordlist.go b/keys/words/wordlist/wordlist.go index 4efff82cb..9ffbb1539 100644 --- a/keys/words/wordlist/wordlist.go +++ b/keys/words/wordlist/wordlist.go @@ -86,7 +86,7 @@ func keysWordsWordlistChinese_simplifiedTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/words/wordlist/chinese_simplified.txt", size: 8192, mode: os.FileMode(420), modTime: time.Unix(1514928181, 0)} + info := bindataFileInfo{name: "keys/words/wordlist/chinese_simplified.txt", size: 8192, mode: os.FileMode(420), modTime: time.Unix(1523115814, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -106,7 +106,7 @@ func keysWordsWordlistEnglishTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/words/wordlist/english.txt", size: 13116, mode: os.FileMode(420), modTime: time.Unix(1514928181, 0)} + info := bindataFileInfo{name: "keys/words/wordlist/english.txt", size: 13116, mode: os.FileMode(420), modTime: time.Unix(1523115814, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -126,7 +126,7 @@ func keysWordsWordlistJapaneseTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/words/wordlist/japanese.txt", size: 24287, mode: os.FileMode(420), modTime: time.Unix(1514928181, 0)} + info := bindataFileInfo{name: "keys/words/wordlist/japanese.txt", size: 24287, mode: os.FileMode(420), modTime: time.Unix(1523115814, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -146,7 +146,7 @@ func keysWordsWordlistSpanishTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/words/wordlist/spanish.txt", size: 13659, mode: os.FileMode(420), modTime: time.Unix(1514928181, 0)} + info := bindataFileInfo{name: "keys/words/wordlist/spanish.txt", size: 13659, mode: os.FileMode(420), modTime: time.Unix(1523115814, 0)} a := &asset{bytes: bytes, info: info} return a, nil } From 3fe985e289f12955161effd2fa4cb0988dc1445c Mon Sep 17 00:00:00 2001 From: Liamsi Date: Tue, 15 May 2018 12:23:33 +0100 Subject: [PATCH 236/273] fix makefile --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 68fb8344c..74af29941 100644 --- a/Makefile +++ b/Makefile @@ -13,12 +13,12 @@ check: check_tools ### Build # Command to generate the workd list (kept here for documentation purposes only): -# wordlist: - # Generating wordlist.go ... +wordlist: + # To re-generate wordlist.go run: # go-bindata -ignore ".*\.go" -o keys/words/wordlist/wordlist.go -pkg "wordlist" keys/words/wordlist/... -#build: wordlist -# # Nothing else to build! +build: wordlist + # Nothing else to build! install: # Nothing to install! From 8423f6ef5a7fd29bd76636cc16702911d246b4b1 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Mon, 21 May 2018 20:45:36 -0700 Subject: [PATCH 237/273] Add the libsodium test vector --- xchacha20poly1035/xchachapoly.go | 8 +-- xchacha20poly1035/xchachapoly_test.go | 91 +++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 xchacha20poly1035/xchachapoly_test.go diff --git a/xchacha20poly1035/xchachapoly.go b/xchacha20poly1035/xchachapoly.go index b9d823414..96413b8c1 100644 --- a/xchacha20poly1035/xchachapoly.go +++ b/xchacha20poly1035/xchachapoly.go @@ -41,11 +41,11 @@ func (c *xchacha20poly1305) Overhead() int { func (c *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { if len(nonce) != NonceSize { - panic("chacha20poly1305: bad nonce length passed to Seal") + panic("xchacha20poly1305: bad nonce length passed to Seal") } if uint64(len(plaintext)) > (1<<38)-64 { - panic("chacha20poly1305: plaintext too large") + panic("xchacha20poly1305: plaintext too large") } var subKey [KeySize]byte @@ -64,10 +64,10 @@ func (c *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) [ func (c *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { if len(nonce) != NonceSize { - panic("chacha20poly1305: bad nonce length passed to Open") + panic("xchacha20poly1305: bad nonce length passed to Open") } if uint64(len(ciphertext)) > (1<<38)-48 { - panic("chacha20poly1305: ciphertext too large") + panic("xchacha20poly1305: ciphertext too large") } var subKey [KeySize]byte var hNonce [16]byte diff --git a/xchacha20poly1035/xchachapoly_test.go b/xchacha20poly1035/xchachapoly_test.go new file mode 100644 index 000000000..5e522e0b1 --- /dev/null +++ b/xchacha20poly1035/xchachapoly_test.go @@ -0,0 +1,91 @@ +package xchacha20poly1305 + +import ( + "bytes" + "encoding/hex" + "testing" +) + +func toHex(bits []byte) string { + return hex.EncodeToString(bits) +} + +func fromHex(bits string) []byte { + b, err := hex.DecodeString(bits) + if err != nil { + panic(err) + } + return b +} + +func TestHChaCha20(t *testing.T) { + for i, v := range hChaCha20Vectors { + var key [32]byte + var nonce [16]byte + copy(key[:], v.key) + copy(nonce[:], v.nonce) + + HChaCha20(&key, &nonce, &key) + if !bytes.Equal(key[:], v.keystream) { + t.Errorf("Test %d: keystream mismatch:\n \t got: %s\n \t want: %s", i, toHex(key[:]), toHex(v.keystream)) + } + } +} + +var hChaCha20Vectors = []struct { + key, nonce, keystream []byte +}{ + { + fromHex("0000000000000000000000000000000000000000000000000000000000000000"), + fromHex("000000000000000000000000000000000000000000000000"), + fromHex("1140704c328d1d5d0e30086cdf209dbd6a43b8f41518a11cc387b669b2ee6586"), + }, + { + fromHex("8000000000000000000000000000000000000000000000000000000000000000"), + fromHex("000000000000000000000000000000000000000000000000"), + fromHex("7d266a7fd808cae4c02a0a70dcbfbcc250dae65ce3eae7fc210f54cc8f77df86"), + }, + { + fromHex("0000000000000000000000000000000000000000000000000000000000000001"), + fromHex("000000000000000000000000000000000000000000000002"), + fromHex("e0c77ff931bb9163a5460c02ac281c2b53d792b1c43fea817e9ad275ae546963"), + }, + { + fromHex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + fromHex("000102030405060708090a0b0c0d0e0f1011121314151617"), + fromHex("51e3ff45a895675c4b33b46c64f4a9ace110d34df6a2ceab486372bacbd3eff6"), + }, +} + +func TestVectors(t *testing.T) { + for i, v := range vectors { + if len(v.plaintext) == 0 { + v.plaintext = make([]byte, len(v.ciphertext)) + } + + var nonce [24]byte + copy(nonce[:], v.nonce) + + aead, err := New(v.key) + if err != nil { + t.Error(err) + } + + dst := aead.Seal(nil, nonce[:], v.plaintext, v.ad) + if !bytes.Equal(dst, v.ciphertext) { + t.Errorf("Test %d: ciphertext mismatch:\n \t got: %s\n \t want: %s", i, toHex(dst), toHex(v.ciphertext)) + } + } +} + +var vectors = []struct { + key, nonce, ad, plaintext, ciphertext []byte +}{ + { + []byte{0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f}, + []byte{0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b}, + []byte{0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7}, + []byte("Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."), + []byte{0x45, 0x3c, 0x06, 0x93, 0xa7, 0x40, 0x7f, 0x04, 0xff, 0x4c, 0x56, 0xae, 0xdb, 0x17, 0xa3, 0xc0, 0xa1, 0xaf, 0xff, 0x01, 0x17, 0x49, 0x30, 0xfc, 0x22, 0x28, 0x7c, 0x33, 0xdb, 0xcf, 0x0a, 0xc8, 0xb8, 0x9a, 0xd9, 0x29, 0x53, 0x0a, 0x1b, 0xb3, 0xab, 0x5e, 0x69, 0xf2, 0x4c, 0x7f, 0x60, 0x70, 0xc8, 0xf8, 0x40, 0xc9, 0xab, 0xb4, 0xf6, 0x9f, 0xbf, 0xc8, 0xa7, 0xff, 0x51, 0x26, 0xfa, 0xee, 0xbb, 0xb5, 0x58, 0x05, 0xee, 0x9c, 0x1c, 0xf2, 0xce, 0x5a, 0x57, 0x26, 0x32, 0x87, 0xae, 0xc5, 0x78, 0x0f, 0x04, 0xec, 0x32, 0x4c, 0x35, 0x14, 0x12, 0x2c, 0xfc, 0x32, 0x31, 0xfc, 0x1a, 0x8b, 0x71, 0x8a, 0x62, 0x86, 0x37, 0x30, 0xa2, 0x70, 0x2b, 0xb7, 0x63, 0x66, 0x11, 0x6b, 0xed, 0x09, 0xe0, 0xfd, 0x5c, 0x6d, 0x84, 0xb6, 0xb0, 0xc1, 0xab, 0xaf, 0x24, 0x9d, 0x5d, 0xd0, 0xf7, 0xf5, 0xa7, 0xea}, + }, +} From 134fdf716930c308ac9f6cd3a80f55ee57f40254 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 22 May 2018 12:43:44 -0400 Subject: [PATCH 238/273] bring in merkle from tmlibs --- merkle/README.md | 4 ++ merkle/simple_map.go | 84 ++++++++++++++++++++++ merkle/simple_map_test.go | 53 ++++++++++++++ merkle/simple_proof.go | 144 +++++++++++++++++++++++++++++++++++++ merkle/simple_tree.go | 91 +++++++++++++++++++++++ merkle/simple_tree_test.go | 87 ++++++++++++++++++++++ merkle/types.go | 47 ++++++++++++ 7 files changed, 510 insertions(+) create mode 100644 merkle/README.md create mode 100644 merkle/simple_map.go create mode 100644 merkle/simple_map_test.go create mode 100644 merkle/simple_proof.go create mode 100644 merkle/simple_tree.go create mode 100644 merkle/simple_tree_test.go create mode 100644 merkle/types.go diff --git a/merkle/README.md b/merkle/README.md new file mode 100644 index 000000000..c44978368 --- /dev/null +++ b/merkle/README.md @@ -0,0 +1,4 @@ +## Simple Merkle Tree + +For smaller static data structures that don't require immutable snapshots or mutability; +for instance the transactions and validation signatures of a block can be hashed using this simple merkle tree logic. diff --git a/merkle/simple_map.go b/merkle/simple_map.go new file mode 100644 index 000000000..cd38de761 --- /dev/null +++ b/merkle/simple_map.go @@ -0,0 +1,84 @@ +package merkle + +import ( + cmn "github.com/tendermint/tmlibs/common" + "golang.org/x/crypto/ripemd160" +) + +type SimpleMap struct { + kvs cmn.KVPairs + sorted bool +} + +func NewSimpleMap() *SimpleMap { + return &SimpleMap{ + kvs: nil, + sorted: false, + } +} + +func (sm *SimpleMap) Set(key string, value Hasher) { + sm.sorted = false + + // Hash the key to blind it... why not? + khash := SimpleHashFromBytes([]byte(key)) + + // And the value is hashed too, so you can + // check for equality with a cached value (say) + // and make a determination to fetch or not. + vhash := value.Hash() + + sm.kvs = append(sm.kvs, cmn.KVPair{ + Key: khash, + Value: vhash, + }) +} + +// Merkle root hash of items sorted by key +// (UNSTABLE: and by value too if duplicate key). +func (sm *SimpleMap) Hash() []byte { + sm.Sort() + return hashKVPairs(sm.kvs) +} + +func (sm *SimpleMap) Sort() { + if sm.sorted { + return + } + sm.kvs.Sort() + sm.sorted = true +} + +// Returns a copy of sorted KVPairs. +func (sm *SimpleMap) KVPairs() cmn.KVPairs { + sm.Sort() + kvs := make(cmn.KVPairs, len(sm.kvs)) + copy(kvs, sm.kvs) + return kvs +} + +//---------------------------------------- + +// A local extension to KVPair that can be hashed. +type KVPair cmn.KVPair + +func (kv KVPair) Hash() []byte { + hasher := ripemd160.New() + err := encodeByteSlice(hasher, kv.Key) + if err != nil { + panic(err) + } + err = encodeByteSlice(hasher, kv.Value) + if err != nil { + panic(err) + } + return hasher.Sum(nil) +} + +func hashKVPairs(kvs cmn.KVPairs) []byte { + kvsH := make([]Hasher, 0, len(kvs)) + for _, kvp := range kvs { + kvsH = append(kvsH, KVPair(kvp)) + } + return SimpleHashFromHashers(kvsH) +} diff --git a/merkle/simple_map_test.go b/merkle/simple_map_test.go new file mode 100644 index 000000000..c9c871354 --- /dev/null +++ b/merkle/simple_map_test.go @@ -0,0 +1,53 @@ +package merkle + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +type strHasher string + +func (str strHasher) Hash() []byte { + return SimpleHashFromBytes([]byte(str)) +} + +func TestSimpleMap(t *testing.T) { + { + db := NewSimpleMap() + db.Set("key1", strHasher("value1")) + assert.Equal(t, "acdb4f121bc6f25041eb263ab463f1cd79236a32", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := NewSimpleMap() + db.Set("key1", strHasher("value2")) + assert.Equal(t, "b8cbf5adee8c524e14f531da9b49adbbbd66fffa", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := NewSimpleMap() + db.Set("key1", strHasher("value1")) + db.Set("key2", strHasher("value2")) + assert.Equal(t, "1708aabc85bbe00242d3db8c299516aa54e48c38", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := NewSimpleMap() + db.Set("key2", strHasher("value2")) // NOTE: out of order + db.Set("key1", strHasher("value1")) + assert.Equal(t, "1708aabc85bbe00242d3db8c299516aa54e48c38", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := NewSimpleMap() + db.Set("key1", strHasher("value1")) + db.Set("key2", strHasher("value2")) + db.Set("key3", strHasher("value3")) + assert.Equal(t, "e728afe72ce351eed6aca65c5f78da19b9a6e214", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } + { + db := NewSimpleMap() + db.Set("key2", strHasher("value2")) // NOTE: out of order + db.Set("key1", strHasher("value1")) + db.Set("key3", strHasher("value3")) + assert.Equal(t, "e728afe72ce351eed6aca65c5f78da19b9a6e214", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + } +} diff --git a/merkle/simple_proof.go b/merkle/simple_proof.go new file mode 100644 index 000000000..ca6ccf372 --- /dev/null +++ b/merkle/simple_proof.go @@ -0,0 +1,144 @@ +package merkle + +import ( + "bytes" + "fmt" +) + +type SimpleProof struct { + Aunts [][]byte `json:"aunts"` // Hashes from leaf's sibling to a root's child. +} + +// proofs[0] is the proof for items[0]. +func SimpleProofsFromHashers(items []Hasher) (rootHash []byte, proofs []*SimpleProof) { + trails, rootSPN := trailsFromHashers(items) + rootHash = rootSPN.Hash + proofs = make([]*SimpleProof, len(items)) + for i, trail := range trails { + proofs[i] = &SimpleProof{ + Aunts: trail.FlattenAunts(), + } + } + return +} + +func SimpleProofsFromMap(m map[string]Hasher) (rootHash []byte, proofs []*SimpleProof) { + sm := NewSimpleMap() + for k, v := range m { + sm.Set(k, v) + } + sm.Sort() + kvs := sm.kvs + kvsH := make([]Hasher, 0, len(kvs)) + for _, kvp := range kvs { + kvsH = append(kvsH, KVPair(kvp)) + } + return SimpleProofsFromHashers(kvsH) +} + +// Verify that leafHash is a leaf hash of the simple-merkle-tree +// which hashes to rootHash. +func (sp *SimpleProof) Verify(index int, total int, leafHash []byte, rootHash []byte) bool { + computedHash := computeHashFromAunts(index, total, leafHash, sp.Aunts) + return computedHash != nil && bytes.Equal(computedHash, rootHash) +} + +func (sp *SimpleProof) String() string { + return sp.StringIndented("") +} + +func (sp *SimpleProof) StringIndented(indent string) string { + return fmt.Sprintf(`SimpleProof{ +%s Aunts: %X +%s}`, + indent, sp.Aunts, + indent) +} + +// Use the leafHash and innerHashes to get the root merkle hash. +// If the length of the innerHashes slice isn't exactly correct, the result is nil. +// Recursive impl. +func computeHashFromAunts(index int, total int, leafHash []byte, innerHashes [][]byte) []byte { + if index >= total || index < 0 || total <= 0 { + return nil + } + switch total { + case 0: + panic("Cannot call computeHashFromAunts() with 0 total") + case 1: + if len(innerHashes) != 0 { + return nil + } + return leafHash + default: + if len(innerHashes) == 0 { + return nil + } + numLeft := (total + 1) / 2 + if index < numLeft { + leftHash := computeHashFromAunts(index, numLeft, leafHash, innerHashes[:len(innerHashes)-1]) + if leftHash == nil { + return nil + } + return SimpleHashFromTwoHashes(leftHash, innerHashes[len(innerHashes)-1]) + } + rightHash := computeHashFromAunts(index-numLeft, total-numLeft, leafHash, innerHashes[:len(innerHashes)-1]) + if rightHash == nil { + return nil + } + return SimpleHashFromTwoHashes(innerHashes[len(innerHashes)-1], rightHash) + } +} + +// Helper structure to construct merkle proof. +// The node and the tree is thrown away afterwards. +// Exactly one of node.Left and node.Right is nil, unless node is the root, in which case both are nil. +// node.Parent.Hash = hash(node.Hash, node.Right.Hash) or +// hash(node.Left.Hash, node.Hash), depending on whether node is a left/right child. +type SimpleProofNode struct { + Hash []byte + Parent *SimpleProofNode + Left *SimpleProofNode // Left sibling (only one of Left,Right is set) + Right *SimpleProofNode // Right sibling (only one of Left,Right is set) +} + +// Starting from a leaf SimpleProofNode, FlattenAunts() will return +// the inner hashes for the item corresponding to the leaf. +func (spn *SimpleProofNode) FlattenAunts() [][]byte { + // Nonrecursive impl. + innerHashes := [][]byte{} + for spn != nil { + if spn.Left != nil { + innerHashes = append(innerHashes, spn.Left.Hash) + } else if spn.Right != nil { + innerHashes = append(innerHashes, spn.Right.Hash) + } else { + break + } + spn = spn.Parent + } + return innerHashes +} + +// trails[0].Hash is the leaf hash for items[0]. +// trails[i].Parent.Parent....Parent == root for all i. +func trailsFromHashers(items []Hasher) (trails []*SimpleProofNode, root *SimpleProofNode) { + // Recursive impl. + switch len(items) { + case 0: + return nil, nil + case 1: + trail := &SimpleProofNode{items[0].Hash(), nil, nil, nil} + return []*SimpleProofNode{trail}, trail + default: + lefts, leftRoot := trailsFromHashers(items[:(len(items)+1)/2]) + rights, rightRoot := trailsFromHashers(items[(len(items)+1)/2:]) + rootHash := SimpleHashFromTwoHashes(leftRoot.Hash, rightRoot.Hash) + root := &SimpleProofNode{rootHash, nil, nil, nil} + leftRoot.Parent = root + leftRoot.Right = rightRoot + rightRoot.Parent = root + rightRoot.Left = leftRoot + return append(lefts, rights...), root + } +} diff --git a/merkle/simple_tree.go b/merkle/simple_tree.go new file mode 100644 index 000000000..9bdf52cb2 --- /dev/null +++ b/merkle/simple_tree.go @@ -0,0 +1,91 @@ +/* +Computes a deterministic minimal height merkle tree hash. +If the number of items is not a power of two, some leaves +will be at different levels. Tries to keep both sides of +the tree the same size, but the left may be one greater. + +Use this for short deterministic trees, such as the validator list. +For larger datasets, use IAVLTree. + + * + / \ + / \ + / \ + / \ + * * + / \ / \ + / \ / \ + / \ / \ + * * * h6 + / \ / \ / \ + h0 h1 h2 h3 h4 h5 + +*/ + +package merkle + +import ( + "golang.org/x/crypto/ripemd160" +) + +func SimpleHashFromTwoHashes(left []byte, right []byte) []byte { + var hasher = ripemd160.New() + err := encodeByteSlice(hasher, left) + if err != nil { + panic(err) + } + err = encodeByteSlice(hasher, right) + if err != nil { + panic(err) + } + return hasher.Sum(nil) +} + +func SimpleHashFromHashes(hashes [][]byte) []byte { + // Recursive impl. + switch len(hashes) { + case 0: + return nil + case 1: + return hashes[0] + default: + left := SimpleHashFromHashes(hashes[:(len(hashes)+1)/2]) + right := SimpleHashFromHashes(hashes[(len(hashes)+1)/2:]) + return SimpleHashFromTwoHashes(left, right) + } +} + +// NOTE: Do not implement this, use SimpleHashFromByteslices instead. +// type Byteser interface { Bytes() []byte } +// func SimpleHashFromBytesers(items []Byteser) []byte { ... } + +func SimpleHashFromByteslices(bzs [][]byte) []byte { + hashes := make([][]byte, len(bzs)) + for i, bz := range bzs { + hashes[i] = SimpleHashFromBytes(bz) + } + return SimpleHashFromHashes(hashes) +} + +func SimpleHashFromBytes(bz []byte) []byte { + hasher := ripemd160.New() + hasher.Write(bz) + return hasher.Sum(nil) +} + +func SimpleHashFromHashers(items []Hasher) []byte { + hashes := make([][]byte, len(items)) + for i, item := range items { + hash := item.Hash() + hashes[i] = hash + } + return SimpleHashFromHashes(hashes) +} + +func SimpleHashFromMap(m map[string]Hasher) []byte { + sm := NewSimpleMap() + for k, v := range m { + sm.Set(k, v) + } + return sm.Hash() +} diff --git a/merkle/simple_tree_test.go b/merkle/simple_tree_test.go new file mode 100644 index 000000000..8c4ed01f8 --- /dev/null +++ b/merkle/simple_tree_test.go @@ -0,0 +1,87 @@ +package merkle + +import ( + "bytes" + + cmn "github.com/tendermint/tmlibs/common" + . "github.com/tendermint/tmlibs/test" + + "testing" +) + +type testItem []byte + +func (tI testItem) Hash() []byte { + return []byte(tI) +} + +func TestSimpleProof(t *testing.T) { + + total := 100 + + items := make([]Hasher, total) + for i := 0; i < total; i++ { + items[i] = testItem(cmn.RandBytes(32)) + } + + rootHash := SimpleHashFromHashers(items) + + rootHash2, proofs := SimpleProofsFromHashers(items) + + if !bytes.Equal(rootHash, rootHash2) { + t.Errorf("Unmatched root hashes: %X vs %X", rootHash, rootHash2) + } + + // For each item, check the trail. + for i, item := range items { + itemHash := item.Hash() + proof := proofs[i] + + // Verify success + ok := proof.Verify(i, total, itemHash, rootHash) + if !ok { + t.Errorf("Verification failed for index %v.", i) + } + + // Wrong item index should make it fail + { + ok = proof.Verify((i+1)%total, total, itemHash, rootHash) + if ok { + t.Errorf("Expected verification to fail for wrong index %v.", i) + } + } + + // Trail too long should make it fail + origAunts := proof.Aunts + proof.Aunts = append(proof.Aunts, cmn.RandBytes(32)) + { + ok = proof.Verify(i, total, itemHash, rootHash) + if ok { + t.Errorf("Expected verification to fail for wrong trail length.") + } + } + proof.Aunts = origAunts + + // Trail too short should make it fail + proof.Aunts = proof.Aunts[0 : len(proof.Aunts)-1] + { + ok = proof.Verify(i, total, itemHash, rootHash) + if ok { + t.Errorf("Expected verification to fail for wrong trail length.") + } + } + proof.Aunts = origAunts + + // Mutating the itemHash should make it fail. + ok = proof.Verify(i, total, MutateByteSlice(itemHash), rootHash) + if ok { + t.Errorf("Expected verification to fail for mutated leaf hash") + } + + // Mutating the rootHash should make it fail. + ok = proof.Verify(i, total, itemHash, MutateByteSlice(rootHash)) + if ok { + t.Errorf("Expected verification to fail for mutated root hash") + } + } +} diff --git a/merkle/types.go b/merkle/types.go new file mode 100644 index 000000000..a0c491a7e --- /dev/null +++ b/merkle/types.go @@ -0,0 +1,47 @@ +package merkle + +import ( + "encoding/binary" + "io" +) + +type Tree interface { + Size() (size int) + Height() (height int8) + Has(key []byte) (has bool) + Proof(key []byte) (value []byte, proof []byte, exists bool) // TODO make it return an index + Get(key []byte) (index int, value []byte, exists bool) + GetByIndex(index int) (key []byte, value []byte) + Set(key []byte, value []byte) (updated bool) + Remove(key []byte) (value []byte, removed bool) + HashWithCount() (hash []byte, count int) + Hash() (hash []byte) + Save() (hash []byte) + Load(hash []byte) + Copy() Tree + Iterate(func(key []byte, value []byte) (stop bool)) (stopped bool) + IterateRange(start []byte, end []byte, ascending bool, fx func(key []byte, value []byte) (stop bool)) (stopped bool) +} + +type Hasher interface { + Hash() []byte +} + +//----------------------------------------------------------------------- +// NOTE: these are duplicated from go-amino so we dont need go-amino as a dep + +func encodeByteSlice(w io.Writer, bz []byte) (err error) { + err = encodeUvarint(w, uint64(len(bz))) + if err != nil { + return + } + _, err = w.Write(bz) + return +} + +func encodeUvarint(w io.Writer, i uint64) (err error) { + var buf [10]byte + n := binary.PutUvarint(buf[:], i) + _, err = w.Write(buf[0:n]) + return +} From 4663ffdf087b571e5ccbc0df5ec6a6b8ad36cce1 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 22 May 2018 12:46:15 -0400 Subject: [PATCH 239/273] add tmhash --- merkle/simple_map.go | 4 ++-- merkle/simple_map_test.go | 12 ++++++------ merkle/simple_tree.go | 6 +++--- tmhash/hash.go | 41 +++++++++++++++++++++++++++++++++++++++ tmhash/hash_test.go | 23 ++++++++++++++++++++++ 5 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 tmhash/hash.go create mode 100644 tmhash/hash_test.go diff --git a/merkle/simple_map.go b/merkle/simple_map.go index cd38de761..41d1ccd56 100644 --- a/merkle/simple_map.go +++ b/merkle/simple_map.go @@ -2,7 +2,7 @@ package merkle import ( cmn "github.com/tendermint/tmlibs/common" - "golang.org/x/crypto/ripemd160" + "github.com/tendermint/go-crypto/tmhash" ) type SimpleMap struct { @@ -63,7 +63,7 @@ func (sm *SimpleMap) KVPairs() cmn.KVPairs { type KVPair cmn.KVPair func (kv KVPair) Hash() []byte { - hasher := ripemd160.New() + hasher := tmhash.New() err := encodeByteSlice(hasher, kv.Key) if err != nil { panic(err) diff --git a/merkle/simple_map_test.go b/merkle/simple_map_test.go index c9c871354..6e1004db2 100644 --- a/merkle/simple_map_test.go +++ b/merkle/simple_map_test.go @@ -17,37 +17,37 @@ func TestSimpleMap(t *testing.T) { { db := NewSimpleMap() db.Set("key1", strHasher("value1")) - assert.Equal(t, "acdb4f121bc6f25041eb263ab463f1cd79236a32", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "3dafc06a52039d029be57c75c9d16356a4256ef4", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() db.Set("key1", strHasher("value2")) - assert.Equal(t, "b8cbf5adee8c524e14f531da9b49adbbbd66fffa", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "03eb5cfdff646bc4e80fec844e72fd248a1c6b2c", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() db.Set("key1", strHasher("value1")) db.Set("key2", strHasher("value2")) - assert.Equal(t, "1708aabc85bbe00242d3db8c299516aa54e48c38", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "acc3971eab8513171cc90ce8b74f368c38f9657d", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() db.Set("key2", strHasher("value2")) // NOTE: out of order db.Set("key1", strHasher("value1")) - assert.Equal(t, "1708aabc85bbe00242d3db8c299516aa54e48c38", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "acc3971eab8513171cc90ce8b74f368c38f9657d", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() db.Set("key1", strHasher("value1")) db.Set("key2", strHasher("value2")) db.Set("key3", strHasher("value3")) - assert.Equal(t, "e728afe72ce351eed6aca65c5f78da19b9a6e214", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "0cd117ad14e6cd22edcd9aa0d84d7063b54b862f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() db.Set("key2", strHasher("value2")) // NOTE: out of order db.Set("key1", strHasher("value1")) db.Set("key3", strHasher("value3")) - assert.Equal(t, "e728afe72ce351eed6aca65c5f78da19b9a6e214", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "0cd117ad14e6cd22edcd9aa0d84d7063b54b862f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } } diff --git a/merkle/simple_tree.go b/merkle/simple_tree.go index 9bdf52cb2..3c31b1337 100644 --- a/merkle/simple_tree.go +++ b/merkle/simple_tree.go @@ -25,11 +25,11 @@ For larger datasets, use IAVLTree. package merkle import ( - "golang.org/x/crypto/ripemd160" + "github.com/tendermint/go-crypto/tmhash" ) func SimpleHashFromTwoHashes(left []byte, right []byte) []byte { - var hasher = ripemd160.New() + var hasher = tmhash.New() err := encodeByteSlice(hasher, left) if err != nil { panic(err) @@ -68,7 +68,7 @@ func SimpleHashFromByteslices(bzs [][]byte) []byte { } func SimpleHashFromBytes(bz []byte) []byte { - hasher := ripemd160.New() + hasher := tmhash.New() hasher.Write(bz) return hasher.Sum(nil) } diff --git a/tmhash/hash.go b/tmhash/hash.go new file mode 100644 index 000000000..de69c406f --- /dev/null +++ b/tmhash/hash.go @@ -0,0 +1,41 @@ +package tmhash + +import ( + "crypto/sha256" + "hash" +) + +var ( + Size = 20 + BlockSize = sha256.BlockSize +) + +type sha256trunc struct { + sha256 hash.Hash +} + +func (h sha256trunc) Write(p []byte) (n int, err error) { + return h.sha256.Write(p) +} +func (h sha256trunc) Sum(b []byte) []byte { + shasum := h.sha256.Sum(b) + return shasum[:Size] +} + +func (h sha256trunc) Reset() { + h.sha256.Reset() +} + +func (h sha256trunc) Size() int { + return Size +} + +func (h sha256trunc) BlockSize() int { + return h.sha256.BlockSize() +} + +func New() hash.Hash { + return sha256trunc{ + sha256: sha256.New(), + } +} diff --git a/tmhash/hash_test.go b/tmhash/hash_test.go new file mode 100644 index 000000000..abf0247ab --- /dev/null +++ b/tmhash/hash_test.go @@ -0,0 +1,23 @@ +package tmhash_test + +import ( + "crypto/sha256" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/tendermint/go-crypto/tmhash" +) + +func TestHash(t *testing.T) { + testVector := []byte("abc") + hasher := tmhash.New() + hasher.Write(testVector) + bz := hasher.Sum(nil) + + hasher = sha256.New() + hasher.Write(testVector) + bz2 := hasher.Sum(nil) + bz2 = bz2[:20] + + assert.Equal(t, bz, bz2) +} From c2636c3c6b95cc314e6a7ddc079daf236a9a1a5a Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 22 May 2018 13:04:42 -0400 Subject: [PATCH 240/273] tmhash: add Sum function --- tmhash/hash.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tmhash/hash.go b/tmhash/hash.go index de69c406f..9f684ce01 100644 --- a/tmhash/hash.go +++ b/tmhash/hash.go @@ -34,8 +34,15 @@ func (h sha256trunc) BlockSize() int { return h.sha256.BlockSize() } +// New returns a new hash.Hash. func New() hash.Hash { return sha256trunc{ sha256: sha256.New(), } } + +// Sum returns the first 20 bytes of SHA256 of the bz. +func Sum(bz []byte) []byte { + hash := sha256.Sum256(bz) + return hash[:Size] +} From 384f1e399afb23a30f01e629145c82afb3498664 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Wed, 23 May 2018 23:54:26 +0200 Subject: [PATCH 241/273] Fixed the directory name and added a test vector --- {xchacha20poly1035 => xchacha20poly1305}/xchachapoly.go | 0 {xchacha20poly1035 => xchacha20poly1305}/xchachapoly_test.go | 5 +++++ 2 files changed, 5 insertions(+) rename {xchacha20poly1035 => xchacha20poly1305}/xchachapoly.go (100%) rename {xchacha20poly1035 => xchacha20poly1305}/xchachapoly_test.go (94%) diff --git a/xchacha20poly1035/xchachapoly.go b/xchacha20poly1305/xchachapoly.go similarity index 100% rename from xchacha20poly1035/xchachapoly.go rename to xchacha20poly1305/xchachapoly.go diff --git a/xchacha20poly1035/xchachapoly_test.go b/xchacha20poly1305/xchachapoly_test.go similarity index 94% rename from xchacha20poly1035/xchachapoly_test.go rename to xchacha20poly1305/xchachapoly_test.go index 5e522e0b1..460b90ab4 100644 --- a/xchacha20poly1035/xchachapoly_test.go +++ b/xchacha20poly1305/xchachapoly_test.go @@ -55,6 +55,11 @@ var hChaCha20Vectors = []struct { fromHex("000102030405060708090a0b0c0d0e0f1011121314151617"), fromHex("51e3ff45a895675c4b33b46c64f4a9ace110d34df6a2ceab486372bacbd3eff6"), }, + { + fromHex("24f11cce8a1b3d61e441561a696c1c1b7e173d084fd4812425435a8896a013dc"), + fromHex("d9660c5900ae19ddad28d6e06e45fe5e"), + fromHex("5966b3eec3bff1189f831f06afe4d4e3be97fa9235ec8c20d08acfbbb4e851e3"), + }, } func TestVectors(t *testing.T) { From 05a5294e528161ca7192295a9397d0d8e8adea63 Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Thu, 24 May 2018 00:12:54 +0200 Subject: [PATCH 242/273] Remove panic and check the round trip --- xchacha20poly1305/xchachapoly.go | 5 +++-- xchacha20poly1305/xchachapoly_test.go | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/xchacha20poly1305/xchachapoly.go b/xchacha20poly1305/xchachapoly.go index 96413b8c1..9e0778579 100644 --- a/xchacha20poly1305/xchachapoly.go +++ b/xchacha20poly1305/xchachapoly.go @@ -4,6 +4,7 @@ import ( "crypto/cipher" "encoding/binary" "errors" + "fmt" "golang.org/x/crypto/chacha20poly1305" ) @@ -64,10 +65,10 @@ func (c *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) [ func (c *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { if len(nonce) != NonceSize { - panic("xchacha20poly1305: bad nonce length passed to Open") + return nil, fmt.Errorf("xchacha20poly1305: bad nonce length passed to Open") } if uint64(len(ciphertext)) > (1<<38)-48 { - panic("xchacha20poly1305: ciphertext too large") + return nil, fmt.Errorf("xchacha20poly1305: ciphertext too large") } var subKey [KeySize]byte var hNonce [16]byte diff --git a/xchacha20poly1305/xchachapoly_test.go b/xchacha20poly1305/xchachapoly_test.go index 460b90ab4..3001217f4 100644 --- a/xchacha20poly1305/xchachapoly_test.go +++ b/xchacha20poly1305/xchachapoly_test.go @@ -80,6 +80,13 @@ func TestVectors(t *testing.T) { if !bytes.Equal(dst, v.ciphertext) { t.Errorf("Test %d: ciphertext mismatch:\n \t got: %s\n \t want: %s", i, toHex(dst), toHex(v.ciphertext)) } + open, err := aead.Open(nil, nonce[:], dst, v.ad) + if err != nil { + t.Error(err) + } + if !bytes.Equal(open, v.plaintext) { + t.Errorf("Test %d: plaintext mismatch:\n \t got: %s\n \t want: %s", i, string(open), string(v.plaintext)) + } } } From 707d27c11e34f87fda4c2d5623f6e0a6b15d2d14 Mon Sep 17 00:00:00 2001 From: vrde Date: Thu, 24 May 2018 16:57:37 +0200 Subject: [PATCH 243/273] Fix dead link in README.md (#106) * Fix dead link in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a524c014..be087e045 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ go-crypto is the cryptographic package adapted for Tendermint's uses ## Binary encoding -For Binary encoding, please refer to the [Tendermint encoding spec](https://github.com/tendermint/tendermint/blob/develop/docs/specification/new-spec/encoding.md). +For Binary encoding, please refer to the [Tendermint encoding spec](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md). ## JSON Encoding From e534559bdc88e0cdbecaf41bc0023f3fb57c9785 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 30 May 2018 01:39:50 +0200 Subject: [PATCH 244/273] Update upstream Ledger code --- Gopkg.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index d65f87b68..332714ee4 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -11,13 +11,13 @@ branch = "master" name = "github.com/btcsuite/btcd" packages = ["btcec"] - revision = "675abc5df3c5531bc741b56a765e35623459da6d" + revision = "bc0944904505aab55e089371a892be2f87883161" [[projects]] branch = "master" name = "github.com/btcsuite/btcutil" packages = ["base58"] - revision = "501929d3d046174c3d39f0ea54ece471aa17238c" + revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" [[projects]] name = "github.com/davecgh/go-spew" @@ -61,7 +61,7 @@ branch = "master" name = "github.com/golang/snappy" packages = ["."] - revision = "553a641470496b2327abcac10b36396bd98e45c9" + revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" [[projects]] branch = "master" @@ -119,7 +119,7 @@ "leveldb/table", "leveldb/util" ] - revision = "9637fa0b2f0db13c99d899b91007edb7df4610b7" + revision = "5d6fca44a948d2be89a9702de7717f0168403d3d" [[projects]] branch = "master" @@ -134,8 +134,8 @@ [[projects]] name = "github.com/tendermint/go-amino" packages = ["."] - revision = "ed62928576cfcaf887209dc96142cd79cdfff389" - version = "0.9.9" + revision = "3c22a7a539411f89a96738fcfa14c1027e24e5ec" + version = "0.9.10" [[projects]] name = "github.com/tendermint/tmlibs" @@ -144,8 +144,8 @@ "db", "log" ] - revision = "d94e312673e16a11ea55d742cefb3e331228f898" - version = "v0.8.2" + revision = "d970af87248a4e162590300dbb74e102183a417d" + version = "v0.8.3" [[projects]] branch = "master" @@ -157,7 +157,7 @@ branch = "master" name = "github.com/zondax/ledger-goclient" packages = ["."] - revision = "5b2fe84d3139027c29bd8f0c054ed9444f8a7622" + revision = "3e2146609cdb97894c064d59e9d00accd8c2b1dd" [[projects]] branch = "master" @@ -173,7 +173,7 @@ "ripemd160", "salsa20/salsa" ] - revision = "034e5325b6ab92faa14d15c30e86919e911cf8e0" + revision = "ab813273cd59e1333f7ae7bff5d027d4aadf528c" [solve-meta] analyzer-name = "dep" From 3186dc4cef541ab8f4a7bd107b2894b1186a601a Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 30 May 2018 03:29:42 +0200 Subject: [PATCH 245/273] Clarify function names --- ledger.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ledger.go b/ledger.go index a9bc1d975..5b681cda8 100644 --- a/ledger.go +++ b/ledger.go @@ -21,7 +21,7 @@ func getLedger() (*ledger.Ledger, error) { return device, err } -func pubkeyLedger(device *ledger.Ledger, path DerivationPath) (pub PubKey, err error) { +func pubkeyLedgerSecp256k1(device *ledger.Ledger, path DerivationPath) (pub PubKey, err error) { key, err := device.GetPublicKeySECP256K1(path) if err != nil { return pub, fmt.Errorf("Error fetching public key: %v", err) @@ -33,7 +33,7 @@ func pubkeyLedger(device *ledger.Ledger, path DerivationPath) (pub PubKey, err e return p, err } -func signLedger(device *ledger.Ledger, path DerivationPath, msg []byte) (sig Signature, err error) { +func signLedgerSecp256k1(device *ledger.Ledger, path DerivationPath, msg []byte) (sig Signature, err error) { bsig, err := device.SignSECP256K1(path, msg) if err != nil { return sig, err @@ -107,12 +107,12 @@ func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) Signature { panic(err) } - sig, err := signLedger(dev, pk.Path, msg) + sig, err := signLedgerSecp256k1(dev, pk.Path, msg) if err != nil { panic(err) } - pub, err := pubkeyLedger(dev, pk.Path) + pub, err := pubkeyLedgerSecp256k1(dev, pk.Path) if err != nil { panic(err) } @@ -154,7 +154,7 @@ func (pk PrivKeyLedgerSecp256k1) forceGetPubKey() (key PubKey, err error) { if err != nil { return key, errors.New(fmt.Sprintf("Cannot connect to Ledger device - error: %v", err)) } - key, err = pubkeyLedger(dev, pk.Path) + key, err = pubkeyLedgerSecp256k1(dev, pk.Path) if err != nil { return key, errors.New(fmt.Sprintf("Please open Cosmos app on the Ledger device - error: %v", err)) } From ee411daa1778470e93f6cbc634c22ded60e40ea6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 30 May 2018 03:42:47 +0200 Subject: [PATCH 246/273] Add ed25519, tests will fail until ed25519 verification fix --- ledger_common.go | 19 ++++ ledger_ed25519.go | 156 +++++++++++++++++++++++++++++++ ledger.go => ledger_secp256k1.go | 13 --- ledger_test.go | 40 +++++++- 4 files changed, 214 insertions(+), 14 deletions(-) create mode 100644 ledger_common.go create mode 100644 ledger_ed25519.go rename ledger.go => ledger_secp256k1.go (94%) diff --git a/ledger_common.go b/ledger_common.go new file mode 100644 index 000000000..39f15464a --- /dev/null +++ b/ledger_common.go @@ -0,0 +1,19 @@ +package crypto + +import ( + ledger "github.com/zondax/ledger-goclient" +) + +var device *ledger.Ledger + +// Ledger derivation path +type DerivationPath = []uint32 + +// getLedger gets a copy of the device, and caches it +func getLedger() (*ledger.Ledger, error) { + var err error + if device == nil { + device, err = ledger.FindLedger() + } + return device, err +} diff --git a/ledger_ed25519.go b/ledger_ed25519.go new file mode 100644 index 000000000..0c9cd157f --- /dev/null +++ b/ledger_ed25519.go @@ -0,0 +1,156 @@ +package crypto + +import ( + "fmt" + "github.com/pkg/errors" + + // "github.com/tendermint/ed25519" + ledger "github.com/zondax/ledger-goclient" +) + +func pubkeyLedgerEd25519(device *ledger.Ledger, path DerivationPath) (pub PubKey, err error) { + key, err := device.GetPublicKeyED25519(path) + if err != nil { + return pub, fmt.Errorf("Error fetching public key: %v", err) + } + var p PubKeyEd25519 + copy(p[:], key[0:32]) + return p, err +} + +func signLedgerEd25519(device *ledger.Ledger, path DerivationPath, msg []byte) (sig Signature, err error) { + bsig, err := device.SignED25519(path, msg) + if err != nil { + return sig, err + } + sig = SignatureEd25519FromBytes(bsig) + return sig, nil +} + +// PrivKeyLedgerEd25519 implements PrivKey, calling the ledger nano +// we cache the PubKey from the first call to use it later +type PrivKeyLedgerEd25519 struct { + // PubKey should be private, but we want to encode it via go-amino + // so we can view the address later, even without having the ledger + // attached + CachedPubKey PubKey + Path DerivationPath +} + +// NewPrivKeyLedgerEd25519 will generate a new key and store the +// public key for later use. +func NewPrivKeyLedgerEd25519(path DerivationPath) (PrivKey, error) { + var pk PrivKeyLedgerEd25519 + pk.Path = path + // getPubKey will cache the pubkey for later use, + // this allows us to return an error early if the ledger + // is not plugged in + _, err := pk.getPubKey() + return &pk, err +} + +// ValidateKey allows us to verify the sanity of a key +// after loading it from disk +func (pk PrivKeyLedgerEd25519) ValidateKey() error { + // getPubKey will return an error if the ledger is not + // properly set up... + pub, err := pk.forceGetPubKey() + if err != nil { + return err + } + // verify this matches cached address + if !pub.Equals(pk.CachedPubKey) { + return errors.New("Cached key does not match retrieved key") + } + return nil +} + +// AssertIsPrivKeyInner fulfils PrivKey Interface +func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} + +// Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify +// the same key when we reconnect to a ledger +func (pk PrivKeyLedgerEd25519) Bytes() []byte { + bin, err := cdc.MarshalBinaryBare(pk) + if err != nil { + panic(err) + } + return bin +} + +// Sign calls the ledger and stores the PubKey for future use +// +// XXX/TODO: panics if there is an error communicating with the ledger. +// +// Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, +// returning an error, so this should only trigger if the privkey is held +// in memory for a while before use. +func (pk PrivKeyLedgerEd25519) Sign(msg []byte) Signature { + // oh, I wish there was better error handling + dev, err := getLedger() + if err != nil { + panic(err) + } + + sig, err := signLedgerEd25519(dev, pk.Path, msg) + if err != nil { + panic(err) + } + + pub, err := pubkeyLedgerEd25519(dev, pk.Path) + if err != nil { + panic(err) + } + + // if we have no pubkey yet, store it for future queries + if pk.CachedPubKey == nil { + pk.CachedPubKey = pub + } else if !pk.CachedPubKey.Equals(pub) { + panic("Stored key does not match signing key") + } + return sig +} + +// PubKey returns the stored PubKey +// TODO: query the ledger if not there, once it is not volatile +func (pk PrivKeyLedgerEd25519) PubKey() PubKey { + key, err := pk.getPubKey() + if err != nil { + panic(err) + } + return key +} + +// getPubKey reads the pubkey from cache or from the ledger itself +// since this involves IO, it may return an error, which is not exposed +// in the PubKey interface, so this function allows better error handling +func (pk PrivKeyLedgerEd25519) getPubKey() (key PubKey, err error) { + // if we have no pubkey, set it + if pk.CachedPubKey == nil { + pk.CachedPubKey, err = pk.forceGetPubKey() + } + return pk.CachedPubKey, err +} + +// forceGetPubKey is like getPubKey but ignores any cached key +// and ensures we get it from the ledger itself. +func (pk PrivKeyLedgerEd25519) forceGetPubKey() (key PubKey, err error) { + dev, err := getLedger() + if err != nil { + return key, errors.New(fmt.Sprintf("Cannot connect to Ledger device - error: %v", err)) + } + key, err = pubkeyLedgerEd25519(dev, pk.Path) + if err != nil { + return key, errors.New(fmt.Sprintf("Please open Cosmos app on the Ledger device - error: %v", err)) + } + return key, err +} + +// Equals fulfils PrivKey Interface - makes sure both keys refer to the +// same +func (pk PrivKeyLedgerEd25519) Equals(other PrivKey) bool { + if ledger, ok := other.(*PrivKeyLedgerEd25519); ok { + return pk.CachedPubKey.Equals(ledger.CachedPubKey) + } + return false +} diff --git a/ledger.go b/ledger_secp256k1.go similarity index 94% rename from ledger.go rename to ledger_secp256k1.go index 5b681cda8..b574035d4 100644 --- a/ledger.go +++ b/ledger_secp256k1.go @@ -8,19 +8,6 @@ import ( ledger "github.com/zondax/ledger-goclient" ) -var device *ledger.Ledger - -type DerivationPath = []uint32 - -// getLedger gets a copy of the device, and caches it -func getLedger() (*ledger.Ledger, error) { - var err error - if device == nil { - device, err = ledger.FindLedger() - } - return device, err -} - func pubkeyLedgerSecp256k1(device *ledger.Ledger, path DerivationPath) (pub PubKey, err error) { key, err := device.GetPublicKeySECP256K1(path) if err != nil { diff --git a/ledger_test.go b/ledger_test.go index 1c193b5f1..a0ea35837 100644 --- a/ledger_test.go +++ b/ledger_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestRealLedger(t *testing.T) { +func TestRealLedgerSecp256k1(t *testing.T) { if os.Getenv("WITH_LEDGER") == "" { t.Skip("Set WITH_LEDGER to run code on real ledger") @@ -46,6 +46,44 @@ func TestRealLedger(t *testing.T) { assert.Equal(t, pub, bpub) } +func TestRealLedgerEd25519(t *testing.T) { + + if os.Getenv("WITH_LEDGER") == "" { + t.Skip("Set WITH_LEDGER to run code on real ledger") + } + msg := []byte("kuhehfeohg") + + path := DerivationPath{44, 60, 0, 0, 0} + + priv, err := NewPrivKeyLedgerEd25519(path) + require.Nil(t, err, "%+v", err) + pub := priv.PubKey() + sig := priv.Sign(msg) + + valid := pub.VerifyBytes(msg, sig) + assert.True(t, valid) + + // now, let's serialize the key and make sure it still works + bs := priv.Bytes() + priv2, err := PrivKeyFromBytes(bs) + require.Nil(t, err, "%+v", err) + + // make sure we get the same pubkey when we load from disk + pub2 := priv2.PubKey() + require.Equal(t, pub, pub2) + + // signing with the loaded key should match the original pubkey + sig = priv2.Sign(msg) + valid = pub.VerifyBytes(msg, sig) + assert.True(t, valid) + + // make sure pubkeys serialize properly as well + bs = pub.Bytes() + bpub, err := PubKeyFromBytes(bs) + require.NoError(t, err) + assert.Equal(t, pub, bpub) +} + // TestRealLedgerErrorHandling calls. These tests assume // the ledger is not plugged in.... func TestRealLedgerErrorHandling(t *testing.T) { From c689f38cb587be1d4681c19e7ebea7ec8e35794e Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 30 May 2018 22:07:20 +0200 Subject: [PATCH 247/273] Implement PubKeyLedgerEd25519 --- amino.go | 4 +++ ledger_ed25519.go | 2 +- ledger_pub_key.go | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 ledger_pub_key.go diff --git a/amino.go b/amino.go index 2af765434..b78a15ed9 100644 --- a/amino.go +++ b/amino.go @@ -19,6 +19,8 @@ func RegisterAmino(cdc *amino.Codec) { cdc.RegisterInterface((*PubKey)(nil), nil) cdc.RegisterConcrete(PubKeyEd25519{}, "tendermint/PubKeyEd25519", nil) + cdc.RegisterConcrete(PubKeyLedgerEd25519{}, + "tendermint/PubKeyLedgerEd25519", nil) cdc.RegisterConcrete(PubKeySecp256k1{}, "tendermint/PubKeySecp256k1", nil) @@ -29,6 +31,8 @@ func RegisterAmino(cdc *amino.Codec) { "tendermint/PrivKeySecp256k1", nil) cdc.RegisterConcrete(PrivKeyLedgerSecp256k1{}, "tendermint/PrivKeyLedgerSecp256k1", nil) + cdc.RegisterConcrete(PrivKeyLedgerEd25519{}, + "tendermint/PrivKeyLedgerEd25519", nil) cdc.RegisterInterface((*Signature)(nil), nil) cdc.RegisterConcrete(SignatureEd25519{}, diff --git a/ledger_ed25519.go b/ledger_ed25519.go index 0c9cd157f..2110b8871 100644 --- a/ledger_ed25519.go +++ b/ledger_ed25519.go @@ -13,7 +13,7 @@ func pubkeyLedgerEd25519(device *ledger.Ledger, path DerivationPath) (pub PubKey if err != nil { return pub, fmt.Errorf("Error fetching public key: %v", err) } - var p PubKeyEd25519 + var p PubKeyLedgerEd25519 copy(p[:], key[0:32]) return p, err } diff --git a/ledger_pub_key.go b/ledger_pub_key.go new file mode 100644 index 000000000..0a5222577 --- /dev/null +++ b/ledger_pub_key.go @@ -0,0 +1,68 @@ +package crypto + +import ( + "bytes" + "crypto/sha512" + "fmt" + + "github.com/tendermint/ed25519" + "github.com/tendermint/ed25519/extra25519" + "golang.org/x/crypto/ripemd160" +) + +var _ PubKey = PubKeyLedgerEd25519{} + +// Implements PubKeyInner +type PubKeyLedgerEd25519 [32]byte + +func (pubKey PubKeyLedgerEd25519) Address() Address { + // append type byte + hasher := ripemd160.New() + hasher.Write(pubKey.Bytes()) // does not error + return Address(hasher.Sum(nil)) +} + +func (pubKey PubKeyLedgerEd25519) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(pubKey) + if err != nil { + panic(err) + } + return bz +} + +func (pubKey PubKeyLedgerEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { + // must verify sha512 hash of msg, no padding, for Ledger compatibility + sig, ok := sig_.(SignatureEd25519) + if !ok { + return false + } + pubKeyBytes := [32]byte(pubKey) + sigBytes := [64]byte(sig) + h := sha512.New() + h.Write(msg) + digest := h.Sum(nil) + return ed25519.Verify(&pubKeyBytes, digest, &sigBytes) +} + +// For use with golang/crypto/nacl/box +// If error, returns nil. +func (pubKey PubKeyLedgerEd25519) ToCurve25519() *[32]byte { + keyCurve25519, pubKeyBytes := new([32]byte), [32]byte(pubKey) + ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes) + if !ok { + return nil + } + return keyCurve25519 +} + +func (pubKey PubKeyLedgerEd25519) String() string { + return fmt.Sprintf("PubKeyLedgerEd25519{%X}", pubKey[:]) +} + +func (pubKey PubKeyLedgerEd25519) Equals(other PubKey) bool { + if otherEd, ok := other.(PubKeyLedgerEd25519); ok { + return bytes.Equal(pubKey[:], otherEd[:]) + } else { + return false + } +} From bb81e4aa5f88218d5b2c478e133909908a5619b4 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 30 May 2018 22:16:30 +0200 Subject: [PATCH 248/273] Pin to an upstream revision --- Gopkg.lock | 3 +-- Gopkg.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 332714ee4..2090ac2e3 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -154,7 +154,6 @@ revision = "8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc" [[projects]] - branch = "master" name = "github.com/zondax/ledger-goclient" packages = ["."] revision = "3e2146609cdb97894c064d59e9d00accd8c2b1dd" @@ -178,6 +177,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "f3cfb54414cb9d59bab79226c7778673e7ac5b7a464baf9b2ea76c1f2563631e" + inputs-digest = "365c3bca75ced49eb0ebcdc5c98fd47b534850684fcc94c16d1bc6a671116395" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 3737ec5f9..10931a1a6 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -59,7 +59,7 @@ [[constraint]] name = "github.com/zondax/ledger-goclient" - branch = "master" + revision = "3e2146609cdb97894c064d59e9d00accd8c2b1dd" [prune] go-tests = true From 9f04935caa0ba104421c5c856bae92d5307e3869 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Tue, 22 May 2018 13:05:27 -0400 Subject: [PATCH 249/273] merkle: remove unused funcs. unexport simplemap. improv docs --- merkle/simple_map.go | 44 ++++++++++-------- merkle/simple_map_test.go | 17 ++++--- merkle/simple_proof.go | 18 ++++++-- merkle/simple_tree.go | 93 ++++++++++++-------------------------- merkle/simple_tree_test.go | 3 +- merkle/types.go | 2 + tmhash/hash.go | 2 +- 7 files changed, 84 insertions(+), 95 deletions(-) diff --git a/merkle/simple_map.go b/merkle/simple_map.go index 41d1ccd56..b073ecdd6 100644 --- a/merkle/simple_map.go +++ b/merkle/simple_map.go @@ -5,23 +5,27 @@ import ( "github.com/tendermint/go-crypto/tmhash" ) -type SimpleMap struct { +// Merkle tree from a map. +// Leaves are `hash(key) | hash(value)`. +// Leaves are sorted before Merkle hashing. +type simpleMap struct { kvs cmn.KVPairs sorted bool } -func NewSimpleMap() *SimpleMap { - return &SimpleMap{ +func newSimpleMap() *simpleMap { + return &simpleMap{ kvs: nil, sorted: false, } } -func (sm *SimpleMap) Set(key string, value Hasher) { +// Set hashes the key and value and appends it to the kv pairs. +func (sm *simpleMap) Set(key string, value Hasher) { sm.sorted = false // Hash the key to blind it... why not? - khash := SimpleHashFromBytes([]byte(key)) + khash := tmhash.Sum([]byte(key)) // And the value is hashed too, so you can // check for equality with a cached value (say) @@ -34,14 +38,14 @@ func (sm *SimpleMap) Set(key string, value Hasher) { }) } -// Merkle root hash of items sorted by key +// Hash Merkle root hash of items sorted by key // (UNSTABLE: and by value too if duplicate key). -func (sm *SimpleMap) Hash() []byte { +func (sm *simpleMap) Hash() []byte { sm.Sort() return hashKVPairs(sm.kvs) } -func (sm *SimpleMap) Sort() { +func (sm *simpleMap) Sort() { if sm.sorted { return } @@ -50,7 +54,8 @@ func (sm *SimpleMap) Sort() { } // Returns a copy of sorted KVPairs. -func (sm *SimpleMap) KVPairs() cmn.KVPairs { +// NOTE these contain the hashed key and value. +func (sm *simpleMap) KVPairs() cmn.KVPairs { sm.Sort() kvs := make(cmn.KVPairs, len(sm.kvs)) copy(kvs, sm.kvs) @@ -60,25 +65,28 @@ func (sm *SimpleMap) KVPairs() cmn.KVPairs { //---------------------------------------- // A local extension to KVPair that can be hashed. -type KVPair cmn.KVPair +// XXX: key and value do not need to already be hashed - +// the kvpair ("abc", "def") would not give the same result +// as ("ab", "cdef") as we're using length-prefixing. +type kvPair cmn.KVPair -func (kv KVPair) Hash() []byte { +func (kv kvPair) Hash() []byte { hasher := tmhash.New() err := encodeByteSlice(hasher, kv.Key) if err != nil { - panic(err) - } + panic(err) + } err = encodeByteSlice(hasher, kv.Value) if err != nil { - panic(err) - } + panic(err) + } return hasher.Sum(nil) } func hashKVPairs(kvs cmn.KVPairs) []byte { - kvsH := make([]Hasher, 0, len(kvs)) - for _, kvp := range kvs { - kvsH = append(kvsH, KVPair(kvp)) + kvsH := make([]Hasher, len(kvs)) + for i, kvp := range kvs { + kvsH[i] = kvPair(kvp) } return SimpleHashFromHashers(kvsH) } diff --git a/merkle/simple_map_test.go b/merkle/simple_map_test.go index 6e1004db2..9d0c25a2a 100644 --- a/merkle/simple_map_test.go +++ b/merkle/simple_map_test.go @@ -5,46 +5,49 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/tendermint/go-crypto/tmhash" ) type strHasher string func (str strHasher) Hash() []byte { - return SimpleHashFromBytes([]byte(str)) + h := tmhash.New() + h.Write([]byte(str)) + return h.Sum(nil) } func TestSimpleMap(t *testing.T) { { - db := NewSimpleMap() + db := newSimpleMap() db.Set("key1", strHasher("value1")) assert.Equal(t, "3dafc06a52039d029be57c75c9d16356a4256ef4", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { - db := NewSimpleMap() + db := newSimpleMap() db.Set("key1", strHasher("value2")) assert.Equal(t, "03eb5cfdff646bc4e80fec844e72fd248a1c6b2c", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { - db := NewSimpleMap() + db := newSimpleMap() db.Set("key1", strHasher("value1")) db.Set("key2", strHasher("value2")) assert.Equal(t, "acc3971eab8513171cc90ce8b74f368c38f9657d", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { - db := NewSimpleMap() + db := newSimpleMap() db.Set("key2", strHasher("value2")) // NOTE: out of order db.Set("key1", strHasher("value1")) assert.Equal(t, "acc3971eab8513171cc90ce8b74f368c38f9657d", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { - db := NewSimpleMap() + db := newSimpleMap() db.Set("key1", strHasher("value1")) db.Set("key2", strHasher("value2")) db.Set("key3", strHasher("value3")) assert.Equal(t, "0cd117ad14e6cd22edcd9aa0d84d7063b54b862f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { - db := NewSimpleMap() + db := newSimpleMap() db.Set("key2", strHasher("value2")) // NOTE: out of order db.Set("key1", strHasher("value1")) db.Set("key3", strHasher("value3")) diff --git a/merkle/simple_proof.go b/merkle/simple_proof.go index ca6ccf372..f52d1ad9f 100644 --- a/merkle/simple_proof.go +++ b/merkle/simple_proof.go @@ -5,10 +5,12 @@ import ( "fmt" ) +// SimpleProof represents a simple merkle proof. type SimpleProof struct { Aunts [][]byte `json:"aunts"` // Hashes from leaf's sibling to a root's child. } +// SimpleProofsFromHashers computes inclusion proof for given items. // proofs[0] is the proof for items[0]. func SimpleProofsFromHashers(items []Hasher) (rootHash []byte, proofs []*SimpleProof) { trails, rootSPN := trailsFromHashers(items) @@ -22,8 +24,11 @@ func SimpleProofsFromHashers(items []Hasher) (rootHash []byte, proofs []*SimpleP return } +// SimpleProofsFromMap generates proofs from a map. The keys/values of the map will be used as the keys/values +// in the underlying key-value pairs. +// The keys are sorted before the proofs are computed. func SimpleProofsFromMap(m map[string]Hasher) (rootHash []byte, proofs []*SimpleProof) { - sm := NewSimpleMap() + sm := newSimpleMap() for k, v := range m { sm.Set(k, v) } @@ -31,7 +36,7 @@ func SimpleProofsFromMap(m map[string]Hasher) (rootHash []byte, proofs []*Simple kvs := sm.kvs kvsH := make([]Hasher, 0, len(kvs)) for _, kvp := range kvs { - kvsH = append(kvsH, KVPair(kvp)) + kvsH = append(kvsH, kvPair(kvp)) } return SimpleProofsFromHashers(kvsH) } @@ -43,10 +48,13 @@ func (sp *SimpleProof) Verify(index int, total int, leafHash []byte, rootHash [] return computedHash != nil && bytes.Equal(computedHash, rootHash) } +// String implements the stringer interface for SimpleProof. +// It is a wrapper around StringIndented. func (sp *SimpleProof) String() string { return sp.StringIndented("") } +// StringIndented generates a canonical string representation of a SimpleProof. func (sp *SimpleProof) StringIndented(indent string) string { return fmt.Sprintf(`SimpleProof{ %s Aunts: %X @@ -90,7 +98,7 @@ func computeHashFromAunts(index int, total int, leafHash []byte, innerHashes [][ } } -// Helper structure to construct merkle proof. +// SimpleProofNode is a helper structure to construct merkle proof. // The node and the tree is thrown away afterwards. // Exactly one of node.Left and node.Right is nil, unless node is the root, in which case both are nil. // node.Parent.Hash = hash(node.Hash, node.Right.Hash) or @@ -102,8 +110,8 @@ type SimpleProofNode struct { Right *SimpleProofNode // Right sibling (only one of Left,Right is set) } -// Starting from a leaf SimpleProofNode, FlattenAunts() will return -// the inner hashes for the item corresponding to the leaf. +// FlattenAunts will return the inner hashes for the item corresponding to the leaf, +// starting from a leaf SimpleProofNode. func (spn *SimpleProofNode) FlattenAunts() [][]byte { // Nonrecursive impl. innerHashes := [][]byte{} diff --git a/merkle/simple_tree.go b/merkle/simple_tree.go index 3c31b1337..c23f84264 100644 --- a/merkle/simple_tree.go +++ b/merkle/simple_tree.go @@ -1,91 +1,58 @@ -/* -Computes a deterministic minimal height merkle tree hash. -If the number of items is not a power of two, some leaves -will be at different levels. Tries to keep both sides of -the tree the same size, but the left may be one greater. - -Use this for short deterministic trees, such as the validator list. -For larger datasets, use IAVLTree. - - * - / \ - / \ - / \ - / \ - * * - / \ / \ - / \ / \ - / \ / \ - * * * h6 - / \ / \ / \ - h0 h1 h2 h3 h4 h5 - -*/ - package merkle import ( "github.com/tendermint/go-crypto/tmhash" ) -func SimpleHashFromTwoHashes(left []byte, right []byte) []byte { +// SimpleHashFromTwoHashes is the basic operation of the Merkle tree: Hash(left | right). +func SimpleHashFromTwoHashes(left, right []byte) []byte { var hasher = tmhash.New() err := encodeByteSlice(hasher, left) if err != nil { - panic(err) - } + panic(err) + } err = encodeByteSlice(hasher, right) if err != nil { - panic(err) - } - return hasher.Sum(nil) -} - -func SimpleHashFromHashes(hashes [][]byte) []byte { - // Recursive impl. - switch len(hashes) { - case 0: - return nil - case 1: - return hashes[0] - default: - left := SimpleHashFromHashes(hashes[:(len(hashes)+1)/2]) - right := SimpleHashFromHashes(hashes[(len(hashes)+1)/2:]) - return SimpleHashFromTwoHashes(left, right) - } -} - -// NOTE: Do not implement this, use SimpleHashFromByteslices instead. -// type Byteser interface { Bytes() []byte } -// func SimpleHashFromBytesers(items []Byteser) []byte { ... } - -func SimpleHashFromByteslices(bzs [][]byte) []byte { - hashes := make([][]byte, len(bzs)) - for i, bz := range bzs { - hashes[i] = SimpleHashFromBytes(bz) - } - return SimpleHashFromHashes(hashes) -} - -func SimpleHashFromBytes(bz []byte) []byte { - hasher := tmhash.New() - hasher.Write(bz) + panic(err) + } return hasher.Sum(nil) } +// SimpleHashFromHashers computes a Merkle tree from items that can be hashed. func SimpleHashFromHashers(items []Hasher) []byte { hashes := make([][]byte, len(items)) for i, item := range items { hash := item.Hash() hashes[i] = hash } - return SimpleHashFromHashes(hashes) + return simpleHashFromHashes(hashes) } +// SimpleHashFromMap computes a Merkle tree from sorted map. +// Like calling SimpleHashFromHashers with +// `item = []byte(Hash(key) | Hash(value))`, +// sorted by `item`. func SimpleHashFromMap(m map[string]Hasher) []byte { - sm := NewSimpleMap() + sm := newSimpleMap() for k, v := range m { sm.Set(k, v) } return sm.Hash() } + +//---------------------------------------------------------------- + +// Expects hashes! +func simpleHashFromHashes(hashes [][]byte) []byte { + // Recursive impl. + switch len(hashes) { + case 0: + return nil + case 1: + return hashes[0] + default: + left := simpleHashFromHashes(hashes[:(len(hashes)+1)/2]) + right := simpleHashFromHashes(hashes[(len(hashes)+1)/2:]) + return SimpleHashFromTwoHashes(left, right) + } +} diff --git a/merkle/simple_tree_test.go b/merkle/simple_tree_test.go index 8c4ed01f8..db8e3d7ff 100644 --- a/merkle/simple_tree_test.go +++ b/merkle/simple_tree_test.go @@ -7,6 +7,7 @@ import ( . "github.com/tendermint/tmlibs/test" "testing" + "github.com/tendermint/go-crypto/tmhash" ) type testItem []byte @@ -21,7 +22,7 @@ func TestSimpleProof(t *testing.T) { items := make([]Hasher, total) for i := 0; i < total; i++ { - items[i] = testItem(cmn.RandBytes(32)) + items[i] = testItem(cmn.RandBytes(tmhash.Size)) } rootHash := SimpleHashFromHashers(items) diff --git a/merkle/types.go b/merkle/types.go index a0c491a7e..ddc420659 100644 --- a/merkle/types.go +++ b/merkle/types.go @@ -5,6 +5,7 @@ import ( "io" ) +// Tree is a Merkle tree interface. type Tree interface { Size() (size int) Height() (height int8) @@ -23,6 +24,7 @@ type Tree interface { IterateRange(start []byte, end []byte, ascending bool, fx func(key []byte, value []byte) (stop bool)) (stopped bool) } +// Hasher represents a hashable piece of data which can be hashed in the Tree. type Hasher interface { Hash() []byte } diff --git a/tmhash/hash.go b/tmhash/hash.go index 9f684ce01..1b29d8680 100644 --- a/tmhash/hash.go +++ b/tmhash/hash.go @@ -5,7 +5,7 @@ import ( "hash" ) -var ( +const ( Size = 20 BlockSize = sha256.BlockSize ) From 862d3c342a03861c74cfbc649439cc81ceff5396 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 30 May 2018 17:28:20 +0100 Subject: [PATCH 250/273] commit doc.go --- merkle/doc.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 merkle/doc.go diff --git a/merkle/doc.go b/merkle/doc.go new file mode 100644 index 000000000..da65dd858 --- /dev/null +++ b/merkle/doc.go @@ -0,0 +1,31 @@ +/* +Package merkle computes a deterministic minimal height Merkle tree hash. +If the number of items is not a power of two, some leaves +will be at different levels. Tries to keep both sides of +the tree the same size, but the left may be one greater. + +Use this for short deterministic trees, such as the validator list. +For larger datasets, use IAVLTree. + +Be aware that the current implementation by itself does not prevent +second pre-image attacks. Hence, use this library with caution. +Otherwise you might run into similar issues as, e.g., in early Bitcoin: +https://bitcointalk.org/?topic=102395 + + * + / \ + / \ + / \ + / \ + * * + / \ / \ + / \ / \ + / \ / \ + * * * h6 + / \ / \ / \ + h0 h1 h2 h3 h4 h5 + +TODO(ismail): add 2nd pre-image protection or clarify further on how we use this and why this secure. + +*/ +package merkle \ No newline at end of file From 52bd867fd918513e7cab9d57cf4fdf9c78396a03 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 30 May 2018 17:50:17 -0400 Subject: [PATCH 251/273] merkle: use amino for byteslice encoding --- merkle/simple_map.go | 15 +++++++-------- merkle/simple_map_test.go | 4 +--- merkle/types.go | 19 ++++--------------- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/merkle/simple_map.go b/merkle/simple_map.go index b073ecdd6..cde5924f4 100644 --- a/merkle/simple_map.go +++ b/merkle/simple_map.go @@ -1,8 +1,8 @@ package merkle import ( - cmn "github.com/tendermint/tmlibs/common" "github.com/tendermint/go-crypto/tmhash" + cmn "github.com/tendermint/tmlibs/common" ) // Merkle tree from a map. @@ -65,21 +65,20 @@ func (sm *simpleMap) KVPairs() cmn.KVPairs { //---------------------------------------- // A local extension to KVPair that can be hashed. -// XXX: key and value do not need to already be hashed - -// the kvpair ("abc", "def") would not give the same result -// as ("ab", "cdef") as we're using length-prefixing. +// Key and value are length prefixed and concatenated, +// then hashed. type kvPair cmn.KVPair func (kv kvPair) Hash() []byte { hasher := tmhash.New() err := encodeByteSlice(hasher, kv.Key) if err != nil { - panic(err) - } + panic(err) + } err = encodeByteSlice(hasher, kv.Value) if err != nil { - panic(err) - } + panic(err) + } return hasher.Sum(nil) } diff --git a/merkle/simple_map_test.go b/merkle/simple_map_test.go index 9d0c25a2a..a89289a8f 100644 --- a/merkle/simple_map_test.go +++ b/merkle/simple_map_test.go @@ -11,9 +11,7 @@ import ( type strHasher string func (str strHasher) Hash() []byte { - h := tmhash.New() - h.Write([]byte(str)) - return h.Sum(nil) + return tmhash.Sum([]byte(str)) } func TestSimpleMap(t *testing.T) { diff --git a/merkle/types.go b/merkle/types.go index ddc420659..2fcb3f39d 100644 --- a/merkle/types.go +++ b/merkle/types.go @@ -1,8 +1,9 @@ package merkle import ( - "encoding/binary" "io" + + amino "github.com/tendermint/go-amino" ) // Tree is a Merkle tree interface. @@ -30,20 +31,8 @@ type Hasher interface { } //----------------------------------------------------------------------- -// NOTE: these are duplicated from go-amino so we dont need go-amino as a dep +// Uvarint length prefixed byteslice func encodeByteSlice(w io.Writer, bz []byte) (err error) { - err = encodeUvarint(w, uint64(len(bz))) - if err != nil { - return - } - _, err = w.Write(bz) - return -} - -func encodeUvarint(w io.Writer, i uint64) (err error) { - var buf [10]byte - n := binary.PutUvarint(buf[:], i) - _, err = w.Write(buf[0:n]) - return + return amino.EncodeByteSlice(w, bz) } From 20fdec6c0efd1d1387e4177ab82efea67b2dadf1 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 30 May 2018 18:34:11 -0400 Subject: [PATCH 252/273] fix comment --- keys/keybase.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keys/keybase.go b/keys/keybase.go index 876eef8f5..dd9726478 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -159,7 +159,7 @@ func (kb dbKeybase) Import(name string, armor string) (err error) { return nil } -// ExportPubKey imports ASCII-armored public keys. +// ImportPubKey imports ASCII-armored public keys. // Store a new Info object holding a public key only, i.e. it will // not be possible to sign with it as it lacks the secret key. func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) { From 21b821d661ea22a2001bb9f394188ba98c07ad03 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 30 May 2018 18:41:08 -0400 Subject: [PATCH 253/273] SignatureKey -> Signature --- amino.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/amino.go b/amino.go index 89636895a..5b9d28994 100644 --- a/amino.go +++ b/amino.go @@ -30,7 +30,7 @@ func RegisterAmino(cdc *amino.Codec) { cdc.RegisterInterface((*Signature)(nil), nil) cdc.RegisterConcrete(SignatureEd25519{}, - "tendermint/SignatureKeyEd25519", nil) + "tendermint/SignatureEd25519", nil) cdc.RegisterConcrete(SignatureSecp256k1{}, - "tendermint/SignatureKeySecp256k1", nil) + "tendermint/SignatureSecp256k1", nil) } From 970693523338af9e9cd6e344c4c9500ef517c159 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 30 May 2018 18:57:53 -0400 Subject: [PATCH 254/273] fix link in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a524c014..959290573 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ go-crypto is the cryptographic package adapted for Tendermint's uses ## Binary encoding -For Binary encoding, please refer to the [Tendermint encoding spec](https://github.com/tendermint/tendermint/blob/develop/docs/specification/new-spec/encoding.md). +For Binary encoding, please refer to the [Tendermint encoding spec](https://github.com/tendermint/tendermint/blob/develop/docs/spec/blockchain/encoding.md). ## JSON Encoding From e1ce3ffe0fd100816e597d842ee6e476dd320b9c Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Wed, 30 May 2018 20:48:52 -0400 Subject: [PATCH 255/273] changelog and version --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ version.go | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91dcfab52..5db3a6109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## 0.7.0 + +**May 30th, 2018** + +BREAKING CHANGES + +No breaking changes compared to 0.6.2, but making up for the version bump that +should have happened in 0.6.1. + +We also bring in the `tmlibs/merkle` package with breaking changes: + +- change the hash function from RIPEMD160 to tmhash (first 20-bytes of SHA256) +- remove unused funcs and unexport SimpleMap + +FEATURES + +- [xchacha20poly1305] New authenticated encryption module +- [merkle] Moved in from tmlibs +- [merkle/tmhash] New hash function: the first 20-bytes of SHA256 + +IMPROVEMENTS + +- Remove some dead code +- Use constant-time compare for signatures + +BUG FIXES + +- Fix MixEntropy weakness +- Fix PrivKeyEd25519.Generate() + ## 0.6.2 (April 9, 2018) IMPROVEMENTS diff --git a/version.go b/version.go index aac87c4f3..4cf5685a5 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.6.2" +const Version = "0.7.0" From 63aac6559032f9fbc1a6a94b2a20ae9b30de0f65 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 31 May 2018 21:21:50 +0200 Subject: [PATCH 256/273] Remove Ledger ed25519 support, for now --- amino.go | 4 -- ledger_ed25519.go | 156 ---------------------------------------------- ledger_pub_key.go | 68 -------------------- ledger_test.go | 38 ----------- 4 files changed, 266 deletions(-) delete mode 100644 ledger_ed25519.go delete mode 100644 ledger_pub_key.go diff --git a/amino.go b/amino.go index b78a15ed9..2af765434 100644 --- a/amino.go +++ b/amino.go @@ -19,8 +19,6 @@ func RegisterAmino(cdc *amino.Codec) { cdc.RegisterInterface((*PubKey)(nil), nil) cdc.RegisterConcrete(PubKeyEd25519{}, "tendermint/PubKeyEd25519", nil) - cdc.RegisterConcrete(PubKeyLedgerEd25519{}, - "tendermint/PubKeyLedgerEd25519", nil) cdc.RegisterConcrete(PubKeySecp256k1{}, "tendermint/PubKeySecp256k1", nil) @@ -31,8 +29,6 @@ func RegisterAmino(cdc *amino.Codec) { "tendermint/PrivKeySecp256k1", nil) cdc.RegisterConcrete(PrivKeyLedgerSecp256k1{}, "tendermint/PrivKeyLedgerSecp256k1", nil) - cdc.RegisterConcrete(PrivKeyLedgerEd25519{}, - "tendermint/PrivKeyLedgerEd25519", nil) cdc.RegisterInterface((*Signature)(nil), nil) cdc.RegisterConcrete(SignatureEd25519{}, diff --git a/ledger_ed25519.go b/ledger_ed25519.go deleted file mode 100644 index 2110b8871..000000000 --- a/ledger_ed25519.go +++ /dev/null @@ -1,156 +0,0 @@ -package crypto - -import ( - "fmt" - "github.com/pkg/errors" - - // "github.com/tendermint/ed25519" - ledger "github.com/zondax/ledger-goclient" -) - -func pubkeyLedgerEd25519(device *ledger.Ledger, path DerivationPath) (pub PubKey, err error) { - key, err := device.GetPublicKeyED25519(path) - if err != nil { - return pub, fmt.Errorf("Error fetching public key: %v", err) - } - var p PubKeyLedgerEd25519 - copy(p[:], key[0:32]) - return p, err -} - -func signLedgerEd25519(device *ledger.Ledger, path DerivationPath, msg []byte) (sig Signature, err error) { - bsig, err := device.SignED25519(path, msg) - if err != nil { - return sig, err - } - sig = SignatureEd25519FromBytes(bsig) - return sig, nil -} - -// PrivKeyLedgerEd25519 implements PrivKey, calling the ledger nano -// we cache the PubKey from the first call to use it later -type PrivKeyLedgerEd25519 struct { - // PubKey should be private, but we want to encode it via go-amino - // so we can view the address later, even without having the ledger - // attached - CachedPubKey PubKey - Path DerivationPath -} - -// NewPrivKeyLedgerEd25519 will generate a new key and store the -// public key for later use. -func NewPrivKeyLedgerEd25519(path DerivationPath) (PrivKey, error) { - var pk PrivKeyLedgerEd25519 - pk.Path = path - // getPubKey will cache the pubkey for later use, - // this allows us to return an error early if the ledger - // is not plugged in - _, err := pk.getPubKey() - return &pk, err -} - -// ValidateKey allows us to verify the sanity of a key -// after loading it from disk -func (pk PrivKeyLedgerEd25519) ValidateKey() error { - // getPubKey will return an error if the ledger is not - // properly set up... - pub, err := pk.forceGetPubKey() - if err != nil { - return err - } - // verify this matches cached address - if !pub.Equals(pk.CachedPubKey) { - return errors.New("Cached key does not match retrieved key") - } - return nil -} - -// AssertIsPrivKeyInner fulfils PrivKey Interface -func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} - -// Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify -// the same key when we reconnect to a ledger -func (pk PrivKeyLedgerEd25519) Bytes() []byte { - bin, err := cdc.MarshalBinaryBare(pk) - if err != nil { - panic(err) - } - return bin -} - -// Sign calls the ledger and stores the PubKey for future use -// -// XXX/TODO: panics if there is an error communicating with the ledger. -// -// Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, -// returning an error, so this should only trigger if the privkey is held -// in memory for a while before use. -func (pk PrivKeyLedgerEd25519) Sign(msg []byte) Signature { - // oh, I wish there was better error handling - dev, err := getLedger() - if err != nil { - panic(err) - } - - sig, err := signLedgerEd25519(dev, pk.Path, msg) - if err != nil { - panic(err) - } - - pub, err := pubkeyLedgerEd25519(dev, pk.Path) - if err != nil { - panic(err) - } - - // if we have no pubkey yet, store it for future queries - if pk.CachedPubKey == nil { - pk.CachedPubKey = pub - } else if !pk.CachedPubKey.Equals(pub) { - panic("Stored key does not match signing key") - } - return sig -} - -// PubKey returns the stored PubKey -// TODO: query the ledger if not there, once it is not volatile -func (pk PrivKeyLedgerEd25519) PubKey() PubKey { - key, err := pk.getPubKey() - if err != nil { - panic(err) - } - return key -} - -// getPubKey reads the pubkey from cache or from the ledger itself -// since this involves IO, it may return an error, which is not exposed -// in the PubKey interface, so this function allows better error handling -func (pk PrivKeyLedgerEd25519) getPubKey() (key PubKey, err error) { - // if we have no pubkey, set it - if pk.CachedPubKey == nil { - pk.CachedPubKey, err = pk.forceGetPubKey() - } - return pk.CachedPubKey, err -} - -// forceGetPubKey is like getPubKey but ignores any cached key -// and ensures we get it from the ledger itself. -func (pk PrivKeyLedgerEd25519) forceGetPubKey() (key PubKey, err error) { - dev, err := getLedger() - if err != nil { - return key, errors.New(fmt.Sprintf("Cannot connect to Ledger device - error: %v", err)) - } - key, err = pubkeyLedgerEd25519(dev, pk.Path) - if err != nil { - return key, errors.New(fmt.Sprintf("Please open Cosmos app on the Ledger device - error: %v", err)) - } - return key, err -} - -// Equals fulfils PrivKey Interface - makes sure both keys refer to the -// same -func (pk PrivKeyLedgerEd25519) Equals(other PrivKey) bool { - if ledger, ok := other.(*PrivKeyLedgerEd25519); ok { - return pk.CachedPubKey.Equals(ledger.CachedPubKey) - } - return false -} diff --git a/ledger_pub_key.go b/ledger_pub_key.go deleted file mode 100644 index 0a5222577..000000000 --- a/ledger_pub_key.go +++ /dev/null @@ -1,68 +0,0 @@ -package crypto - -import ( - "bytes" - "crypto/sha512" - "fmt" - - "github.com/tendermint/ed25519" - "github.com/tendermint/ed25519/extra25519" - "golang.org/x/crypto/ripemd160" -) - -var _ PubKey = PubKeyLedgerEd25519{} - -// Implements PubKeyInner -type PubKeyLedgerEd25519 [32]byte - -func (pubKey PubKeyLedgerEd25519) Address() Address { - // append type byte - hasher := ripemd160.New() - hasher.Write(pubKey.Bytes()) // does not error - return Address(hasher.Sum(nil)) -} - -func (pubKey PubKeyLedgerEd25519) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(pubKey) - if err != nil { - panic(err) - } - return bz -} - -func (pubKey PubKeyLedgerEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { - // must verify sha512 hash of msg, no padding, for Ledger compatibility - sig, ok := sig_.(SignatureEd25519) - if !ok { - return false - } - pubKeyBytes := [32]byte(pubKey) - sigBytes := [64]byte(sig) - h := sha512.New() - h.Write(msg) - digest := h.Sum(nil) - return ed25519.Verify(&pubKeyBytes, digest, &sigBytes) -} - -// For use with golang/crypto/nacl/box -// If error, returns nil. -func (pubKey PubKeyLedgerEd25519) ToCurve25519() *[32]byte { - keyCurve25519, pubKeyBytes := new([32]byte), [32]byte(pubKey) - ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes) - if !ok { - return nil - } - return keyCurve25519 -} - -func (pubKey PubKeyLedgerEd25519) String() string { - return fmt.Sprintf("PubKeyLedgerEd25519{%X}", pubKey[:]) -} - -func (pubKey PubKeyLedgerEd25519) Equals(other PubKey) bool { - if otherEd, ok := other.(PubKeyLedgerEd25519); ok { - return bytes.Equal(pubKey[:], otherEd[:]) - } else { - return false - } -} diff --git a/ledger_test.go b/ledger_test.go index a0ea35837..dda3d3d3d 100644 --- a/ledger_test.go +++ b/ledger_test.go @@ -46,44 +46,6 @@ func TestRealLedgerSecp256k1(t *testing.T) { assert.Equal(t, pub, bpub) } -func TestRealLedgerEd25519(t *testing.T) { - - if os.Getenv("WITH_LEDGER") == "" { - t.Skip("Set WITH_LEDGER to run code on real ledger") - } - msg := []byte("kuhehfeohg") - - path := DerivationPath{44, 60, 0, 0, 0} - - priv, err := NewPrivKeyLedgerEd25519(path) - require.Nil(t, err, "%+v", err) - pub := priv.PubKey() - sig := priv.Sign(msg) - - valid := pub.VerifyBytes(msg, sig) - assert.True(t, valid) - - // now, let's serialize the key and make sure it still works - bs := priv.Bytes() - priv2, err := PrivKeyFromBytes(bs) - require.Nil(t, err, "%+v", err) - - // make sure we get the same pubkey when we load from disk - pub2 := priv2.PubKey() - require.Equal(t, pub, pub2) - - // signing with the loaded key should match the original pubkey - sig = priv2.Sign(msg) - valid = pub.VerifyBytes(msg, sig) - assert.True(t, valid) - - // make sure pubkeys serialize properly as well - bs = pub.Bytes() - bpub, err := PubKeyFromBytes(bs) - require.NoError(t, err) - assert.Equal(t, pub, bpub) -} - // TestRealLedgerErrorHandling calls. These tests assume // the ledger is not plugged in.... func TestRealLedgerErrorHandling(t *testing.T) { From 80e97522504e79dca2f0e2c35168e6f47dc307ce Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 31 May 2018 21:30:20 +0200 Subject: [PATCH 257/273] Move TODOs to #114 --- Gopkg.lock | 4 ++-- ledger_secp256k1.go | 19 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 2090ac2e3..f51e2b229 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -11,7 +11,7 @@ branch = "master" name = "github.com/btcsuite/btcd" packages = ["btcec"] - revision = "bc0944904505aab55e089371a892be2f87883161" + revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64" [[projects]] branch = "master" @@ -172,7 +172,7 @@ "ripemd160", "salsa20/salsa" ] - revision = "ab813273cd59e1333f7ae7bff5d027d4aadf528c" + revision = "5ba7f63082460102a45837dbd1827e10f9479ac0" [solve-meta] analyzer-name = "dep" diff --git a/ledger_secp256k1.go b/ledger_secp256k1.go index b574035d4..f485bb415 100644 --- a/ledger_secp256k1.go +++ b/ledger_secp256k1.go @@ -2,7 +2,6 @@ package crypto import ( "fmt" - "github.com/pkg/errors" secp256k1 "github.com/btcsuite/btcd/btcec" ledger "github.com/zondax/ledger-goclient" @@ -11,13 +10,14 @@ import ( func pubkeyLedgerSecp256k1(device *ledger.Ledger, path DerivationPath) (pub PubKey, err error) { key, err := device.GetPublicKeySECP256K1(path) if err != nil { - return pub, fmt.Errorf("Error fetching public key: %v", err) + return nil, fmt.Errorf("error fetching public key: %v", err) } var p PubKeySecp256k1 // Reserialize in the 33-byte compressed format cmp, err := secp256k1.ParsePubKey(key[:], secp256k1.S256()) copy(p[:], cmp.SerializeCompressed()) - return p, err + pub = p + return } func signLedgerSecp256k1(device *ledger.Ledger, path DerivationPath, msg []byte) (sig Signature, err error) { @@ -26,7 +26,7 @@ func signLedgerSecp256k1(device *ledger.Ledger, path DerivationPath, msg []byte) return sig, err } sig = SignatureSecp256k1FromBytes(bsig) - return sig, nil + return } // PrivKeyLedgerSecp256k1 implements PrivKey, calling the ledger nano @@ -62,7 +62,7 @@ func (pk PrivKeyLedgerSecp256k1) ValidateKey() error { } // verify this matches cached address if !pub.Equals(pk.CachedPubKey) { - return errors.New("Cached key does not match retrieved key") + return fmt.Errorf("cached key does not match retrieved key") } return nil } @@ -82,8 +82,6 @@ func (pk PrivKeyLedgerSecp256k1) Bytes() []byte { // Sign calls the ledger and stores the PubKey for future use // -// XXX/TODO: panics if there is an error communicating with the ledger. -// // Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, // returning an error, so this should only trigger if the privkey is held // in memory for a while before use. @@ -108,13 +106,12 @@ func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) Signature { if pk.CachedPubKey == nil { pk.CachedPubKey = pub } else if !pk.CachedPubKey.Equals(pub) { - panic("Stored key does not match signing key") + panic("stored key does not match signing key") } return sig } // PubKey returns the stored PubKey -// TODO: query the ledger if not there, once it is not volatile func (pk PrivKeyLedgerSecp256k1) PubKey() PubKey { key, err := pk.getPubKey() if err != nil { @@ -139,11 +136,11 @@ func (pk PrivKeyLedgerSecp256k1) getPubKey() (key PubKey, err error) { func (pk PrivKeyLedgerSecp256k1) forceGetPubKey() (key PubKey, err error) { dev, err := getLedger() if err != nil { - return key, errors.New(fmt.Sprintf("Cannot connect to Ledger device - error: %v", err)) + return key, fmt.Errorf("cannot connect to Ledger device - error: %v", err) } key, err = pubkeyLedgerSecp256k1(dev, pk.Path) if err != nil { - return key, errors.New(fmt.Sprintf("Please open Cosmos app on the Ledger device - error: %v", err)) + return key, fmt.Errorf("please open Cosmos app on the Ledger device - error: %v", err) } return key, err } From 854eb323ddb27d10eddc7dfb36e91e98165dd6c2 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Fri, 8 Jun 2018 17:28:50 -0700 Subject: [PATCH 258/273] dev version bump --- CHANGELOG.md | 4 ++++ version.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5db3a6109..4c31551b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.8.0 + +**TBD** + ## 0.7.0 **May 30th, 2018** diff --git a/version.go b/version.go index 4cf5685a5..57806e26c 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.7.0" +const Version = "0.8.0-dev" From c21f67c5af7fef3ca064fa578084a73ac9fdfb81 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Sun, 10 Jun 2018 10:01:41 +0200 Subject: [PATCH 259/273] Unify local and external keys in keybase interface (#117) * Return errors on priv.Sign(), priv.PubKey() * Add CreateLedger, CreateOffline * Add switch on .Sign() for Ledger wallets * Add offline signing switch on .Sign() * Use MustUnmarshalBinaryBare() * Add confirmation to delete offline/Ledger keys * Lowercase error message * Add human-readable .GetType() function to Info interface * Rename CryptoAlgo => SignAlgo * assert.Nil(t, err) => assert.NoError(t, err) --- Gopkg.lock | 23 ++++-- Gopkg.toml | 3 +- encode_test.go | 6 +- keys/keybase.go | 168 ++++++++++++++++++++++++++++++++----------- keys/keybase_test.go | 147 ++++++++++++++++++++----------------- keys/keys.go | 10 +-- keys/types.go | 124 ++++++++++++++++++++++++++------ keys/wire.go | 4 ++ ledger_secp256k1.go | 27 +++---- ledger_test.go | 12 ++-- priv_key.go | 47 ++++-------- priv_key_test.go | 6 +- pub_key_test.go | 6 +- signature_test.go | 18 +++-- 14 files changed, 391 insertions(+), 210 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index f51e2b229..24b638a55 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -119,7 +119,7 @@ "leveldb/table", "leveldb/util" ] - revision = "5d6fca44a948d2be89a9702de7717f0168403d3d" + revision = "e2150783cd35f5b607daca48afd8c57ec54cc995" [[projects]] branch = "master" @@ -142,10 +142,11 @@ packages = [ "common", "db", - "log" + "log", + "test" ] - revision = "d970af87248a4e162590300dbb74e102183a417d" - version = "v0.8.3" + revision = "692f1d86a6e2c0efa698fd1e4541b68c74ffaf38" + version = "v0.8.4" [[projects]] branch = "master" @@ -156,7 +157,7 @@ [[projects]] name = "github.com/zondax/ledger-goclient" packages = ["."] - revision = "3e2146609cdb97894c064d59e9d00accd8c2b1dd" + revision = "065cbf938a16f20335c40cfe180f9cd4955c6a5a" [[projects]] branch = "master" @@ -164,6 +165,8 @@ packages = [ "bcrypt", "blowfish", + "chacha20poly1305", + "internal/chacha20", "nacl/secretbox", "openpgp/armor", "openpgp/errors", @@ -172,11 +175,17 @@ "ripemd160", "salsa20/salsa" ] - revision = "5ba7f63082460102a45837dbd1827e10f9479ac0" + revision = "8ac0e0d97ce45cd83d1d7243c060cb8461dda5e9" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["cpu"] + revision = "9527bec2660bd847c050fda93a0f0c6dee0800bb" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "365c3bca75ced49eb0ebcdc5c98fd47b534850684fcc94c16d1bc6a671116395" + inputs-digest = "f20e34cd998442d4ffe2f9aa45ab87a55ba6e4cd19f29009adaadac3b5dccf26" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 10931a1a6..d2b50e5a1 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -24,7 +24,6 @@ # go-tests = true # unused-packages = true - [[constraint]] name = "github.com/btcsuite/btcutil" branch = "master" @@ -59,7 +58,7 @@ [[constraint]] name = "github.com/zondax/ledger-goclient" - revision = "3e2146609cdb97894c064d59e9d00accd8c2b1dd" + revision = "065cbf938a16f20335c40cfe180f9cd4955c6a5a" [prune] go-tests = true diff --git a/encode_test.go b/encode_test.go index 0bd450829..f78d9439c 100644 --- a/encode_test.go +++ b/encode_test.go @@ -69,14 +69,16 @@ func TestKeyEncodings(t *testing.T) { // Check (de/en)codings of Signatures. var sig1, sig2, sig3 Signature - sig1 = tc.privKey.Sign([]byte("something")) + sig1, err := tc.privKey.Sign([]byte("something")) + assert.NoError(t, err) checkAminoBinary(t, sig1, &sig2, -1) // Siganture size changes for Secp anyways. assert.EqualValues(t, sig1, sig2) checkAminoJSON(t, sig1, &sig3, false) // TODO also check Prefix bytes. assert.EqualValues(t, sig1, sig3) // Check (de/en)codings of PubKeys. - pubKey := tc.privKey.PubKey() + pubKey, err := tc.privKey.PubKey() + assert.NoError(t, err) var pub2, pub3 PubKey checkAminoBinary(t, pubKey, &pub2, tc.pubSize) assert.EqualValues(t, pubKey, pub2) diff --git a/keys/keybase.go b/keys/keybase.go index dd9726478..39a3de59e 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -1,7 +1,9 @@ package keys import ( + "bufio" "fmt" + "os" "strings" "github.com/pkg/errors" @@ -26,23 +28,23 @@ func New(db dbm.DB, codec words.Codec) dbKeybase { var _ Keybase = dbKeybase{} -// Create generates a new key and persists it to storage, encrypted +// CreateMnemonic generates a new key and persists it to storage, encrypted // using the passphrase. It returns the generated seedphrase // (mnemonic) and the key Info. It returns an error if it fails to // generate a key for the given algo type, or if another key is // already stored under the same name. -func (kb dbKeybase) Create(name, passphrase string, algo CryptoAlgo) (Info, string, error) { +func (kb dbKeybase) CreateMnemonic(name, passphrase string, algo SignAlgo) (Info, string, error) { // NOTE: secret is SHA256 hashed by secp256k1 and ed25519. // 16 byte secret corresponds to 12 BIP39 words. // XXX: Ledgers use 24 words now - should we ? secret := crypto.CRandBytes(16) priv, err := generate(algo, secret) if err != nil { - return Info{}, "", err + return nil, "", err } // encrypt and persist the key - info := kb.writeKey(priv, name, passphrase) + info := kb.writeLocalKey(priv, name, passphrase) // we append the type byte to the serialized secret to help with // recovery @@ -56,6 +58,29 @@ func (kb dbKeybase) Create(name, passphrase string, algo CryptoAlgo) (Info, stri return info, seed, err } +// CreateLedger creates a new locally-stored reference to a Ledger keypair +// It returns the created key info and an error if the Ledger could not be queried +func (kb dbKeybase) CreateLedger(name string, path crypto.DerivationPath, algo SignAlgo) (Info, error) { + if algo != AlgoSecp256k1 { + return nil, fmt.Errorf("Only secp256k1 is supported for Ledger devices") + } + priv, err := crypto.NewPrivKeyLedgerSecp256k1(path) + if err != nil { + return nil, err + } + pub, err := priv.PubKey() + if err != nil { + return nil, err + } + return kb.writeLedgerKey(pub, path, name), nil +} + +// CreateOffline creates a new reference to an offline keypair +// It returns the created key info +func (kb dbKeybase) CreateOffline(name string, pub crypto.PubKey) (Info, error) { + return kb.writeOfflineKey(pub, name), nil +} + // Recover converts a seedphrase to a private key and persists it, // encrypted with the given passphrase. Functions like Create, but // seedphrase is input not output. @@ -63,22 +88,22 @@ func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { words := strings.Split(strings.TrimSpace(seedphrase), " ") secret, err := kb.codec.WordsToBytes(words) if err != nil { - return Info{}, err + return nil, err } // secret is comprised of the actual secret with the type // appended. // ie [secret] = [type] + [secret] typ, secret := secret[0], secret[1:] - algo := byteToCryptoAlgo(typ) + algo := byteToSignAlgo(typ) priv, err := generate(algo, secret) if err != nil { - return Info{}, err + return nil, err } // encrypt and persist key. - public := kb.writeKey(priv, name, passphrase) - return public, err + public := kb.writeLocalKey(priv, name, passphrase) + return public, nil } // List returns the keys from storage in alphabetical order. @@ -87,7 +112,6 @@ func (kb dbKeybase) List() ([]Info, error) { iter := kb.db.Iterator(nil, nil) defer iter.Close() for ; iter.Valid(); iter.Next() { - // key := iter.Key() info, err := readInfo(iter.Value()) if err != nil { return nil, err @@ -110,17 +134,46 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signat if err != nil { return } - if info.PrivKeyArmor == "" { - err = fmt.Errorf("private key not available") - return + var priv crypto.PrivKey + switch info.(type) { + case localInfo: + linfo := info.(localInfo) + if linfo.PrivKeyArmor == "" { + err = fmt.Errorf("private key not available") + return + } + priv, err = unarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase) + if err != nil { + return nil, nil, err + } + case ledgerInfo: + linfo := info.(ledgerInfo) + priv, err = crypto.NewPrivKeyLedgerSecp256k1(linfo.Path) + if err != nil { + return + } + case offlineInfo: + linfo := info.(offlineInfo) + fmt.Printf("Bytes to sign:\n%s", msg) + buf := bufio.NewReader(os.Stdin) + fmt.Printf("\nEnter Amino-encoded signature:\n") + // Will block until user inputs the signature + signed, err := buf.ReadString('\n') + if err != nil { + return nil, nil, err + } + cdc.MustUnmarshalBinary([]byte(signed), sig) + return sig, linfo.GetPubKey(), nil } - priv, err := unarmorDecryptPrivKey(info.PrivKeyArmor, passphrase) + sig, err = priv.Sign(msg) if err != nil { - return + return nil, nil, err } - sig = priv.Sign(msg) - pub = priv.PubKey() - return + pub, err = priv.PubKey() + if err != nil { + return nil, nil, err + } + return sig, pub, nil } func (kb dbKeybase) Export(name string) (armor string, err error) { @@ -143,7 +196,7 @@ func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) { if err != nil { return } - return armorPubKeyBytes(info.PubKey.Bytes()), nil + return armorPubKeyBytes(info.GetPubKey().Bytes()), nil } func (kb dbKeybase) Import(name string, armor string) (err error) { @@ -175,23 +228,37 @@ func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) { if err != nil { return } - kb.writePubKey(pubKey, name) + kb.writeOfflineKey(pubKey, name) return } // Delete removes key forever, but we must present the // proper passphrase before deleting it (for security). +// A passphrase of 'yes' is used to delete stored +// references to offline and Ledger / HW wallet keys func (kb dbKeybase) Delete(name, passphrase string) error { // verify we have the proper password before deleting info, err := kb.Get(name) if err != nil { return err } - _, err = unarmorDecryptPrivKey(info.PrivKeyArmor, passphrase) - if err != nil { - return err + switch info.(type) { + case localInfo: + linfo := info.(localInfo) + _, err = unarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase) + if err != nil { + return err + } + kb.db.DeleteSync(infoKey(name)) + return nil + case ledgerInfo: + case offlineInfo: + if passphrase != "yes" { + return fmt.Errorf("enter exactly 'yes' to delete the key") + } + kb.db.DeleteSync(infoKey(name)) + return nil } - kb.db.DeleteSync(infoKey(name)) return nil } @@ -205,36 +272,51 @@ func (kb dbKeybase) Update(name, oldpass, newpass string) error { if err != nil { return err } - key, err := unarmorDecryptPrivKey(info.PrivKeyArmor, oldpass) - if err != nil { - return err + switch info.(type) { + case localInfo: + linfo := info.(localInfo) + key, err := unarmorDecryptPrivKey(linfo.PrivKeyArmor, oldpass) + if err != nil { + return err + } + kb.writeLocalKey(key, name, newpass) + return nil + default: + return fmt.Errorf("Locally stored key required") } - - kb.writeKey(key, name, newpass) - return nil } -func (kb dbKeybase) writePubKey(pub crypto.PubKey, name string) Info { +func (kb dbKeybase) writeLocalKey(priv crypto.PrivKey, name, passphrase string) Info { + // encrypt private key using passphrase + privArmor := encryptArmorPrivKey(priv, passphrase) // make Info - info := newInfo(name, pub, "") - - // write them both - kb.db.SetSync(infoKey(name), info.bytes()) + pub, err := priv.PubKey() + if err != nil { + panic(err) + } + info := newLocalInfo(name, pub, privArmor) + kb.writeInfo(info, name) return info } -func (kb dbKeybase) writeKey(priv crypto.PrivKey, name, passphrase string) Info { - // generate the encrypted privkey - privArmor := encryptArmorPrivKey(priv, passphrase) - // make Info - info := newInfo(name, priv.PubKey(), privArmor) +func (kb dbKeybase) writeLedgerKey(pub crypto.PubKey, path crypto.DerivationPath, name string) Info { + info := newLedgerInfo(name, pub, path) + kb.writeInfo(info, name) + return info +} - // write them both - kb.db.SetSync(infoKey(name), info.bytes()) +func (kb dbKeybase) writeOfflineKey(pub crypto.PubKey, name string) Info { + info := newOfflineInfo(name, pub) + kb.writeInfo(info, name) return info } -func generate(algo CryptoAlgo, secret []byte) (crypto.PrivKey, error) { +func (kb dbKeybase) writeInfo(info Info, name string) { + // write the info by key + kb.db.SetSync(infoKey(name), writeInfo(info)) +} + +func generate(algo SignAlgo, secret []byte) (crypto.PrivKey, error) { switch algo { case AlgoEd25519: return crypto.GenPrivKeyEd25519FromSecret(secret), nil diff --git a/keys/keybase_test.go b/keys/keybase_test.go index aaf3b92fb..3627626cb 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -35,15 +35,15 @@ func TestKeyManagement(t *testing.T) { // create some keys _, err = cstore.Get(n1) assert.NotNil(t, err) - i, _, err := cstore.Create(n1, p1, algo) - require.Equal(t, n1, i.Name) + i, _, err := cstore.CreateMnemonic(n1, p1, algo) + require.Equal(t, n1, i.GetName()) require.Nil(t, err) - _, _, err = cstore.Create(n2, p2, algo) + _, _, err = cstore.CreateMnemonic(n2, p2, algo) require.Nil(t, err) // we can get these keys i2, err := cstore.Get(n2) - assert.Nil(t, err) + assert.NoError(t, err) _, err = cstore.Get(n3) assert.NotNil(t, err) @@ -52,9 +52,9 @@ func TestKeyManagement(t *testing.T) { require.Nil(t, err) require.Equal(t, 2, len(keyS)) // note these are in alphabetical order - assert.Equal(t, n2, keyS[0].Name) - assert.Equal(t, n1, keyS[1].Name) - assert.Equal(t, i2.PubKey, keyS[0].PubKey) + assert.Equal(t, n2, keyS[0].GetName()) + assert.Equal(t, n1, keyS[1].GetName()) + assert.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) // deleting a key removes it err = cstore.Delete("bad name", "foo") @@ -67,6 +67,26 @@ func TestKeyManagement(t *testing.T) { _, err = cstore.Get(n1) assert.NotNil(t, err) + // create an offline key + o1 := "offline" + priv1 := crypto.GenPrivKeyEd25519() + pub1, err := priv1.PubKey() + require.Nil(t, err) + i, err = cstore.CreateOffline(o1, pub1) + require.Nil(t, err) + require.Equal(t, pub1, i.GetPubKey()) + require.Equal(t, o1, i.GetName()) + keyS, err = cstore.List() + require.Equal(t, 2, len(keyS)) + + // delete the offline key + err = cstore.Delete(o1, "no") + require.NotNil(t, err) + err = cstore.Delete(o1, "yes") + require.Nil(t, err) + keyS, err = cstore.List() + require.Equal(t, 1, len(keyS)) + // make sure that it only signs with the right password // tx := mock.NewSig([]byte("mytransactiondata")) // err = cstore.Sign(n2, p1, tx) @@ -95,19 +115,18 @@ func TestSignVerify(t *testing.T) { p1, p2, p3 := "1234", "foobar", "foobar" // create two users and get their info - i1, _, err := cstore.Create(n1, p1, algo) + i1, _, err := cstore.CreateMnemonic(n1, p1, algo) require.Nil(t, err) - i2, _, err := cstore.Create(n2, p2, algo) + i2, _, err := cstore.CreateMnemonic(n2, p2, algo) require.Nil(t, err) // Import a public key armor, err := cstore.ExportPubKey(n2) require.Nil(t, err) cstore.ImportPubKey(n3, armor) - i3, err := cstore.Get(n3) + _, err = cstore.Get(n3) require.Nil(t, err) - require.Equal(t, i3.PrivKeyArmor, "") // let's try to sign some messages d1 := []byte("my first message") @@ -117,19 +136,19 @@ func TestSignVerify(t *testing.T) { // try signing both data with both keys... s11, pub1, err := cstore.Sign(n1, p1, d1) require.Nil(t, err) - require.Equal(t, i1.PubKey, pub1) + require.Equal(t, i1.GetPubKey(), pub1) s12, pub1, err := cstore.Sign(n1, p1, d2) require.Nil(t, err) - require.Equal(t, i1.PubKey, pub1) + require.Equal(t, i1.GetPubKey(), pub1) s21, pub2, err := cstore.Sign(n2, p2, d1) require.Nil(t, err) - require.Equal(t, i2.PubKey, pub2) + require.Equal(t, i2.GetPubKey(), pub2) s22, pub2, err := cstore.Sign(n2, p2, d2) require.Nil(t, err) - require.Equal(t, i2.PubKey, pub2) + require.Equal(t, i2.GetPubKey(), pub2) // let's try to validate and make sure it only works when everything is proper cases := []struct { @@ -139,15 +158,15 @@ func TestSignVerify(t *testing.T) { valid bool }{ // proper matches - {i1.PubKey, d1, s11, true}, + {i1.GetPubKey(), d1, s11, true}, // change data, pubkey, or signature leads to fail - {i1.PubKey, d2, s11, false}, - {i2.PubKey, d1, s11, false}, - {i1.PubKey, d1, s21, false}, + {i1.GetPubKey(), d2, s11, false}, + {i2.GetPubKey(), d1, s11, false}, + {i1.GetPubKey(), d1, s21, false}, // make sure other successes - {i1.PubKey, d2, s12, true}, - {i2.PubKey, d1, s21, true}, - {i2.PubKey, d2, s22, true}, + {i1.GetPubKey(), d2, s12, true}, + {i2.GetPubKey(), d1, s21, true}, + {i2.GetPubKey(), d2, s22, true}, } for i, tc := range cases { @@ -232,27 +251,27 @@ func TestExportImport(t *testing.T) { words.MustLoadCodec("english"), ) - info, _, err := cstore.Create("john", "passphrase", keys.AlgoEd25519) - assert.Nil(t, err) - assert.Equal(t, info.Name, "john") - addr := info.PubKey.Address() + info, _, err := cstore.CreateMnemonic("john", "passphrase", keys.AlgoEd25519) + assert.NoError(t, err) + assert.Equal(t, info.GetName(), "john") + addr := info.GetPubKey().Address() john, err := cstore.Get("john") - assert.Nil(t, err) - assert.Equal(t, john.Name, "john") - assert.Equal(t, john.PubKey.Address(), addr) + assert.NoError(t, err) + assert.Equal(t, john.GetName(), "john") + assert.Equal(t, john.GetPubKey().Address(), addr) armor, err := cstore.Export("john") - assert.Nil(t, err) + assert.NoError(t, err) err = cstore.Import("john2", armor) - assert.Nil(t, err) + assert.NoError(t, err) john2, err := cstore.Get("john2") - assert.Nil(t, err) + assert.NoError(t, err) - assert.Equal(t, john.PubKey.Address(), addr) - assert.Equal(t, john.Name, "john") + assert.Equal(t, john.GetPubKey().Address(), addr) + assert.Equal(t, john.GetName(), "john") assert.Equal(t, john, john2) } @@ -265,33 +284,31 @@ func TestExportImportPubKey(t *testing.T) { ) // Create a private-public key pair and ensure consistency - info, _, err := cstore.Create("john", "passphrase", keys.AlgoEd25519) - assert.Nil(t, err) - assert.NotEqual(t, info.PrivKeyArmor, "") - assert.Equal(t, info.Name, "john") - addr := info.PubKey.Address() + info, _, err := cstore.CreateMnemonic("john", "passphrase", keys.AlgoEd25519) + assert.NoError(t, err) + assert.Equal(t, info.GetName(), "john") + addr := info.GetPubKey().Address() john, err := cstore.Get("john") - assert.Nil(t, err) - assert.Equal(t, john.Name, "john") - assert.Equal(t, john.PubKey.Address(), addr) + assert.NoError(t, err) + assert.Equal(t, john.GetName(), "john") + assert.Equal(t, john.GetPubKey().Address(), addr) // Export the public key only armor, err := cstore.ExportPubKey("john") - assert.Nil(t, err) + assert.NoError(t, err) // Import it under a different name err = cstore.ImportPubKey("john-pubkey-only", armor) - assert.Nil(t, err) + assert.NoError(t, err) // Ensure consistency john2, err := cstore.Get("john-pubkey-only") - assert.Nil(t, err) - assert.Equal(t, john2.PrivKeyArmor, "") + assert.NoError(t, err) // Compare the public keys - assert.True(t, john.PubKey.Equals(john2.PubKey)) + assert.True(t, john.GetPubKey().Equals(john2.GetPubKey())) // Ensure the original key hasn't changed john, err = cstore.Get("john") - assert.Nil(t, err) - assert.Equal(t, john.PubKey.Address(), addr) - assert.Equal(t, john.Name, "john") + assert.NoError(t, err) + assert.Equal(t, john.GetPubKey().Address(), addr) + assert.Equal(t, john.GetName(), "john") // Ensure keys cannot be overwritten err = cstore.ImportPubKey("john-pubkey-only", armor) @@ -312,7 +329,7 @@ func TestAdvancedKeyManagement(t *testing.T) { p1, p2 := "1234", "foobar" // make sure key works with initial password - _, _, err := cstore.Create(n1, p1, algo) + _, _, err := cstore.CreateMnemonic(n1, p1, algo) require.Nil(t, err, "%+v", err) assertPassword(t, cstore, n1, p1, p2) @@ -323,7 +340,7 @@ func TestAdvancedKeyManagement(t *testing.T) { // then it changes the password when correct err = cstore.Update(n1, p1, p2) - assert.Nil(t, err) + assert.NoError(t, err) // p2 is now the proper one! assertPassword(t, cstore, n1, p2, p1) @@ -341,7 +358,7 @@ func TestAdvancedKeyManagement(t *testing.T) { // import succeeds err = cstore.Import(n2, exported) - assert.Nil(t, err) + assert.NoError(t, err) // second import fails err = cstore.Import(n2, exported) @@ -362,9 +379,9 @@ func TestSeedPhrase(t *testing.T) { p1, p2 := "1234", "foobar" // make sure key works with initial password - info, seed, err := cstore.Create(n1, p1, algo) + info, seed, err := cstore.CreateMnemonic(n1, p1, algo) require.Nil(t, err, "%+v", err) - assert.Equal(t, n1, info.Name) + assert.Equal(t, n1, info.GetName()) assert.NotEmpty(t, seed) // now, let us delete this key @@ -376,9 +393,9 @@ func TestSeedPhrase(t *testing.T) { // let us re-create it from the seed-phrase newInfo, err := cstore.Recover(n2, p2, seed) require.Nil(t, err, "%+v", err) - assert.Equal(t, n2, newInfo.Name) - assert.Equal(t, info.Address(), newInfo.Address()) - assert.Equal(t, info.PubKey, newInfo.PubKey) + assert.Equal(t, n2, newInfo.GetName()) + assert.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) + assert.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) } func ExampleNew() { @@ -391,19 +408,19 @@ func ExampleNew() { sec := keys.AlgoSecp256k1 // Add keys and see they return in alphabetical order - bob, _, err := cstore.Create("Bob", "friend", ed) + bob, _, err := cstore.CreateMnemonic("Bob", "friend", ed) if err != nil { // this should never happen fmt.Println(err) } else { // return info here just like in List - fmt.Println(bob.Name) + fmt.Println(bob.GetName()) } - cstore.Create("Alice", "secret", sec) - cstore.Create("Carl", "mitm", ed) + cstore.CreateMnemonic("Alice", "secret", sec) + cstore.CreateMnemonic("Carl", "mitm", ed) info, _ := cstore.List() for _, i := range info { - fmt.Println(i.Name) + fmt.Println(i.GetName()) } // We need to use passphrase to generate a signature @@ -415,11 +432,11 @@ func ExampleNew() { // and we can validate the signature with publically available info binfo, _ := cstore.Get("Bob") - if !binfo.PubKey.Equals(bob.PubKey) { + if !binfo.GetPubKey().Equals(bob.GetPubKey()) { fmt.Println("Get and Create return different keys") } - if pub.Equals(binfo.PubKey) { + if pub.Equals(binfo.GetPubKey()) { fmt.Println("signed by Bob") } if !pub.VerifyBytes(tx, sig) { diff --git a/keys/keys.go b/keys/keys.go index 0ed89b3fd..c8e25da3c 100644 --- a/keys/keys.go +++ b/keys/keys.go @@ -2,14 +2,14 @@ package keys import "fmt" -type CryptoAlgo string +type SignAlgo string const ( - AlgoEd25519 = CryptoAlgo("ed25519") - AlgoSecp256k1 = CryptoAlgo("secp256k1") + AlgoEd25519 = SignAlgo("ed25519") + AlgoSecp256k1 = SignAlgo("secp256k1") ) -func cryptoAlgoToByte(key CryptoAlgo) byte { +func cryptoAlgoToByte(key SignAlgo) byte { switch key { case AlgoEd25519: return 0x01 @@ -20,7 +20,7 @@ func cryptoAlgoToByte(key CryptoAlgo) byte { } } -func byteToCryptoAlgo(b byte) CryptoAlgo { +func byteToSignAlgo(b byte) SignAlgo { switch b { case 0x01: return AlgoEd25519 diff --git a/keys/types.go b/keys/types.go index e1df644ab..53821e8bf 100644 --- a/keys/types.go +++ b/keys/types.go @@ -4,54 +4,136 @@ import ( crypto "github.com/tendermint/go-crypto" ) -// Keybase allows simple CRUD on a keystore, as an aid to signing +// Keybase exposes operations on a generic keystore type Keybase interface { - // Sign some bytes - Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) - // Create a new keypair - Create(name, passphrase string, algo CryptoAlgo) (info Info, seed string, err error) - // Recover takes a seedphrase and loads in the key - Recover(name, passphrase, seedphrase string) (info Info, erro error) + + // CRUD on the keystore List() ([]Info, error) Get(name string) (Info, error) - Update(name, oldpass, newpass string) error Delete(name, passphrase string) error + // Sign some bytes, looking up the private key to use + Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) + + // Create a new locally-stored keypair, returning the mnemonic + CreateMnemonic(name, passphrase string, algo SignAlgo) (info Info, seed string, err error) + // Recover takes a seedphrase and loads in the key + Recover(name, passphrase, seedphrase string) (info Info, erro error) + + // Create, store, and return a new Ledger key reference + CreateLedger(name string, path crypto.DerivationPath, algo SignAlgo) (info Info, err error) + + // Create, store, and return a new offline key reference + CreateOffline(name string, pubkey crypto.PubKey) (info Info, err error) + + // The following operations will *only* work on locally-stored keys + Update(name, oldpass, newpass string) error Import(name string, armor string) (err error) ImportPubKey(name string, armor string) (err error) Export(name string) (armor string, err error) ExportPubKey(name string) (armor string, err error) } -// Info is the public information about a key -type Info struct { +// Publically exposed information about a keypair +type Info interface { + // Human-readable type for key listing + GetType() string + // Name of the key + GetName() string + // Public key + GetPubKey() crypto.PubKey +} + +var _ Info = &localInfo{} +var _ Info = &ledgerInfo{} +var _ Info = &offlineInfo{} + +// localInfo is the public information about a locally stored key +type localInfo struct { Name string `json:"name"` PubKey crypto.PubKey `json:"pubkey"` PrivKeyArmor string `json:"privkey.armor"` } -func newInfo(name string, pub crypto.PubKey, privArmor string) Info { - return Info{ +func newLocalInfo(name string, pub crypto.PubKey, privArmor string) Info { + return &localInfo{ Name: name, PubKey: pub, PrivKeyArmor: privArmor, } } -// Address is a helper function to calculate the address from the pubkey -func (i Info) Address() []byte { - return i.PubKey.Address() +func (i localInfo) GetType() string { + return "local" } -func (i Info) bytes() []byte { - bz, err := cdc.MarshalBinaryBare(i) - if err != nil { - panic(err) +func (i localInfo) GetName() string { + return i.Name +} + +func (i localInfo) GetPubKey() crypto.PubKey { + return i.PubKey +} + +// ledgerInfo is the public information about a Ledger key +type ledgerInfo struct { + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + Path crypto.DerivationPath `json:"path"` +} + +func newLedgerInfo(name string, pub crypto.PubKey, path crypto.DerivationPath) Info { + return &ledgerInfo{ + Name: name, + PubKey: pub, + Path: path, + } +} + +func (i ledgerInfo) GetType() string { + return "ledger" +} + +func (i ledgerInfo) GetName() string { + return i.Name +} + +func (i ledgerInfo) GetPubKey() crypto.PubKey { + return i.PubKey +} + +// offlineInfo is the public information about an offline key +type offlineInfo struct { + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` +} + +func newOfflineInfo(name string, pub crypto.PubKey) Info { + return &offlineInfo{ + Name: name, + PubKey: pub, } - return bz } +func (i offlineInfo) GetType() string { + return "offline" +} + +func (i offlineInfo) GetName() string { + return i.Name +} + +func (i offlineInfo) GetPubKey() crypto.PubKey { + return i.PubKey +} + +// encoding info +func writeInfo(i Info) []byte { + return cdc.MustMarshalBinary(i) +} + +// decoding info func readInfo(bz []byte) (info Info, err error) { - err = cdc.UnmarshalBinaryBare(bz, &info) + err = cdc.UnmarshalBinary(bz, &info) return } diff --git a/keys/wire.go b/keys/wire.go index 7deaad673..7cde0dd45 100644 --- a/keys/wire.go +++ b/keys/wire.go @@ -9,4 +9,8 @@ var cdc = amino.NewCodec() func init() { crypto.RegisterAmino(cdc) + cdc.RegisterInterface((*Info)(nil), nil) + cdc.RegisterConcrete(localInfo{}, "crypto/keys/localInfo", nil) + cdc.RegisterConcrete(ledgerInfo{}, "crypto/keys/ledgerInfo", nil) + cdc.RegisterConcrete(offlineInfo{}, "crypto/keys/offlineInfo", nil) } diff --git a/ledger_secp256k1.go b/ledger_secp256k1.go index f485bb415..1a7887ad3 100644 --- a/ledger_secp256k1.go +++ b/ledger_secp256k1.go @@ -73,11 +73,7 @@ func (pk *PrivKeyLedgerSecp256k1) AssertIsPrivKeyInner() {} // Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify // the same key when we reconnect to a ledger func (pk PrivKeyLedgerSecp256k1) Bytes() []byte { - bin, err := cdc.MarshalBinaryBare(pk) - if err != nil { - panic(err) - } - return bin + return cdc.MustMarshalBinaryBare(pk) } // Sign calls the ledger and stores the PubKey for future use @@ -85,39 +81,34 @@ func (pk PrivKeyLedgerSecp256k1) Bytes() []byte { // Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, // returning an error, so this should only trigger if the privkey is held // in memory for a while before use. -func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) Signature { - // oh, I wish there was better error handling +func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) (Signature, error) { dev, err := getLedger() if err != nil { - panic(err) + return nil, err } sig, err := signLedgerSecp256k1(dev, pk.Path, msg) if err != nil { - panic(err) + return nil, err } pub, err := pubkeyLedgerSecp256k1(dev, pk.Path) if err != nil { - panic(err) + return nil, err } // if we have no pubkey yet, store it for future queries if pk.CachedPubKey == nil { pk.CachedPubKey = pub } else if !pk.CachedPubKey.Equals(pub) { - panic("stored key does not match signing key") + return nil, fmt.Errorf("stored key does not match signing key") } - return sig + return sig, nil } // PubKey returns the stored PubKey -func (pk PrivKeyLedgerSecp256k1) PubKey() PubKey { - key, err := pk.getPubKey() - if err != nil { - panic(err) - } - return key +func (pk PrivKeyLedgerSecp256k1) PubKey() (PubKey, error) { + return pk.getPubKey() } // getPubKey reads the pubkey from cache or from the ledger itself diff --git a/ledger_test.go b/ledger_test.go index dda3d3d3d..4a7ae46e4 100644 --- a/ledger_test.go +++ b/ledger_test.go @@ -19,8 +19,10 @@ func TestRealLedgerSecp256k1(t *testing.T) { priv, err := NewPrivKeyLedgerSecp256k1(path) require.Nil(t, err, "%+v", err) - pub := priv.PubKey() - sig := priv.Sign(msg) + pub, err := priv.PubKey() + require.Nil(t, err) + sig, err := priv.Sign(msg) + require.Nil(t, err) valid := pub.VerifyBytes(msg, sig) assert.True(t, valid) @@ -31,11 +33,13 @@ func TestRealLedgerSecp256k1(t *testing.T) { require.Nil(t, err, "%+v", err) // make sure we get the same pubkey when we load from disk - pub2 := priv2.PubKey() + pub2, err := priv2.PubKey() + require.Nil(t, err) require.Equal(t, pub, pub2) // signing with the loaded key should match the original pubkey - sig = priv2.Sign(msg) + sig, err = priv2.Sign(msg) + require.Nil(t, err) valid = pub.VerifyBytes(msg, sig) assert.True(t, valid) diff --git a/priv_key.go b/priv_key.go index 82e1cfced..2c06f3452 100644 --- a/priv_key.go +++ b/priv_key.go @@ -6,7 +6,6 @@ import ( secp256k1 "github.com/btcsuite/btcd/btcec" "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" - . "github.com/tendermint/tmlibs/common" ) func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { @@ -18,8 +17,8 @@ func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { type PrivKey interface { Bytes() []byte - Sign(msg []byte) Signature - PubKey() PubKey + Sign(msg []byte) (Signature, error) + PubKey() (PubKey, error) Equals(PrivKey) bool } @@ -31,23 +30,19 @@ var _ PrivKey = PrivKeyEd25519{} type PrivKeyEd25519 [64]byte func (privKey PrivKeyEd25519) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(privKey) - if err != nil { - panic(err) - } - return bz + return cdc.MustMarshalBinaryBare(privKey) } -func (privKey PrivKeyEd25519) Sign(msg []byte) Signature { +func (privKey PrivKeyEd25519) Sign(msg []byte) (Signature, error) { privKeyBytes := [64]byte(privKey) signatureBytes := ed25519.Sign(&privKeyBytes, msg) - return SignatureEd25519(*signatureBytes) + return SignatureEd25519(*signatureBytes), nil } -func (privKey PrivKeyEd25519) PubKey() PubKey { +func (privKey PrivKeyEd25519) PubKey() (PubKey, error) { privKeyBytes := [64]byte(privKey) pubBytes := *ed25519.MakePublicKey(&privKeyBytes) - return PubKeyEd25519(pubBytes) + return PubKeyEd25519(pubBytes), nil } // Equals - you probably don't need to use this. @@ -67,12 +62,6 @@ func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { return keyCurve25519 } -/* -func (privKey PrivKeyEd25519) String() string { - return Fmt("PrivKeyEd25519{*****}") -} -*/ - // Deterministically generates new priv-key bytes from key. func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { bz, err := cdc.MarshalBinaryBare(struct { @@ -114,27 +103,23 @@ var _ PrivKey = PrivKeySecp256k1{} type PrivKeySecp256k1 [32]byte func (privKey PrivKeySecp256k1) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(privKey) - if err != nil { - panic(err) - } - return bz + return cdc.MustMarshalBinaryBare(privKey) } -func (privKey PrivKeySecp256k1) Sign(msg []byte) Signature { +func (privKey PrivKeySecp256k1) Sign(msg []byte) (Signature, error) { priv__, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) sig__, err := priv__.Sign(Sha256(msg)) if err != nil { - PanicSanity(err) + return nil, err } - return SignatureSecp256k1(sig__.Serialize()) + return SignatureSecp256k1(sig__.Serialize()), nil } -func (privKey PrivKeySecp256k1) PubKey() PubKey { +func (privKey PrivKeySecp256k1) PubKey() (PubKey, error) { _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) var pub PubKeySecp256k1 copy(pub[:], pub__.SerializeCompressed()) - return pub + return pub, nil } // Equals - you probably don't need to use this. @@ -147,12 +132,6 @@ func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { } } -/* -func (privKey PrivKeySecp256k1) String() string { - return Fmt("PrivKeySecp256k1{*****}") -} -*/ - /* // Deterministically generates new priv-key bytes from key. func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 { diff --git a/priv_key_test.go b/priv_key_test.go index 6abe36ac5..33f3eb7ee 100644 --- a/priv_key_test.go +++ b/priv_key_test.go @@ -11,7 +11,11 @@ func TestGeneratePrivKey(t *testing.T) { testPriv := crypto.GenPrivKeyEd25519() testGenerate := testPriv.Generate(1) signBytes := []byte("something to sign") - assert.True(t, testGenerate.PubKey().VerifyBytes(signBytes, testGenerate.Sign(signBytes))) + pub, err := testGenerate.PubKey() + assert.NoError(t, err) + sig, err := testGenerate.Sign(signBytes) + assert.NoError(t, err) + assert.True(t, pub.VerifyBytes(signBytes, sig)) } /* diff --git a/pub_key_test.go b/pub_key_test.go index 29672390b..35c78a46a 100644 --- a/pub_key_test.go +++ b/pub_key_test.go @@ -33,9 +33,11 @@ func TestPubKeySecp256k1Address(t *testing.T) { var priv PrivKeySecp256k1 copy(priv[:], privB) - pubT := priv.PubKey().(PubKeySecp256k1) + pubKey, err := priv.PubKey() + assert.NoError(t, err) + pubT, _ := pubKey.(PubKeySecp256k1) pub := pubT[:] - addr := priv.PubKey().Address() + addr := pubKey.Address() assert.Equal(t, pub, pubB, "Expected pub keys to match") assert.Equal(t, addr, addrB, "Expected addresses to match") diff --git a/signature_test.go b/signature_test.go index 0ba44ded5..52da65572 100644 --- a/signature_test.go +++ b/signature_test.go @@ -12,10 +12,12 @@ import ( func TestSignAndValidateEd25519(t *testing.T) { privKey := GenPrivKeyEd25519() - pubKey := privKey.PubKey() + pubKey, err := privKey.PubKey() + require.Nil(t, err) msg := CRandBytes(128) - sig := privKey.Sign(msg) + sig, err := privKey.Sign(msg) + require.Nil(t, err) // Test the signature assert.True(t, pubKey.VerifyBytes(msg, sig)) @@ -30,10 +32,12 @@ func TestSignAndValidateEd25519(t *testing.T) { func TestSignAndValidateSecp256k1(t *testing.T) { privKey := GenPrivKeySecp256k1() - pubKey := privKey.PubKey() + pubKey, err := privKey.PubKey() + require.Nil(t, err) msg := CRandBytes(128) - sig := privKey.Sign(msg) + sig, err := privKey.Sign(msg) + require.Nil(t, err) assert.True(t, pubKey.VerifyBytes(msg, sig)) @@ -65,10 +69,12 @@ func TestSignatureEncodings(t *testing.T) { for _, tc := range cases { // note we embed them from the beginning.... - pubKey := tc.privKey.PubKey() + pubKey, err := tc.privKey.PubKey() + require.Nil(t, err) msg := CRandBytes(128) - sig := tc.privKey.Sign(msg) + sig, err := tc.privKey.Sign(msg) + require.Nil(t, err) // store as amino bin, err := cdc.MarshalBinaryBare(sig) From 66794a174ac0f0a03235ba1348321e247f391822 Mon Sep 17 00:00:00 2001 From: Joon Date: Sun, 10 Jun 2018 20:43:40 -0700 Subject: [PATCH 260/273] Move from tmlibs #213 (#115) * move from tmlibs 213 * expose KVPair, simpleproofsfrommap returns keys --- merkle/simple_map.go | 13 +++++-------- merkle/simple_map_test.go | 12 ++++++------ merkle/simple_proof.go | 14 +++++++++++--- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/merkle/simple_map.go b/merkle/simple_map.go index cde5924f4..24863267b 100644 --- a/merkle/simple_map.go +++ b/merkle/simple_map.go @@ -24,16 +24,13 @@ func newSimpleMap() *simpleMap { func (sm *simpleMap) Set(key string, value Hasher) { sm.sorted = false - // Hash the key to blind it... why not? - khash := tmhash.Sum([]byte(key)) - - // And the value is hashed too, so you can + // The value is hashed, so you can // check for equality with a cached value (say) // and make a determination to fetch or not. vhash := value.Hash() sm.kvs = append(sm.kvs, cmn.KVPair{ - Key: khash, + Key: []byte(key), Value: vhash, }) } @@ -67,9 +64,9 @@ func (sm *simpleMap) KVPairs() cmn.KVPairs { // A local extension to KVPair that can be hashed. // Key and value are length prefixed and concatenated, // then hashed. -type kvPair cmn.KVPair +type KVPair cmn.KVPair -func (kv kvPair) Hash() []byte { +func (kv KVPair) Hash() []byte { hasher := tmhash.New() err := encodeByteSlice(hasher, kv.Key) if err != nil { @@ -85,7 +82,7 @@ func (kv kvPair) Hash() []byte { func hashKVPairs(kvs cmn.KVPairs) []byte { kvsH := make([]Hasher, len(kvs)) for i, kvp := range kvs { - kvsH[i] = kvPair(kvp) + kvsH[i] = KVPair(kvp) } return SimpleHashFromHashers(kvsH) } diff --git a/merkle/simple_map_test.go b/merkle/simple_map_test.go index a89289a8f..d9d635115 100644 --- a/merkle/simple_map_test.go +++ b/merkle/simple_map_test.go @@ -18,37 +18,37 @@ func TestSimpleMap(t *testing.T) { { db := newSimpleMap() db.Set("key1", strHasher("value1")) - assert.Equal(t, "3dafc06a52039d029be57c75c9d16356a4256ef4", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "fa9bc106ffd932d919bee935ceb6cf2b3dd72d8f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := newSimpleMap() db.Set("key1", strHasher("value2")) - assert.Equal(t, "03eb5cfdff646bc4e80fec844e72fd248a1c6b2c", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "e00e7dcfe54e9fafef5111e813a587f01ba9c3e8", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := newSimpleMap() db.Set("key1", strHasher("value1")) db.Set("key2", strHasher("value2")) - assert.Equal(t, "acc3971eab8513171cc90ce8b74f368c38f9657d", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "eff12d1c703a1022ab509287c0f196130123d786", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := newSimpleMap() db.Set("key2", strHasher("value2")) // NOTE: out of order db.Set("key1", strHasher("value1")) - assert.Equal(t, "acc3971eab8513171cc90ce8b74f368c38f9657d", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "eff12d1c703a1022ab509287c0f196130123d786", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := newSimpleMap() db.Set("key1", strHasher("value1")) db.Set("key2", strHasher("value2")) db.Set("key3", strHasher("value3")) - assert.Equal(t, "0cd117ad14e6cd22edcd9aa0d84d7063b54b862f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "b2c62a277c08dbd2ad73ca53cd1d6bfdf5830d26", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := newSimpleMap() db.Set("key2", strHasher("value2")) // NOTE: out of order db.Set("key1", strHasher("value1")) db.Set("key3", strHasher("value3")) - assert.Equal(t, "0cd117ad14e6cd22edcd9aa0d84d7063b54b862f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + assert.Equal(t, "b2c62a277c08dbd2ad73ca53cd1d6bfdf5830d26", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } } diff --git a/merkle/simple_proof.go b/merkle/simple_proof.go index f52d1ad9f..2541b6d38 100644 --- a/merkle/simple_proof.go +++ b/merkle/simple_proof.go @@ -27,7 +27,7 @@ func SimpleProofsFromHashers(items []Hasher) (rootHash []byte, proofs []*SimpleP // SimpleProofsFromMap generates proofs from a map. The keys/values of the map will be used as the keys/values // in the underlying key-value pairs. // The keys are sorted before the proofs are computed. -func SimpleProofsFromMap(m map[string]Hasher) (rootHash []byte, proofs []*SimpleProof) { +func SimpleProofsFromMap(m map[string]Hasher) (rootHash []byte, proofs map[string]*SimpleProof, keys []string) { sm := newSimpleMap() for k, v := range m { sm.Set(k, v) @@ -36,9 +36,17 @@ func SimpleProofsFromMap(m map[string]Hasher) (rootHash []byte, proofs []*Simple kvs := sm.kvs kvsH := make([]Hasher, 0, len(kvs)) for _, kvp := range kvs { - kvsH = append(kvsH, kvPair(kvp)) + kvsH = append(kvsH, KVPair(kvp)) } - return SimpleProofsFromHashers(kvsH) + + rootHash, proofList := SimpleProofsFromHashers(kvsH) + proofs = make(map[string]*SimpleProof) + keys = make([]string, len(proofList)) + for i, kvp := range kvs { + proofs[string(kvp.Key)] = proofList[i] + keys[i] = string(kvp.Key) + } + return } // Verify that leafHash is a leaf hash of the simple-merkle-tree From e694c309ba2ad13dfac65c3f0fdd1efb535b27c5 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 11 Jun 2018 15:43:32 -0700 Subject: [PATCH 261/273] update ed25519 address scheme (#112) make PubKeyEd25519.Address() returns the first 20 bytes of the hash of the raw 32-byte pubkey, no amino required --- pub_key.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pub_key.go b/pub_key.go index 9be64acdf..c509ff8de 100644 --- a/pub_key.go +++ b/pub_key.go @@ -5,11 +5,16 @@ import ( "crypto/sha256" "fmt" + "golang.org/x/crypto/ripemd160" + secp256k1 "github.com/btcsuite/btcd/btcec" + "github.com/tendermint/ed25519" "github.com/tendermint/ed25519/extra25519" + cmn "github.com/tendermint/tmlibs/common" - "golang.org/x/crypto/ripemd160" + + "github.com/tendermint/go-crypto/tmhash" ) // An address is a []byte, but hex-encoded even in JSON. @@ -38,11 +43,9 @@ var _ PubKey = PubKeyEd25519{} // Implements PubKeyInner type PubKeyEd25519 [32]byte +// Address is the SHA256-20 of the raw pubkey bytes. func (pubKey PubKeyEd25519) Address() Address { - // append type byte - hasher := ripemd160.New() - hasher.Write(pubKey.Bytes()) // does not error - return Address(hasher.Sum(nil)) + return Address(tmhash.Sum(pubKey[:])) } func (pubKey PubKeyEd25519) Bytes() []byte { From 45a1c8aef36641b5020098dac004675a1c8fbfd4 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 11 Jun 2018 16:23:34 -0700 Subject: [PATCH 262/273] fix tests, move encoding to encode_test.go, include an example --- Gopkg.lock | 11 +++++--- Gopkg.toml | 2 +- encode_test.go | 13 ++++++++++ signature_test.go | 65 ----------------------------------------------- 4 files changed, 21 insertions(+), 70 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index f52af5591..2bcf5cdd5 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -128,15 +128,16 @@ [[projects]] name = "github.com/tendermint/go-amino" packages = ["."] - revision = "42246108ff925a457fb709475070a03dfd3e2b5c" - version = "0.9.6" + revision = "1715b7b78c65d6adcc5937315be4710234cefe09" + version = "0.10.0-rc2" [[projects]] name = "github.com/tendermint/tmlibs" packages = [ "common", "db", - "log" + "log", + "test" ] revision = "2e24b64fc121dcdf1cabceab8dc2f7257675483c" version = "v0.8.1" @@ -153,6 +154,8 @@ packages = [ "bcrypt", "blowfish", + "chacha20poly1305", + "internal/chacha20", "nacl/secretbox", "openpgp/armor", "openpgp/errors", @@ -166,6 +169,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "f9ccfa2cadfcbfb43bf729b871a0ad2f8d4f4acb118cd859e6faf9b24842b840" + inputs-digest = "b34cf043cab77178eebff1b7cfce8b31b6c2b6b3318c6d01add271b68f550345" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 4ccb8c07d..5761cf69f 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -47,7 +47,7 @@ [[constraint]] name = "github.com/tendermint/go-amino" - version = "0.9.6" + version = "0.10.0-rc2" [[constraint]] name = "github.com/tendermint/tmlibs" diff --git a/encode_test.go b/encode_test.go index 0bd450829..99ff17d43 100644 --- a/encode_test.go +++ b/encode_test.go @@ -1,6 +1,7 @@ package crypto import ( + "os" "testing" "github.com/stretchr/testify/assert" @@ -41,6 +42,18 @@ func checkAminoJSON(t *testing.T, src interface{}, dst interface{}, isNil bool) require.Nil(t, err, "%+v", err) } +func ExamplePrintRegisteredTypes() { + cdc.PrintTypes(os.Stdout) + // Output: | Type | Name | Prefix | Length | Notes | + //| ---- | ---- | ------ | ----- | ------ | + //| PubKeyEd25519 | tendermint/PubKeyEd25519 | 0x1624DE64 | 0x20 | | + //| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | | + //| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | | + //| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | | + //| SignatureEd25519 | tendermint/SignatureEd25519 | 0x2031EA53 | 0x40 | | + //| SignatureSecp256k1 | tendermint/SignatureSecp256k1 | 0x7FC4A495 | variable | | +} + func TestKeyEncodings(t *testing.T) { cases := []struct { privKey PrivKey diff --git a/signature_test.go b/signature_test.go index 0ba44ded5..3b1d74ad3 100644 --- a/signature_test.go +++ b/signature_test.go @@ -4,9 +4,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/tendermint/ed25519" - amino "github.com/tendermint/go-amino" ) func TestSignAndValidateEd25519(t *testing.T) { @@ -44,65 +41,3 @@ func TestSignAndValidateSecp256k1(t *testing.T) { assert.False(t, pubKey.VerifyBytes(msg, sig)) } - -func TestSignatureEncodings(t *testing.T) { - cases := []struct { - privKey PrivKey - sigSize int - sigPrefix amino.PrefixBytes - }{ - { - privKey: GenPrivKeyEd25519(), - sigSize: ed25519.SignatureSize, - sigPrefix: [4]byte{0x3d, 0xa1, 0xdb, 0x2a}, - }, - { - privKey: GenPrivKeySecp256k1(), - sigSize: 0, // unknown - sigPrefix: [4]byte{0x16, 0xe1, 0xfe, 0xea}, - }, - } - - for _, tc := range cases { - // note we embed them from the beginning.... - pubKey := tc.privKey.PubKey() - - msg := CRandBytes(128) - sig := tc.privKey.Sign(msg) - - // store as amino - bin, err := cdc.MarshalBinaryBare(sig) - require.Nil(t, err, "%+v", err) - if tc.sigSize != 0 { - // Q: where is 1 byte coming from? - assert.Equal(t, tc.sigSize+amino.PrefixBytesLen+1, len(bin)) - } - assert.Equal(t, tc.sigPrefix[:], bin[0:amino.PrefixBytesLen]) - - // and back - sig2 := Signature(nil) - err = cdc.UnmarshalBinaryBare(bin, &sig2) - require.Nil(t, err, "%+v", err) - assert.EqualValues(t, sig, sig2) - assert.True(t, pubKey.VerifyBytes(msg, sig2)) - - /* - // store as json - js, err := data.ToJSON(sig) - require.Nil(t, err, "%+v", err) - assert.True(t, strings.Contains(string(js), tc.sigName)) - - // and back - sig3 := Signature{} - err = data.FromJSON(js, &sig3) - require.Nil(t, err, "%+v", err) - assert.EqualValues(t, sig, sig3) - assert.True(t, pubKey.VerifyBytes(msg, sig3)) - - // and make sure we can textify it - text, err := data.ToText(sig) - require.Nil(t, err, "%+v", err) - assert.True(t, strings.HasPrefix(text, tc.sigName)) - */ - } -} From f4663e5bb790065f4b730d873fb02fef5fed2ca1 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 11 Jun 2018 16:37:14 -0700 Subject: [PATCH 263/273] fix tests, bump amino version, move encoding to encode_test.go, include an example, do not err check on info ... bur for empty info instead --- keys/keybase_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/keys/keybase_test.go b/keys/keybase_test.go index aaf3b92fb..820add7b9 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -33,9 +33,9 @@ func TestKeyManagement(t *testing.T) { assert.Empty(t, l) // create some keys - _, err = cstore.Get(n1) - assert.NotNil(t, err) - i, _, err := cstore.Create(n1, p1, algo) + i, err := cstore.Get(n1) + assert.Equal(t, i, keys.Info{}) + i, _, err = cstore.Create(n1, p1, algo) require.Equal(t, n1, i.Name) require.Nil(t, err) _, _, err = cstore.Create(n2, p2, algo) @@ -44,8 +44,8 @@ func TestKeyManagement(t *testing.T) { // we can get these keys i2, err := cstore.Get(n2) assert.Nil(t, err) - _, err = cstore.Get(n3) - assert.NotNil(t, err) + i, err = cstore.Get(n3) + assert.Equal(t, i, keys.Info{}) // list shows them in order keyS, err := cstore.List() @@ -64,8 +64,8 @@ func TestKeyManagement(t *testing.T) { keyS, err = cstore.List() require.Nil(t, err) assert.Equal(t, 1, len(keyS)) - _, err = cstore.Get(n1) - assert.NotNil(t, err) + i, err = cstore.Get(n1) + assert.Equal(t, i, keys.Info{}) // make sure that it only signs with the right password // tx := mock.NewSig([]byte("mytransactiondata")) @@ -370,8 +370,8 @@ func TestSeedPhrase(t *testing.T) { // now, let us delete this key err = cstore.Delete(n1, p1) require.Nil(t, err, "%+v", err) - _, err = cstore.Get(n1) - require.NotNil(t, err) + i, err := cstore.Get(n1) + require.Equal(t, i, keys.Info{}, "expected empty info") // let us re-create it from the seed-phrase newInfo, err := cstore.Recover(n2, p2, seed) From e552d344e3551b7382f42c216118c6c302a31dd8 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 11 Jun 2018 16:51:38 -0700 Subject: [PATCH 264/273] forgot PrivKeyLedgerSecp256k1 --- encode_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/encode_test.go b/encode_test.go index fa9465ddd..ed5395db8 100644 --- a/encode_test.go +++ b/encode_test.go @@ -50,6 +50,7 @@ func ExamplePrintRegisteredTypes() { //| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | | //| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | | //| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | | + //| PrivKeyLedgerSecp256k1 | tendermint/PrivKeyLedgerSecp256k1 | 0x10CAB393 | variable | | //| SignatureEd25519 | tendermint/SignatureEd25519 | 0x2031EA53 | 0x40 | | //| SignatureSecp256k1 | tendermint/SignatureSecp256k1 | 0x7FC4A495 | variable | | } From 42c6a64e0421c149de4733a14884c0ca4be7d6d5 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Mon, 11 Jun 2018 17:27:32 -0700 Subject: [PATCH 265/273] version bump (#128) version bump --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 57806e26c..77c0bed8a 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package crypto -const Version = "0.8.0-dev" +const Version = "0.9.0-dev" From 8e273220a35e200caa63ad6d1fbe5a91a49b45e2 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 12 Jun 2018 22:35:22 +0200 Subject: [PATCH 266/273] Remove error from priv.PubKey() (#131) * Remove error from priv.PubKey() * Update changelog --- CHANGELOG.md | 6 ++++++ Gopkg.lock | 8 ++++---- encode_test.go | 3 +-- keys/keybase.go | 15 +++------------ keys/keybase_test.go | 3 +-- ledger_secp256k1.go | 42 ++++++++++-------------------------------- ledger_test.go | 6 ++---- priv_key.go | 10 +++++----- priv_key_test.go | 3 +-- pub_key_test.go | 3 +-- signature_test.go | 8 +++----- 11 files changed, 37 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c31551b5..dd7c1039f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.9.0 + +BREAKING CHANGES + +- `priv.PubKey()` no longer returns an error. Any applicable errors (such as when fetching the public key from a hardware wallet) should be checked and returned when constructing the private key. + ## 0.8.0 **TBD** diff --git a/Gopkg.lock b/Gopkg.lock index a475c6656..fbfd54dcf 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -99,8 +99,8 @@ "assert", "require" ] - revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" - version = "v1.2.1" + revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" + version = "v1.2.2" [[projects]] branch = "master" @@ -181,11 +181,11 @@ branch = "master" name = "golang.org/x/sys" packages = ["cpu"] - revision = "9527bec2660bd847c050fda93a0f0c6dee0800bb" + revision = "a9e25c09b96b8870693763211309e213c6ef299d" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "f20e34cd998442d4ffe2f9aa45ab87a55ba6e4cd19f29009adaadac3b5dccf26" + inputs-digest = "1731880d432026bbd22865582cf7c7dd6d5c65618149de586e30ce156d338c01" solver-name = "gps-cdcl" solver-version = 1 diff --git a/encode_test.go b/encode_test.go index ed5395db8..025b09c80 100644 --- a/encode_test.go +++ b/encode_test.go @@ -91,8 +91,7 @@ func TestKeyEncodings(t *testing.T) { assert.EqualValues(t, sig1, sig3) // Check (de/en)codings of PubKeys. - pubKey, err := tc.privKey.PubKey() - assert.NoError(t, err) + pubKey := tc.privKey.PubKey() var pub2, pub3 PubKey checkAminoBinary(t, pubKey, &pub2, tc.pubSize) assert.EqualValues(t, pubKey, pub2) diff --git a/keys/keybase.go b/keys/keybase.go index 39a3de59e..79e6f15fa 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -68,10 +68,7 @@ func (kb dbKeybase) CreateLedger(name string, path crypto.DerivationPath, algo S if err != nil { return nil, err } - pub, err := priv.PubKey() - if err != nil { - return nil, err - } + pub := priv.PubKey() return kb.writeLedgerKey(pub, path, name), nil } @@ -169,10 +166,7 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signat if err != nil { return nil, nil, err } - pub, err = priv.PubKey() - if err != nil { - return nil, nil, err - } + pub = priv.PubKey() return sig, pub, nil } @@ -290,10 +284,7 @@ func (kb dbKeybase) writeLocalKey(priv crypto.PrivKey, name, passphrase string) // encrypt private key using passphrase privArmor := encryptArmorPrivKey(priv, passphrase) // make Info - pub, err := priv.PubKey() - if err != nil { - panic(err) - } + pub := priv.PubKey() info := newLocalInfo(name, pub, privArmor) kb.writeInfo(info, name) return info diff --git a/keys/keybase_test.go b/keys/keybase_test.go index 3627626cb..5caf82af8 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -70,8 +70,7 @@ func TestKeyManagement(t *testing.T) { // create an offline key o1 := "offline" priv1 := crypto.GenPrivKeyEd25519() - pub1, err := priv1.PubKey() - require.Nil(t, err) + pub1 := priv1.PubKey() i, err = cstore.CreateOffline(o1, pub1) require.Nil(t, err) require.Equal(t, pub1, i.GetPubKey()) diff --git a/ledger_secp256k1.go b/ledger_secp256k1.go index 1a7887ad3..21dfbb8b5 100644 --- a/ledger_secp256k1.go +++ b/ledger_secp256k1.go @@ -44,10 +44,12 @@ type PrivKeyLedgerSecp256k1 struct { func NewPrivKeyLedgerSecp256k1(path DerivationPath) (PrivKey, error) { var pk PrivKeyLedgerSecp256k1 pk.Path = path - // getPubKey will cache the pubkey for later use, - // this allows us to return an error early if the ledger - // is not plugged in - _, err := pk.getPubKey() + // cache the pubkey for later use + pubKey, err := pk.getPubKey() + if err != nil { + return nil, err + } + pk.CachedPubKey = pubKey return &pk, err } @@ -55,8 +57,7 @@ func NewPrivKeyLedgerSecp256k1(path DerivationPath) (PrivKey, error) { // after loading it from disk func (pk PrivKeyLedgerSecp256k1) ValidateKey() error { // getPubKey will return an error if the ledger is not - // properly set up... - pub, err := pk.forceGetPubKey() + pub, err := pk.getPubKey() if err != nil { return err } @@ -86,45 +87,22 @@ func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) (Signature, error) { if err != nil { return nil, err } - sig, err := signLedgerSecp256k1(dev, pk.Path, msg) if err != nil { return nil, err } - - pub, err := pubkeyLedgerSecp256k1(dev, pk.Path) - if err != nil { - return nil, err - } - - // if we have no pubkey yet, store it for future queries - if pk.CachedPubKey == nil { - pk.CachedPubKey = pub - } else if !pk.CachedPubKey.Equals(pub) { - return nil, fmt.Errorf("stored key does not match signing key") - } return sig, nil } // PubKey returns the stored PubKey -func (pk PrivKeyLedgerSecp256k1) PubKey() (PubKey, error) { - return pk.getPubKey() +func (pk PrivKeyLedgerSecp256k1) PubKey() PubKey { + return pk.CachedPubKey } -// getPubKey reads the pubkey from cache or from the ledger itself +// getPubKey reads the pubkey the ledger itself // since this involves IO, it may return an error, which is not exposed // in the PubKey interface, so this function allows better error handling func (pk PrivKeyLedgerSecp256k1) getPubKey() (key PubKey, err error) { - // if we have no pubkey, set it - if pk.CachedPubKey == nil { - pk.CachedPubKey, err = pk.forceGetPubKey() - } - return pk.CachedPubKey, err -} - -// forceGetPubKey is like getPubKey but ignores any cached key -// and ensures we get it from the ledger itself. -func (pk PrivKeyLedgerSecp256k1) forceGetPubKey() (key PubKey, err error) { dev, err := getLedger() if err != nil { return key, fmt.Errorf("cannot connect to Ledger device - error: %v", err) diff --git a/ledger_test.go b/ledger_test.go index 4a7ae46e4..83390cc36 100644 --- a/ledger_test.go +++ b/ledger_test.go @@ -19,8 +19,7 @@ func TestRealLedgerSecp256k1(t *testing.T) { priv, err := NewPrivKeyLedgerSecp256k1(path) require.Nil(t, err, "%+v", err) - pub, err := priv.PubKey() - require.Nil(t, err) + pub := priv.PubKey() sig, err := priv.Sign(msg) require.Nil(t, err) @@ -33,8 +32,7 @@ func TestRealLedgerSecp256k1(t *testing.T) { require.Nil(t, err, "%+v", err) // make sure we get the same pubkey when we load from disk - pub2, err := priv2.PubKey() - require.Nil(t, err) + pub2 := priv2.PubKey() require.Equal(t, pub, pub2) // signing with the loaded key should match the original pubkey diff --git a/priv_key.go b/priv_key.go index 2c06f3452..dbfe64c33 100644 --- a/priv_key.go +++ b/priv_key.go @@ -18,7 +18,7 @@ func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { type PrivKey interface { Bytes() []byte Sign(msg []byte) (Signature, error) - PubKey() (PubKey, error) + PubKey() PubKey Equals(PrivKey) bool } @@ -39,10 +39,10 @@ func (privKey PrivKeyEd25519) Sign(msg []byte) (Signature, error) { return SignatureEd25519(*signatureBytes), nil } -func (privKey PrivKeyEd25519) PubKey() (PubKey, error) { +func (privKey PrivKeyEd25519) PubKey() PubKey { privKeyBytes := [64]byte(privKey) pubBytes := *ed25519.MakePublicKey(&privKeyBytes) - return PubKeyEd25519(pubBytes), nil + return PubKeyEd25519(pubBytes) } // Equals - you probably don't need to use this. @@ -115,11 +115,11 @@ func (privKey PrivKeySecp256k1) Sign(msg []byte) (Signature, error) { return SignatureSecp256k1(sig__.Serialize()), nil } -func (privKey PrivKeySecp256k1) PubKey() (PubKey, error) { +func (privKey PrivKeySecp256k1) PubKey() PubKey { _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) var pub PubKeySecp256k1 copy(pub[:], pub__.SerializeCompressed()) - return pub, nil + return pub } // Equals - you probably don't need to use this. diff --git a/priv_key_test.go b/priv_key_test.go index 33f3eb7ee..c43a6d1b1 100644 --- a/priv_key_test.go +++ b/priv_key_test.go @@ -11,8 +11,7 @@ func TestGeneratePrivKey(t *testing.T) { testPriv := crypto.GenPrivKeyEd25519() testGenerate := testPriv.Generate(1) signBytes := []byte("something to sign") - pub, err := testGenerate.PubKey() - assert.NoError(t, err) + pub := testGenerate.PubKey() sig, err := testGenerate.Sign(signBytes) assert.NoError(t, err) assert.True(t, pub.VerifyBytes(signBytes, sig)) diff --git a/pub_key_test.go b/pub_key_test.go index 35c78a46a..7b856cf18 100644 --- a/pub_key_test.go +++ b/pub_key_test.go @@ -33,8 +33,7 @@ func TestPubKeySecp256k1Address(t *testing.T) { var priv PrivKeySecp256k1 copy(priv[:], privB) - pubKey, err := priv.PubKey() - assert.NoError(t, err) + pubKey := priv.PubKey() pubT, _ := pubKey.(PubKeySecp256k1) pub := pubT[:] addr := pubKey.Address() diff --git a/signature_test.go b/signature_test.go index 560815ccf..d6ae2b7a9 100644 --- a/signature_test.go +++ b/signature_test.go @@ -3,15 +3,14 @@ package crypto import ( "testing" - "github.com/stretchr/testify/require" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestSignAndValidateEd25519(t *testing.T) { privKey := GenPrivKeyEd25519() - pubKey, err := privKey.PubKey() - require.Nil(t, err) + pubKey := privKey.PubKey() msg := CRandBytes(128) sig, err := privKey.Sign(msg) @@ -30,8 +29,7 @@ func TestSignAndValidateEd25519(t *testing.T) { func TestSignAndValidateSecp256k1(t *testing.T) { privKey := GenPrivKeySecp256k1() - pubKey, err := privKey.PubKey() - require.Nil(t, err) + pubKey := privKey.PubKey() msg := CRandBytes(128) sig, err := privKey.Sign(msg) From 41369d7529bb0f79a327446dd0d35e5fe162e711 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Thu, 14 Jun 2018 00:04:30 -0700 Subject: [PATCH 267/273] circleci 2.0 (#134) * circleci 2.0 --- .circleci/circle.yml | 25 +++++++++++++++++++++++++ circle.yml | 21 --------------------- 2 files changed, 25 insertions(+), 21 deletions(-) create mode 100644 .circleci/circle.yml delete mode 100644 circle.yml diff --git a/.circleci/circle.yml b/.circleci/circle.yml new file mode 100644 index 000000000..3fc8f0b64 --- /dev/null +++ b/.circleci/circle.yml @@ -0,0 +1,25 @@ +version: 2 + +jobs: + build: + working_directory: /go/src/github.com/tendermint/go-crypto + docker: + - image: circleci/golang:1.10.0 + environment: + GOBIN: /tmp/workspace/bin + steps: + - run: mkdir -p /tmp/workspace/bin + - run: mkdir -p /tmp/workspace/profiles + - checkout + - restore_cache: + keys: + - v1-dep-{{ .Branch }} + - run: + name: test + command: | + go version + cd $PROJECT_PATH && make get_tools && make all + - save_cache: + key: v1-dep-{{ .Branch }} + paths: + - /go/pkg diff --git a/circle.yml b/circle.yml deleted file mode 100644 index af63a0594..000000000 --- a/circle.yml +++ /dev/null @@ -1,21 +0,0 @@ -machine: - environment: - GOPATH: /home/ubuntu/.go_workspace - PROJECT_PARENT_PATH: "$GOPATH/src/github.com/$CIRCLE_PROJECT_USERNAME" - PROJECT_PATH: $GOPATH/src/github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME - GO15VENDOREXPERIMENT: 1 - hosts: - circlehost: 127.0.0.1 - localhost: 127.0.0.1 - -dependencies: - override: - - mkdir -p "$PROJECT_PARENT_PATH" - - ln -sf "$HOME/$CIRCLE_PROJECT_REPONAME/" "$PROJECT_PATH" - post: - - go version - -test: - override: - - "go version" - - "cd $PROJECT_PATH && make get_tools && make all" From 1a2f468695f9a57907cda7f018855ea7cc912175 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Fri, 15 Jun 2018 15:17:40 -0700 Subject: [PATCH 268/273] fix circleci 2.0 config (#139) --- .circleci/{circle.yml => config.yml} | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) rename .circleci/{circle.yml => config.yml} (56%) diff --git a/.circleci/circle.yml b/.circleci/config.yml similarity index 56% rename from .circleci/circle.yml rename to .circleci/config.yml index 3fc8f0b64..c0bab9eae 100644 --- a/.circleci/circle.yml +++ b/.circleci/config.yml @@ -1,12 +1,13 @@ version: 2 - jobs: build: - working_directory: /go/src/github.com/tendermint/go-crypto docker: - - image: circleci/golang:1.10.0 - environment: - GOBIN: /tmp/workspace/bin + - image: circleci/golang:1.10.3 + environment: + GOBIN: /tmp/workspace/bin + + working_directory: /go/src/github.com/tendermint/go-crypto + steps: - run: mkdir -p /tmp/workspace/bin - run: mkdir -p /tmp/workspace/profiles @@ -17,9 +18,11 @@ jobs: - run: name: test command: | + export PATH="$GOBIN:$PATH" + go env go version - cd $PROJECT_PATH && make get_tools && make all - - save_cache: - key: v1-dep-{{ .Branch }} - paths: - - /go/pkg + make get_tools && make all + - save_cache: + key: v1-dep-{{ .Branch }} + paths: + - /go/pkg From fed8807a32014d14d29af31a1e02a3880b11eac5 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 19 Jun 2018 22:18:36 -0700 Subject: [PATCH 269/273] Switch xchachapoly to hkdfchachapoly (#135) * Switch from xchachapoly to hkdfchachapoly --- Gopkg.lock | 3 +- hkdfchacha20poly1305/hkdfchachapoly.go | 105 +++++++++ hkdfchacha20poly1305/hkdfchachapoly_test.go | 139 ++++++++++++ xchacha20poly1305/xchachapoly.go | 238 -------------------- xchacha20poly1305/xchachapoly_test.go | 103 --------- 5 files changed, 246 insertions(+), 342 deletions(-) create mode 100644 hkdfchacha20poly1305/hkdfchachapoly.go create mode 100644 hkdfchacha20poly1305/hkdfchachapoly_test.go delete mode 100644 xchacha20poly1305/xchachapoly.go delete mode 100644 xchacha20poly1305/xchachapoly_test.go diff --git a/Gopkg.lock b/Gopkg.lock index fbfd54dcf..7d3bac984 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -166,6 +166,7 @@ "bcrypt", "blowfish", "chacha20poly1305", + "hkdf", "internal/chacha20", "nacl/secretbox", "openpgp/armor", @@ -186,6 +187,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "1731880d432026bbd22865582cf7c7dd6d5c65618149de586e30ce156d338c01" + inputs-digest = "684746f2b651a722ee32eae056b437baf7a2213d68ddbfcefe04a1c3df27c93b" solver-name = "gps-cdcl" solver-version = 1 diff --git a/hkdfchacha20poly1305/hkdfchachapoly.go b/hkdfchacha20poly1305/hkdfchachapoly.go new file mode 100644 index 000000000..ab3b9df3a --- /dev/null +++ b/hkdfchacha20poly1305/hkdfchachapoly.go @@ -0,0 +1,105 @@ +// Package hkdfchacha20poly1305 creates an AEAD using hkdf, chacha20, and poly1305 +// When sealing and opening, the hkdf is used to obtain the nonce and subkey for +// chacha20. Other than the change for the how the subkey and nonce for chacha +// are obtained, this is the same as chacha20poly1305 +package hkdfchacha20poly1305 + +import ( + "crypto/cipher" + "crypto/sha256" + "errors" + "io" + + "golang.org/x/crypto/chacha20poly1305" + "golang.org/x/crypto/hkdf" +) + +type hkdfchacha20poly1305 struct { + key [KeySize]byte +} + +const ( + // KeySize is the size of the key used by this AEAD, in bytes. + KeySize = 32 + // NonceSize is the size of the nonce used with this AEAD, in bytes. + NonceSize = 24 + // TagSize is the size added from poly1305 + TagSize = 16 + // MaxPlaintextSize is the max size that can be passed into a single call of Seal + MaxPlaintextSize = (1 << 38) - 64 + // MaxCiphertextSize is the max size that can be passed into a single call of Open, + // this differs from plaintext size due to the tag + MaxCiphertextSize = (1 << 38) - 48 + // HkdfInfo is the parameter used internally for Hkdf's info parameter. + HkdfInfo = "TENDERMINT_SECRET_CONNECTION_FRAME_KEY_DERIVE" +) + +//New xChaChapoly1305 AEAD with 24 byte nonces +func New(key []byte) (cipher.AEAD, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20poly1305: bad key length") + } + ret := new(hkdfchacha20poly1305) + copy(ret.key[:], key) + return ret, nil + +} +func (c *hkdfchacha20poly1305) NonceSize() int { + return NonceSize +} + +func (c *hkdfchacha20poly1305) Overhead() int { + return TagSize +} + +func (c *hkdfchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != NonceSize { + panic("hkdfchacha20poly1305: bad nonce length passed to Seal") + } + + if uint64(len(plaintext)) > MaxPlaintextSize { + panic("hkdfchacha20poly1305: plaintext too large") + } + + subKey, chachaNonce := getSubkeyAndChachaNonceFromHkdf(&c.key, &nonce) + + aead, err := chacha20poly1305.New(subKey[:]) + if err != nil { + panic("hkdfchacha20poly1305: failed to initialize chacha20poly1305") + } + + return aead.Seal(dst, chachaNonce[:], plaintext, additionalData) +} + +func (c *hkdfchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != NonceSize { + return nil, errors.New("hkdfchacha20poly1305: bad nonce length passed to Open") + } + if uint64(len(ciphertext)) > MaxCiphertextSize { + return nil, errors.New("hkdfchacha20poly1305: ciphertext too large") + } + + subKey, chachaNonce := getSubkeyAndChachaNonceFromHkdf(&c.key, &nonce) + + aead, err := chacha20poly1305.New(subKey[:]) + if err != nil { + panic("hkdfchacha20poly1305: failed to initialize chacha20poly1305") + } + + return aead.Open(dst, chachaNonce[:], ciphertext, additionalData) +} + +func getSubkeyAndChachaNonceFromHkdf(cKey *[32]byte, nonce *[]byte) ( + subKey [KeySize]byte, chachaNonce [chacha20poly1305.NonceSize]byte) { + hash := sha256.New + hkdf := hkdf.New(hash, (*cKey)[:], *nonce, []byte(HkdfInfo)) + _, err := io.ReadFull(hkdf, subKey[:]) + if err != nil { + panic("hkdfchacha20poly1305: failed to read subkey from hkdf") + } + _, err = io.ReadFull(hkdf, chachaNonce[:]) + if err != nil { + panic("hkdfchacha20poly1305: failed to read chachaNonce from hkdf") + } + return +} diff --git a/hkdfchacha20poly1305/hkdfchachapoly_test.go b/hkdfchacha20poly1305/hkdfchachapoly_test.go new file mode 100644 index 000000000..66b770a18 --- /dev/null +++ b/hkdfchacha20poly1305/hkdfchachapoly_test.go @@ -0,0 +1,139 @@ +package hkdfchacha20poly1305 + +import ( + "bytes" + cr "crypto/rand" + "encoding/hex" + mr "math/rand" + "testing" + + "github.com/stretchr/testify/assert" +) + +// Test that a test vector we generated is valid. (Ensures backwards +// compatability) +func TestVector(t *testing.T) { + key, _ := hex.DecodeString("56f8de45d3c294c7675bcaf457bdd4b71c380b9b2408ce9412b348d0f08b69ee") + aead, err := New(key[:]) + if err != nil { + t.Fatal(err) + } + cts := []string{"e20a8bf42c535ac30125cfc52031577f0b", + "657695b37ba30f67b25860d90a6f1d00d8", + "e9aa6f3b7f625d957fd50f05bcdf20d014", + "8a00b3b5a6014e0d2033bebc5935086245", + "aadd74867b923879e6866ea9e03c009039", + "fc59773c2c864ee3b4cc971876b3c7bed4", + "caec14e3a9a52ce1a2682c6737defa4752", + "0b89511ffe490d2049d6950494ee51f919", + "7de854ea71f43ca35167a07566c769083d", + "cd477327f4ea4765c71e311c5fec1edbfb"} + + for i := 0; i < 10; i++ { + ct, _ := hex.DecodeString(cts[i]) + + byteArr := []byte{byte(i)} + nonce := make([]byte, 24, 24) + nonce[0] = byteArr[0] + + plaintext, err := aead.Open(nil, nonce, ct, byteArr) + if err != nil { + t.Errorf("%dth Open failed", i) + continue + } + assert.Equal(t, byteArr, plaintext) + } +} + +// The following test is taken from +// https://github.com/golang/crypto/blob/master/chacha20poly1305/chacha20poly1305_test.go#L69 +// It requires the below copyright notice, where "this source code" refers to the following function. +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found at the bottom of this file. +func TestRandom(t *testing.T) { + // Some random tests to verify Open(Seal) == Plaintext + for i := 0; i < 256; i++ { + var nonce [24]byte + var key [32]byte + + al := mr.Intn(128) + pl := mr.Intn(16384) + ad := make([]byte, al) + plaintext := make([]byte, pl) + cr.Read(key[:]) + cr.Read(nonce[:]) + cr.Read(ad) + cr.Read(plaintext) + + aead, err := New(key[:]) + if err != nil { + t.Fatal(err) + } + + ct := aead.Seal(nil, nonce[:], plaintext, ad) + + plaintext2, err := aead.Open(nil, nonce[:], ct, ad) + if err != nil { + t.Errorf("Random #%d: Open failed", i) + continue + } + + if !bytes.Equal(plaintext, plaintext2) { + t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) + continue + } + + if len(ad) > 0 { + alterAdIdx := mr.Intn(len(ad)) + ad[alterAdIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering additional data", i) + } + ad[alterAdIdx] ^= 0x80 + } + + alterNonceIdx := mr.Intn(aead.NonceSize()) + nonce[alterNonceIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering nonce", i) + } + nonce[alterNonceIdx] ^= 0x80 + + alterCtIdx := mr.Intn(len(ct)) + ct[alterCtIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering ciphertext", i) + } + ct[alterCtIdx] ^= 0x80 + } +} + +// AFOREMENTIONED LICENCE +// Copyright (c) 2009 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/xchacha20poly1305/xchachapoly.go b/xchacha20poly1305/xchachapoly.go deleted file mode 100644 index 9e0778579..000000000 --- a/xchacha20poly1305/xchachapoly.go +++ /dev/null @@ -1,238 +0,0 @@ -package xchacha20poly1305 - -import ( - "crypto/cipher" - "encoding/binary" - "errors" - "fmt" - - "golang.org/x/crypto/chacha20poly1305" -) - -var sigma = [4]uint32{0x61707865, 0x3320646e, 0x79622d32, 0x6b206574} - -type xchacha20poly1305 struct { - key [KeySize]byte -} - -const ( - // KeySize is the size of the key used by this AEAD, in bytes. - KeySize = 32 - // NonceSize is the size of the nonce used with this AEAD, in bytes. - NonceSize = 24 -) - -//New xChaChapoly1305 AEAD with 24 byte nonces -func New(key []byte) (cipher.AEAD, error) { - if len(key) != KeySize { - return nil, errors.New("chacha20poly1305: bad key length") - } - ret := new(xchacha20poly1305) - copy(ret.key[:], key) - return ret, nil - -} -func (c *xchacha20poly1305) NonceSize() int { - return NonceSize -} - -func (c *xchacha20poly1305) Overhead() int { - return 16 -} - -func (c *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { - if len(nonce) != NonceSize { - panic("xchacha20poly1305: bad nonce length passed to Seal") - } - - if uint64(len(plaintext)) > (1<<38)-64 { - panic("xchacha20poly1305: plaintext too large") - } - - var subKey [KeySize]byte - var hNonce [16]byte - var subNonce [chacha20poly1305.NonceSize]byte - copy(hNonce[:], nonce[:16]) - - HChaCha20(&subKey, &hNonce, &c.key) - - chacha20poly1305, _ := chacha20poly1305.New(subKey[:]) - - copy(subNonce[4:], nonce[16:]) - - return chacha20poly1305.Seal(dst, subNonce[:], plaintext, additionalData) -} - -func (c *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { - if len(nonce) != NonceSize { - return nil, fmt.Errorf("xchacha20poly1305: bad nonce length passed to Open") - } - if uint64(len(ciphertext)) > (1<<38)-48 { - return nil, fmt.Errorf("xchacha20poly1305: ciphertext too large") - } - var subKey [KeySize]byte - var hNonce [16]byte - var subNonce [chacha20poly1305.NonceSize]byte - copy(hNonce[:], nonce[:16]) - - HChaCha20(&subKey, &hNonce, &c.key) - - chacha20poly1305, _ := chacha20poly1305.New(subKey[:]) - - copy(subNonce[4:], nonce[16:]) - - return chacha20poly1305.Open(dst, subNonce[:], ciphertext, additionalData) -} - -// The MIT License (MIT) - -// Copyright (c) 2016 Andreas Auernhammer - -// 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. - -// HChaCha20 generates 32 pseudo-random bytes from a 128 bit nonce and a 256 bit secret key. -// It can be used as a key-derivation-function (KDF). -func HChaCha20(out *[32]byte, nonce *[16]byte, key *[32]byte) { hChaCha20Generic(out, nonce, key) } - -func hChaCha20Generic(out *[32]byte, nonce *[16]byte, key *[32]byte) { - v00 := sigma[0] - v01 := sigma[1] - v02 := sigma[2] - v03 := sigma[3] - v04 := binary.LittleEndian.Uint32(key[0:]) - v05 := binary.LittleEndian.Uint32(key[4:]) - v06 := binary.LittleEndian.Uint32(key[8:]) - v07 := binary.LittleEndian.Uint32(key[12:]) - v08 := binary.LittleEndian.Uint32(key[16:]) - v09 := binary.LittleEndian.Uint32(key[20:]) - v10 := binary.LittleEndian.Uint32(key[24:]) - v11 := binary.LittleEndian.Uint32(key[28:]) - v12 := binary.LittleEndian.Uint32(nonce[0:]) - v13 := binary.LittleEndian.Uint32(nonce[4:]) - v14 := binary.LittleEndian.Uint32(nonce[8:]) - v15 := binary.LittleEndian.Uint32(nonce[12:]) - - for i := 0; i < 20; i += 2 { - v00 += v04 - v12 ^= v00 - v12 = (v12 << 16) | (v12 >> 16) - v08 += v12 - v04 ^= v08 - v04 = (v04 << 12) | (v04 >> 20) - v00 += v04 - v12 ^= v00 - v12 = (v12 << 8) | (v12 >> 24) - v08 += v12 - v04 ^= v08 - v04 = (v04 << 7) | (v04 >> 25) - v01 += v05 - v13 ^= v01 - v13 = (v13 << 16) | (v13 >> 16) - v09 += v13 - v05 ^= v09 - v05 = (v05 << 12) | (v05 >> 20) - v01 += v05 - v13 ^= v01 - v13 = (v13 << 8) | (v13 >> 24) - v09 += v13 - v05 ^= v09 - v05 = (v05 << 7) | (v05 >> 25) - v02 += v06 - v14 ^= v02 - v14 = (v14 << 16) | (v14 >> 16) - v10 += v14 - v06 ^= v10 - v06 = (v06 << 12) | (v06 >> 20) - v02 += v06 - v14 ^= v02 - v14 = (v14 << 8) | (v14 >> 24) - v10 += v14 - v06 ^= v10 - v06 = (v06 << 7) | (v06 >> 25) - v03 += v07 - v15 ^= v03 - v15 = (v15 << 16) | (v15 >> 16) - v11 += v15 - v07 ^= v11 - v07 = (v07 << 12) | (v07 >> 20) - v03 += v07 - v15 ^= v03 - v15 = (v15 << 8) | (v15 >> 24) - v11 += v15 - v07 ^= v11 - v07 = (v07 << 7) | (v07 >> 25) - v00 += v05 - v15 ^= v00 - v15 = (v15 << 16) | (v15 >> 16) - v10 += v15 - v05 ^= v10 - v05 = (v05 << 12) | (v05 >> 20) - v00 += v05 - v15 ^= v00 - v15 = (v15 << 8) | (v15 >> 24) - v10 += v15 - v05 ^= v10 - v05 = (v05 << 7) | (v05 >> 25) - v01 += v06 - v12 ^= v01 - v12 = (v12 << 16) | (v12 >> 16) - v11 += v12 - v06 ^= v11 - v06 = (v06 << 12) | (v06 >> 20) - v01 += v06 - v12 ^= v01 - v12 = (v12 << 8) | (v12 >> 24) - v11 += v12 - v06 ^= v11 - v06 = (v06 << 7) | (v06 >> 25) - v02 += v07 - v13 ^= v02 - v13 = (v13 << 16) | (v13 >> 16) - v08 += v13 - v07 ^= v08 - v07 = (v07 << 12) | (v07 >> 20) - v02 += v07 - v13 ^= v02 - v13 = (v13 << 8) | (v13 >> 24) - v08 += v13 - v07 ^= v08 - v07 = (v07 << 7) | (v07 >> 25) - v03 += v04 - v14 ^= v03 - v14 = (v14 << 16) | (v14 >> 16) - v09 += v14 - v04 ^= v09 - v04 = (v04 << 12) | (v04 >> 20) - v03 += v04 - v14 ^= v03 - v14 = (v14 << 8) | (v14 >> 24) - v09 += v14 - v04 ^= v09 - v04 = (v04 << 7) | (v04 >> 25) - } - - binary.LittleEndian.PutUint32(out[0:], v00) - binary.LittleEndian.PutUint32(out[4:], v01) - binary.LittleEndian.PutUint32(out[8:], v02) - binary.LittleEndian.PutUint32(out[12:], v03) - binary.LittleEndian.PutUint32(out[16:], v12) - binary.LittleEndian.PutUint32(out[20:], v13) - binary.LittleEndian.PutUint32(out[24:], v14) - binary.LittleEndian.PutUint32(out[28:], v15) -} diff --git a/xchacha20poly1305/xchachapoly_test.go b/xchacha20poly1305/xchachapoly_test.go deleted file mode 100644 index 3001217f4..000000000 --- a/xchacha20poly1305/xchachapoly_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package xchacha20poly1305 - -import ( - "bytes" - "encoding/hex" - "testing" -) - -func toHex(bits []byte) string { - return hex.EncodeToString(bits) -} - -func fromHex(bits string) []byte { - b, err := hex.DecodeString(bits) - if err != nil { - panic(err) - } - return b -} - -func TestHChaCha20(t *testing.T) { - for i, v := range hChaCha20Vectors { - var key [32]byte - var nonce [16]byte - copy(key[:], v.key) - copy(nonce[:], v.nonce) - - HChaCha20(&key, &nonce, &key) - if !bytes.Equal(key[:], v.keystream) { - t.Errorf("Test %d: keystream mismatch:\n \t got: %s\n \t want: %s", i, toHex(key[:]), toHex(v.keystream)) - } - } -} - -var hChaCha20Vectors = []struct { - key, nonce, keystream []byte -}{ - { - fromHex("0000000000000000000000000000000000000000000000000000000000000000"), - fromHex("000000000000000000000000000000000000000000000000"), - fromHex("1140704c328d1d5d0e30086cdf209dbd6a43b8f41518a11cc387b669b2ee6586"), - }, - { - fromHex("8000000000000000000000000000000000000000000000000000000000000000"), - fromHex("000000000000000000000000000000000000000000000000"), - fromHex("7d266a7fd808cae4c02a0a70dcbfbcc250dae65ce3eae7fc210f54cc8f77df86"), - }, - { - fromHex("0000000000000000000000000000000000000000000000000000000000000001"), - fromHex("000000000000000000000000000000000000000000000002"), - fromHex("e0c77ff931bb9163a5460c02ac281c2b53d792b1c43fea817e9ad275ae546963"), - }, - { - fromHex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), - fromHex("000102030405060708090a0b0c0d0e0f1011121314151617"), - fromHex("51e3ff45a895675c4b33b46c64f4a9ace110d34df6a2ceab486372bacbd3eff6"), - }, - { - fromHex("24f11cce8a1b3d61e441561a696c1c1b7e173d084fd4812425435a8896a013dc"), - fromHex("d9660c5900ae19ddad28d6e06e45fe5e"), - fromHex("5966b3eec3bff1189f831f06afe4d4e3be97fa9235ec8c20d08acfbbb4e851e3"), - }, -} - -func TestVectors(t *testing.T) { - for i, v := range vectors { - if len(v.plaintext) == 0 { - v.plaintext = make([]byte, len(v.ciphertext)) - } - - var nonce [24]byte - copy(nonce[:], v.nonce) - - aead, err := New(v.key) - if err != nil { - t.Error(err) - } - - dst := aead.Seal(nil, nonce[:], v.plaintext, v.ad) - if !bytes.Equal(dst, v.ciphertext) { - t.Errorf("Test %d: ciphertext mismatch:\n \t got: %s\n \t want: %s", i, toHex(dst), toHex(v.ciphertext)) - } - open, err := aead.Open(nil, nonce[:], dst, v.ad) - if err != nil { - t.Error(err) - } - if !bytes.Equal(open, v.plaintext) { - t.Errorf("Test %d: plaintext mismatch:\n \t got: %s\n \t want: %s", i, string(open), string(v.plaintext)) - } - } -} - -var vectors = []struct { - key, nonce, ad, plaintext, ciphertext []byte -}{ - { - []byte{0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f}, - []byte{0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b}, - []byte{0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7}, - []byte("Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."), - []byte{0x45, 0x3c, 0x06, 0x93, 0xa7, 0x40, 0x7f, 0x04, 0xff, 0x4c, 0x56, 0xae, 0xdb, 0x17, 0xa3, 0xc0, 0xa1, 0xaf, 0xff, 0x01, 0x17, 0x49, 0x30, 0xfc, 0x22, 0x28, 0x7c, 0x33, 0xdb, 0xcf, 0x0a, 0xc8, 0xb8, 0x9a, 0xd9, 0x29, 0x53, 0x0a, 0x1b, 0xb3, 0xab, 0x5e, 0x69, 0xf2, 0x4c, 0x7f, 0x60, 0x70, 0xc8, 0xf8, 0x40, 0xc9, 0xab, 0xb4, 0xf6, 0x9f, 0xbf, 0xc8, 0xa7, 0xff, 0x51, 0x26, 0xfa, 0xee, 0xbb, 0xb5, 0x58, 0x05, 0xee, 0x9c, 0x1c, 0xf2, 0xce, 0x5a, 0x57, 0x26, 0x32, 0x87, 0xae, 0xc5, 0x78, 0x0f, 0x04, 0xec, 0x32, 0x4c, 0x35, 0x14, 0x12, 0x2c, 0xfc, 0x32, 0x31, 0xfc, 0x1a, 0x8b, 0x71, 0x8a, 0x62, 0x86, 0x37, 0x30, 0xa2, 0x70, 0x2b, 0xb7, 0x63, 0x66, 0x11, 0x6b, 0xed, 0x09, 0xe0, 0xfd, 0x5c, 0x6d, 0x84, 0xb6, 0xb0, 0xc1, 0xab, 0xaf, 0x24, 0x9d, 0x5d, 0xd0, 0xf7, 0xf5, 0xa7, 0xea}, - }, -} From 4634063698d3ffdcd1645769ea8fee989cd362fe Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 20 Jun 2018 13:30:22 -0700 Subject: [PATCH 270/273] keys package: fundraiser compatibility and HD keys (BIP 39 & BIP 32 / BIP 44) (#118) - fundraiser compatibility for HD keys (BIP 39 & BIP 32 / BIP 44) --- Gopkg.lock | 12 +- Gopkg.toml | 4 - Makefile | 2 +- amino.go | 1 + armor.go | 8 +- keys/bcrypt/bcrypt.go | 2 +- keys/bip39/wordcodec.go | 62 + keys/bip39/wordcodec_test.go | 15 + keys/hd/address.go | 352 ---- keys/hd/address_test.go | 37 - keys/hd/fundraiser_test.go | 83 + keys/hd/hd_test.go | 238 --- keys/hd/hdpath.go | 168 ++ keys/hd/hdpath_test.go | 73 + keys/keybase.go | 174 +- keys/keybase_test.go | 172 +- keys/keys.go | 36 +- keys/types.go | 17 +- keys/words/ecc.go | 208 -- keys/words/ecc_test.go | 62 - keys/words/wordcodec.go | 200 -- keys/words/wordcodec_test.go | 180 -- keys/words/wordcodecbench_test.go | 68 - keys/words/wordlist/chinese_simplified.txt | 2048 -------------------- keys/words/wordlist/english.txt | 2048 -------------------- keys/words/wordlist/japanese.txt | 2048 -------------------- keys/words/wordlist/spanish.txt | 2048 -------------------- keys/words/wordlist/wordlist.go | 310 --- 28 files changed, 590 insertions(+), 10086 deletions(-) create mode 100644 keys/bip39/wordcodec.go create mode 100644 keys/bip39/wordcodec_test.go delete mode 100644 keys/hd/address.go delete mode 100644 keys/hd/address_test.go create mode 100644 keys/hd/fundraiser_test.go delete mode 100644 keys/hd/hd_test.go create mode 100644 keys/hd/hdpath.go create mode 100644 keys/hd/hdpath_test.go delete mode 100644 keys/words/ecc.go delete mode 100644 keys/words/ecc_test.go delete mode 100644 keys/words/wordcodec.go delete mode 100644 keys/words/wordcodec_test.go delete mode 100644 keys/words/wordcodecbench_test.go delete mode 100644 keys/words/wordlist/chinese_simplified.txt delete mode 100644 keys/words/wordlist/english.txt delete mode 100644 keys/words/wordlist/japanese.txt delete mode 100644 keys/words/wordlist/spanish.txt delete mode 100644 keys/words/wordlist/wordlist.go diff --git a/Gopkg.lock b/Gopkg.lock index 7d3bac984..83fe33bd7 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,12 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + name = "github.com/bartekn/go-bip39" + packages = ["."] + revision = "a05967ea095d81c8fe4833776774cfaff8e5036c" + [[projects]] branch = "master" name = "github.com/brejski/hid" @@ -63,12 +69,6 @@ packages = ["."] revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" -[[projects]] - branch = "master" - name = "github.com/howeyc/crc16" - packages = ["."] - revision = "2b2a61e366a66d3efb279e46176e7291001e0354" - [[projects]] branch = "master" name = "github.com/jmhodges/levigo" diff --git a/Gopkg.toml b/Gopkg.toml index df7e5e221..92bfecacd 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -28,10 +28,6 @@ name = "github.com/btcsuite/btcutil" branch = "master" -[[constraint]] - name = "github.com/howeyc/crc16" - branch = "master" - [[constraint]] name = "github.com/pkg/errors" version = "0.8.0" diff --git a/Makefile b/Makefile index 74af29941..96f4ae06d 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ check: check_tools # Command to generate the workd list (kept here for documentation purposes only): wordlist: # To re-generate wordlist.go run: - # go-bindata -ignore ".*\.go" -o keys/words/wordlist/wordlist.go -pkg "wordlist" keys/words/wordlist/... + # go-bindata -ignore ".*\.go" -o keys/words/bip39/wordlist.go -pkg "wordlist" keys/bip39/wordlist/... build: wordlist # Nothing else to build! diff --git a/amino.go b/amino.go index ddf3e193a..63e4c4ac3 100644 --- a/amino.go +++ b/amino.go @@ -15,6 +15,7 @@ func init() { RegisterAmino(cdc) } +// RegisterAmino registers all go-crypto related types in the given (amino) codec. func RegisterAmino(cdc *amino.Codec) { cdc.RegisterInterface((*PubKey)(nil), nil) cdc.RegisterConcrete(PubKeyEd25519{}, diff --git a/armor.go b/armor.go index 5f199df43..4146048ad 100644 --- a/armor.go +++ b/armor.go @@ -2,9 +2,9 @@ package crypto import ( "bytes" + "fmt" "io/ioutil" - . "github.com/tendermint/tmlibs/common" "golang.org/x/crypto/openpgp/armor" ) @@ -12,15 +12,15 @@ func EncodeArmor(blockType string, headers map[string]string, data []byte) strin buf := new(bytes.Buffer) w, err := armor.Encode(buf, blockType, headers) if err != nil { - PanicSanity("Error encoding ascii armor: " + err.Error()) + panic(fmt.Errorf("could not encode ascii armor: %s", err)) } _, err = w.Write(data) if err != nil { - PanicSanity("Error encoding ascii armor: " + err.Error()) + panic(fmt.Errorf("could not encode ascii armor: %s", err)) } err = w.Close() if err != nil { - PanicSanity("Error encoding ascii armor: " + err.Error()) + panic(fmt.Errorf("could not encode ascii armor: %s", err)) } return buf.String() } diff --git a/keys/bcrypt/bcrypt.go b/keys/bcrypt/bcrypt.go index 6b23b7a9d..ce2b9f4bc 100644 --- a/keys/bcrypt/bcrypt.go +++ b/keys/bcrypt/bcrypt.go @@ -88,7 +88,7 @@ type hashed struct { // to compare the returned hashed password with its cleartext version. func GenerateFromPassword(salt []byte, password []byte, cost int) ([]byte, error) { if len(salt) != maxSaltSize { - return nil, fmt.Errorf("Salt len must be %v", maxSaltSize) + return nil, fmt.Errorf("salt len must be %v", maxSaltSize) } p, err := newFromPassword(salt, password, cost) if err != nil { diff --git a/keys/bip39/wordcodec.go b/keys/bip39/wordcodec.go new file mode 100644 index 000000000..b0c23e629 --- /dev/null +++ b/keys/bip39/wordcodec.go @@ -0,0 +1,62 @@ +package bip39 + +import ( + "strings" + + "github.com/bartekn/go-bip39" +) + +// ValidSentenceLen defines the mnemonic sentence lengths supported by this BIP 39 library. +type ValidSentenceLen uint8 + +const ( + // FundRaiser is the sentence length used during the cosmos fundraiser (12 words). + FundRaiser ValidSentenceLen = 12 + // FreshKey is the sentence length used for newly created keys (24 words). + FreshKey ValidSentenceLen = 24 +) + +// NewMnemonic will return a string consisting of the mnemonic words for +// the given sentence length. +func NewMnemonic(len ValidSentenceLen) (words []string, err error) { + // len = (ENT + checksum) / 11 + var ENT int + switch len { + case FundRaiser: + ENT = 128 + case FreshKey: + ENT = 256 + } + var entropy []byte + entropy, err = bip39.NewEntropy(ENT) + if err != nil { + return + } + var mnemonic string + mnemonic, err = bip39.NewMnemonic(entropy) + if err != nil { + return + } + words = strings.Split(mnemonic, " ") + return +} + +// MnemonicToSeed creates a BIP 39 seed from the passed mnemonic (with an empty BIP 39 password). +// This method does not validate the mnemonics checksum. +func MnemonicToSeed(mne string) (seed []byte) { + // we do not checksum here... + seed = bip39.NewSeed(mne, "") + return +} + +// MnemonicToSeedWithErrChecking returns the same seed as MnemonicToSeed. +// It creates a BIP 39 seed from the passed mnemonic (with an empty BIP 39 password). +// +// Different from MnemonicToSeed it validates the checksum. +// For details on the checksum see the BIP 39 spec. +func MnemonicToSeedWithErrChecking(mne string) (seed []byte, err error) { + seed, err = bip39.NewSeedWithErrorChecking(mne, "") + return +} + + diff --git a/keys/bip39/wordcodec_test.go b/keys/bip39/wordcodec_test.go new file mode 100644 index 000000000..dbc5c0d02 --- /dev/null +++ b/keys/bip39/wordcodec_test.go @@ -0,0 +1,15 @@ +package bip39 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestWordCodec_NewMnemonic(t *testing.T) { + _, err := NewMnemonic(FundRaiser) + assert.NoError(t, err, "unexpected error generating fundraiser mnemonic") + + _, err = NewMnemonic(FreshKey) + assert.NoError(t, err, "unexpected error generating new 24-word mnemonic") +} diff --git a/keys/hd/address.go b/keys/hd/address.go deleted file mode 100644 index 9511ffad2..000000000 --- a/keys/hd/address.go +++ /dev/null @@ -1,352 +0,0 @@ -package hd - -// XXX This package doesn't work with our address scheme, -// XXX and it probably doesn't work for our other pubkey types. -// XXX Fix it up to be more general but compatible. - -import ( - "crypto/ecdsa" - "crypto/hmac" - "crypto/sha256" - "crypto/sha512" - "encoding/base64" - "encoding/binary" - "encoding/hex" - "errors" - "fmt" - "hash" - "math/big" - "strconv" - "strings" - - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcutil/base58" - "golang.org/x/crypto/ripemd160" -) - -/* - - This file implements BIP32 HD wallets. - Note it only works for SECP256k1 keys. - It also includes some Bitcoin specific utility functions. - -*/ - -// ComputeBTCAddress returns the BTC address using the pubKeyHex and chainCodeHex -// for the given path and index. -func ComputeBTCAddress(pubKeyHex string, chainCodeHex string, path string, index int32) string { - pubKeyBytes := DerivePublicKeyForPath( - HexDecode(pubKeyHex), - HexDecode(chainCodeHex), - fmt.Sprintf("%v/%v", path, index), - ) - return BTCAddrFromPubKeyBytes(pubKeyBytes) -} - -// ComputePrivateKey returns the private key using the master mprivHex and chainCodeHex -// for the given path and index. -func ComputePrivateKey(mprivHex string, chainHex string, path string, index int32) string { - privKeyBytes := DerivePrivateKeyForPath( - HexDecode(mprivHex), - HexDecode(chainHex), - fmt.Sprintf("%v/%v", path, index), - ) - return HexEncode(privKeyBytes) -} - -// ComputeBTCAddressForPrivKey returns the Bitcoin address for the given privKey. -func ComputeBTCAddressForPrivKey(privKey string) string { - pubKeyBytes := PubKeyBytesFromPrivKeyBytes(HexDecode(privKey), true) - return BTCAddrFromPubKeyBytes(pubKeyBytes) -} - -// SignBTCMessage signs a "Bitcoin Signed Message". -func SignBTCMessage(privKey string, message string, compress bool) string { - prefixBytes := []byte("Bitcoin Signed Message:\n") - messageBytes := []byte(message) - bytes := []byte{} - bytes = append(bytes, byte(len(prefixBytes))) - bytes = append(bytes, prefixBytes...) - bytes = append(bytes, byte(len(messageBytes))) - bytes = append(bytes, messageBytes...) - privKeyBytes := HexDecode(privKey) - x, y := btcec.S256().ScalarBaseMult(privKeyBytes) - ecdsaPubKey := ecdsa.PublicKey{ - Curve: btcec.S256(), - X: x, - Y: y, - } - ecdsaPrivKey := &btcec.PrivateKey{ - PublicKey: ecdsaPubKey, - D: new(big.Int).SetBytes(privKeyBytes), - } - sigbytes, err := btcec.SignCompact(btcec.S256(), ecdsaPrivKey, CalcHash256(bytes), compress) - if err != nil { - panic(err) - } - return base64.StdEncoding.EncodeToString(sigbytes) -} - -// ComputeMastersFromSeed returns the master public key, master secret, and chain code in hex. -func ComputeMastersFromSeed(seed string) (string, string, string) { - key, data := []byte("Bitcoin seed"), []byte(seed) - secret, chain := I64(key, data) - pubKeyBytes := PubKeyBytesFromPrivKeyBytes(secret, true) - return HexEncode(pubKeyBytes), HexEncode(secret), HexEncode(chain) -} - -// ComputeWIF returns the privKey in Wallet Import Format. -func ComputeWIF(privKey string, compress bool) string { - return WIFFromPrivKeyBytes(HexDecode(privKey), compress) -} - -// ComputeBTCTxId returns the bitcoin transaction ID. -func ComputeBTCTxId(rawTxHex string) string { - return HexEncode(ReverseBytes(CalcHash256(HexDecode(rawTxHex)))) -} - -/* -func printKeyInfo(privKeyBytes []byte, pubKeyBytes []byte, chain []byte) { - if pubKeyBytes == nil { - pubKeyBytes = PubKeyBytesFromPrivKeyBytes(privKeyBytes, true) - } - addr := AddrFromPubKeyBytes(pubKeyBytes) - log.Println("\nprikey:\t%v\npubKeyBytes:\t%v\naddr:\t%v\nchain:\t%v", - HexEncode(privKeyBytes), - HexEncode(pubKeyBytes), - addr, - HexEncode(chain)) -} -*/ - -//------------------------------------------------------------------- - -// DerivePrivateKeyForPath derives the private key by following the path from privKeyBytes, -// using the given chainCode. -func DerivePrivateKeyForPath(privKeyBytes []byte, chainCode []byte, path string) []byte { - data := privKeyBytes - parts := strings.Split(path, "/") - for _, part := range parts { - prime := part[len(part)-1:] == "'" - // prime == private derivation. Otherwise public. - if prime { - part = part[:len(part)-1] - } - i, err := strconv.Atoi(part) - if err != nil { - panic(err) - } - if i < 0 { - panic(errors.New("index too large.")) - } - data, chainCode = DerivePrivateKey(data, chainCode, uint32(i), prime) - //printKeyInfo(data, nil, chain) - } - return data -} - -// DerivePublicKeyForPath derives the public key by following the path from pubKeyBytes -// using the given chainCode. -func DerivePublicKeyForPath(pubKeyBytes []byte, chainCode []byte, path string) []byte { - data := pubKeyBytes - parts := strings.Split(path, "/") - for _, part := range parts { - prime := part[len(part)-1:] == "'" - if prime { - panic(errors.New("cannot do a prime derivation from public key")) - } - i, err := strconv.Atoi(part) - if err != nil { - panic(err) - } - if i < 0 { - panic(errors.New("index too large.")) - } - data, chainCode = DerivePublicKey(data, chainCode, uint32(i)) - //printKeyInfo(nil, data, chainCode) - } - return data -} - -// DerivePrivateKey derives the private key with index and chainCode. -// If prime is true, the derivation is 'hardened'. -// It returns the new private key and new chain code. -func DerivePrivateKey(privKeyBytes []byte, chainCode []byte, index uint32, prime bool) ([]byte, []byte) { - var data []byte - if prime { - index = index | 0x80000000 - data = append([]byte{byte(0)}, privKeyBytes...) - } else { - public := PubKeyBytesFromPrivKeyBytes(privKeyBytes, true) - data = public - } - data = append(data, uint32ToBytes(index)...) - data2, chainCode2 := I64(chainCode, data) - x := addScalars(privKeyBytes, data2) - return x, chainCode2 -} - -// DerivePublicKey derives the public key with index and chainCode. -// It returns the new public key and new chain code. -func DerivePublicKey(pubKeyBytes []byte, chainCode []byte, index uint32) ([]byte, []byte) { - data := []byte{} - data = append(data, pubKeyBytes...) - data = append(data, uint32ToBytes(index)...) - data2, chainCode2 := I64(chainCode, data) - data2p := PubKeyBytesFromPrivKeyBytes(data2, true) - return addPoints(pubKeyBytes, data2p), chainCode2 -} - -// eliptic curve pubkey addition -func addPoints(a []byte, b []byte) []byte { - ap, err := btcec.ParsePubKey(a, btcec.S256()) - if err != nil { - panic(err) - } - bp, err := btcec.ParsePubKey(b, btcec.S256()) - if err != nil { - panic(err) - } - sumX, sumY := btcec.S256().Add(ap.X, ap.Y, bp.X, bp.Y) - sum := &btcec.PublicKey{ - Curve: btcec.S256(), - X: sumX, - Y: sumY, - } - return sum.SerializeCompressed() -} - -// modular big endian addition -func addScalars(a []byte, b []byte) []byte { - aInt := new(big.Int).SetBytes(a) - bInt := new(big.Int).SetBytes(b) - sInt := new(big.Int).Add(aInt, bInt) - x := sInt.Mod(sInt, btcec.S256().N).Bytes() - x2 := [32]byte{} - copy(x2[32-len(x):], x) - return x2[:] -} - -func uint32ToBytes(i uint32) []byte { - b := [4]byte{} - binary.BigEndian.PutUint32(b[:], i) - return b[:] -} - -//------------------------------------------------------------------- - -// HexEncode encodes b in hex. -func HexEncode(b []byte) string { - return hex.EncodeToString(b) -} - -// HexDecode hex decodes the str. If str is not valid hex -// it will return an empty byte slice. -func HexDecode(str string) []byte { - b, _ := hex.DecodeString(str) - return b -} - -// I64 returns the two halfs of the SHA512 HMAC of key and data. -func I64(key []byte, data []byte) ([]byte, []byte) { - mac := hmac.New(sha512.New, key) - mac.Write(data) - I := mac.Sum(nil) - return I[:32], I[32:] -} - -//------------------------------------------------------------------- - -const ( - btcPrefixPubKeyHash = byte(0x00) - btcPrefixPrivKey = byte(0x80) -) - -// BTCAddrFromPubKeyBytes returns a B58 encoded Bitcoin mainnet address. -func BTCAddrFromPubKeyBytes(pubKeyBytes []byte) string { - versionPrefix := btcPrefixPubKeyHash // TODO Make const or configurable - h160 := CalcHash160(pubKeyBytes) - h160 = append([]byte{versionPrefix}, h160...) - checksum := CalcHash256(h160) - b := append(h160, checksum[:4]...) - return base58.Encode(b) -} - -// BTCAddrBytesFromPubKeyBytes returns a hex Bitcoin mainnet address and its checksum. -func BTCAddrBytesFromPubKeyBytes(pubKeyBytes []byte) (addrBytes []byte, checksum []byte) { - versionPrefix := btcPrefixPubKeyHash // TODO Make const or configurable - h160 := CalcHash160(pubKeyBytes) - _h160 := append([]byte{versionPrefix}, h160...) - checksum = CalcHash256(_h160)[:4] - return h160, checksum -} - -// WIFFromPrivKeyBytes returns the privKeyBytes in Wallet Import Format. -func WIFFromPrivKeyBytes(privKeyBytes []byte, compress bool) string { - versionPrefix := btcPrefixPrivKey // TODO Make const or configurable - bytes := append([]byte{versionPrefix}, privKeyBytes...) - if compress { - bytes = append(bytes, byte(1)) - } - checksum := CalcHash256(bytes) - bytes = append(bytes, checksum[:4]...) - return base58.Encode(bytes) -} - -// PubKeyBytesFromPrivKeyBytes returns the optionally compressed public key bytes. -func PubKeyBytesFromPrivKeyBytes(privKeyBytes []byte, compress bool) (pubKeyBytes []byte) { - x, y := btcec.S256().ScalarBaseMult(privKeyBytes) - pub := &btcec.PublicKey{ - Curve: btcec.S256(), - X: x, - Y: y, - } - - if compress { - return pub.SerializeCompressed() - } - return pub.SerializeUncompressed() -} - -//-------------------------------------------------------------- - -// CalcHash returns the hash of data using hasher. -func CalcHash(data []byte, hasher hash.Hash) []byte { - hasher.Write(data) - return hasher.Sum(nil) -} - -// CalcHash160 returns the ripemd160(sha256(data)). -func CalcHash160(data []byte) []byte { - return CalcHash(CalcHash(data, sha256.New()), ripemd160.New()) -} - -// CalcHash256 returns the sha256(sha256(data)). -func CalcHash256(data []byte) []byte { - return CalcHash(CalcHash(data, sha256.New()), sha256.New()) -} - -// CalcSha512 returns the sha512(data). -func CalcSha512(data []byte) []byte { - return CalcHash(data, sha512.New()) -} - -// ReverseBytes returns the buf in the opposite order -func ReverseBytes(buf []byte) []byte { - var res []byte - if len(buf) == 0 { - return res - } - - // Walk till mid-way, swapping bytes from each end: - // b[i] and b[len-i-1] - blen := len(buf) - res = make([]byte, blen) - mid := blen / 2 - for left := 0; left <= mid; left++ { - right := blen - left - 1 - res[left] = buf[right] - res[right] = buf[left] - } - return res -} diff --git a/keys/hd/address_test.go b/keys/hd/address_test.go deleted file mode 100644 index 0554733f1..000000000 --- a/keys/hd/address_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package hd - -/* - -import ( - "encoding/hex" - "fmt" - "testing" -) - -func TestManual(t *testing.T) { - bytes, _ := hex.DecodeString("dfac699f1618c9be4df2befe94dc5f313946ebafa386756bd4926a1ecfd7cf2438426ede521d1ee6512391bc200b7910bcbea593e68d52b874c29bdc5a308ed1") - fmt.Println(bytes) - puk, prk, ch, se := ComputeMastersFromSeed(string(bytes)) - fmt.Println(puk, ch, se) - - pubBytes2 := DerivePublicKeyForPath( - HexDecode(puk), - HexDecode(ch), - //"44'/118'/0'/0/0", - "0/0", - ) - fmt.Printf("PUB2 %X\n", pubBytes2) - - privBytes := DerivePrivateKeyForPath( - HexDecode(prk), - HexDecode(ch), - //"44'/118'/0'/0/0", - //"0/0", - "44'/118'/0'/0/0", - ) - fmt.Printf("PRIV %X\n", privBytes) - pubBytes := PubKeyBytesFromPrivKeyBytes(privBytes, true) - fmt.Printf("PUB %X\n", pubBytes) -} - -*/ diff --git a/keys/hd/fundraiser_test.go b/keys/hd/fundraiser_test.go new file mode 100644 index 000000000..63607b0a5 --- /dev/null +++ b/keys/hd/fundraiser_test.go @@ -0,0 +1,83 @@ +package hd + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/tyler-smith/go-bip39" + + "github.com/tendermint/go-crypto" +) + +type addrData struct { + Mnemonic string + Master string + Seed string + Priv string + Pub string + Addr string +} + + +func initFundraiserTestVectors(t *testing.T) []addrData { + // NOTE: atom fundraiser address + // var hdPath string = "m/44'/118'/0'/0/0" + var hdToAddrTable []addrData + + b, err := ioutil.ReadFile("test.json") + if err != nil { + t.Fatalf("could not read fundraiser test vector file (test.json): %s", err) + } + + err = json.Unmarshal(b, &hdToAddrTable) + if err != nil { + t.Fatalf("could not decode test vectors (test.json): %s", err) + } + return hdToAddrTable +} + +func TestFundraiserCompatibility(t *testing.T) { + hdToAddrTable := initFundraiserTestVectors(t) + + for i, d := range hdToAddrTable { + privB, _ := hex.DecodeString(d.Priv) + pubB, _ := hex.DecodeString(d.Pub) + addrB, _ := hex.DecodeString(d.Addr) + seedB, _ := hex.DecodeString(d.Seed) + masterB, _ := hex.DecodeString(d.Master) + + seed := bip39.NewSeed(d.Mnemonic, "") + + t.Log("================================") + t.Logf("ROUND: %d MNEMONIC: %s", i, d.Mnemonic) + + master, ch := ComputeMastersFromSeed(seed) + priv, err := DerivePrivateKeyForPath(master, ch, "44'/118'/0'/0/0") + assert.NoError(t, err) + pub := crypto.PrivKeySecp256k1(priv).PubKey() + + t.Log("\tNODEJS GOLANG\n") + t.Logf("SEED \t%X %X\n", seedB, seed) + t.Logf("MSTR \t%X %X\n", masterB, master) + t.Logf("PRIV \t%X %X\n", privB, priv) + t.Logf("PUB \t%X %X\n", pubB, pub) + + assert.Equal(t, seedB, seed) + assert.Equal(t, master[:], masterB, fmt.Sprintf("Expected masters to match for %d", i)) + assert.Equal(t, priv[:], privB, "Expected priv keys to match") + var pubBFixed [33]byte + copy(pubBFixed[:], pubB) + assert.Equal(t, pub, crypto.PubKeySecp256k1(pubBFixed), fmt.Sprintf("Expected pub keys to match for %d", i)) + + addr := pub.Address() + t.Logf("ADDR \t%X %X\n", addrB, addr) + assert.Equal(t, addr, crypto.Address(addrB), fmt.Sprintf("Expected addresses to match %d", i)) + + } +} + + diff --git a/keys/hd/hd_test.go b/keys/hd/hd_test.go deleted file mode 100644 index c9e540ad5..000000000 --- a/keys/hd/hd_test.go +++ /dev/null @@ -1,238 +0,0 @@ -package hd - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "fmt" - "io/ioutil" - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/tyler-smith/go-bip39" - - "github.com/tendermint/go-crypto" -) - -type addrData struct { - Mnemonic string - Master string - Seed string - Priv string - Pub string - Addr string -} - -// NOTE: atom fundraiser address -// var hdPath string = "m/44'/118'/0'/0/0" -var hdToAddrTable []addrData - -func init() { - - b, err := ioutil.ReadFile("test.json") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - err = json.Unmarshal(b, &hdToAddrTable) - if err != nil { - fmt.Println(err) - os.Exit(1) - } -} - -func TestHDToAddr(t *testing.T) { - - for i, d := range hdToAddrTable { - privB, _ := hex.DecodeString(d.Priv) - pubB, _ := hex.DecodeString(d.Pub) - addrB, _ := hex.DecodeString(d.Addr) - seedB, _ := hex.DecodeString(d.Seed) - masterB, _ := hex.DecodeString(d.Master) - - seed := bip39.NewSeed(d.Mnemonic, "") - - fmt.Println("================================") - fmt.Println("ROUND:", i, "MNEMONIC:", d.Mnemonic) - - // master, priv, pub := tylerSmith(seed) - // master, priv, pub := btcsuite(seed) - master, priv, pub := gocrypto(seed) - - fmt.Printf("\tNODEJS GOLANG\n") - fmt.Printf("SEED \t%X %X\n", seedB, seed) - fmt.Printf("MSTR \t%X %X\n", masterB, master) - fmt.Printf("PRIV \t%X %X\n", privB, priv) - fmt.Printf("PUB \t%X %X\n", pubB, pub) - _, _ = priv, privB - - assert.Equal(t, master, masterB, fmt.Sprintf("Expected masters to match for %d", i)) - assert.Equal(t, priv, privB, "Expected priv keys to match") - assert.Equal(t, pub, pubB, fmt.Sprintf("Expected pub keys to match for %d", i)) - - var pubT crypto.PubKeySecp256k1 - copy(pubT[:], pub) - addr := pubT.Address() - fmt.Printf("ADDR \t%X %X\n", addrB, addr) - assert.Equal(t, addr, crypto.Address(addrB), fmt.Sprintf("Expected addresses to match %d", i)) - - } -} - -func TestReverseBytes(t *testing.T) { - tests := [...]struct { - v []byte - want []byte - }{ - {[]byte(""), []byte("")}, - {nil, nil}, - {[]byte("Tendermint"), []byte("tnimredneT")}, - {[]byte("T"), []byte("T")}, - {[]byte("Te"), []byte("eT")}, - } - - for i, tt := range tests { - got := ReverseBytes(tt.v) - if !bytes.Equal(got, tt.want) { - t.Errorf("#%d:\ngot= (%x)\nwant=(%x)", i, got, tt.want) - } - } -} - -/* -func ifExit(err error, n int) { - if err != nil { - fmt.Println(n, err) - os.Exit(1) - } -} -*/ - -func gocrypto(seed []byte) ([]byte, []byte, []byte) { - - _, priv, ch := ComputeMastersFromSeed(string(seed)) - - privBytes := DerivePrivateKeyForPath( - HexDecode(priv), - HexDecode(ch), - "44'/118'/0'/0/0", - ) - - pubBytes := PubKeyBytesFromPrivKeyBytes(privBytes, true) - - return HexDecode(priv), privBytes, pubBytes -} - -/* -func btcsuite(seed []byte) ([]byte, []byte, []byte) { - fmt.Println("HD") - masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) - if err != nil { - hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) - hmac.Write([]byte(seed)) - intermediary := hmac.Sum(nil) - - curve := btcutil.Secp256k1() - curveParams := curve.Params() - - // Split it into our key and chain code - keyBytes := intermediary[:32] - fmt.Printf("\t%X\n", keyBytes) - fmt.Printf("\t%X\n", curveParams.N.Bytes()) - keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes)) - fmt.Printf("\t%d\n", keyInt) - } - fh := hdkeychain.HardenedKeyStart - k, err := masterKey.Child(uint32(fh + 44)) - ifExit(err, 44) - k, err = k.Child(uint32(fh + 118)) - ifExit(err, 118) - k, err = k.Child(uint32(fh + 0)) - ifExit(err, 1) - k, err = k.Child(uint32(0)) - ifExit(err, 2) - k, err = k.Child(uint32(0)) - ifExit(err, 3) - ecpriv, err := k.ECPrivKey() - ifExit(err, 10) - ecpub, err := k.ECPubKey() - ifExit(err, 11) - - priv := ecpriv.Serialize() - pub := ecpub.SerializeCompressed() - mkey, _ := masterKey.ECPrivKey() - return mkey.Serialize(), priv, pub -} - -// return priv and pub -func tylerSmith(seed []byte) ([]byte, []byte, []byte) { - masterKey, err := bip32.NewMasterKey(seed) - if err != nil { - hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) - hmac.Write([]byte(seed)) - intermediary := hmac.Sum(nil) - - curve := btcutil.Secp256k1() - curveParams := curve.Params() - - // Split it into our key and chain code - keyBytes := intermediary[:32] - fmt.Printf("\t%X\n", keyBytes) - fmt.Printf("\t%X\n", curveParams.N.Bytes()) - keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes)) - fmt.Printf("\t%d\n", keyInt) - - } - ifExit(err, 0) - fh := bip32.FirstHardenedChild - k, err := masterKey.NewChildKey(fh + 44) - ifExit(err, 44) - k, err = k.NewChildKey(fh + 118) - ifExit(err, 118) - k, err = k.NewChildKey(fh + 0) - ifExit(err, 1) - k, err = k.NewChildKey(0) - ifExit(err, 2) - k, err = k.NewChildKey(0) - ifExit(err, 3) - - priv := k.Key - pub := k.PublicKey().Key - return masterKey.Key, priv, pub -} -*/ - -// Benchmarks -var revBytesCases = [][]byte{ - nil, - []byte(""), - - []byte("12"), - - // 16byte case - []byte("abcdefghijklmnop"), - - // 32byte case - []byte("abcdefghijklmnopqrstuvwxyz123456"), - - // 64byte case - []byte("abcdefghijklmnopqrstuvwxyz123456abcdefghijklmnopqrstuvwxyz123456"), -} - -func BenchmarkReverseBytes(b *testing.B) { - var sink []byte - for i := 0; i < b.N; i++ { - for _, tt := range revBytesCases { - sink = ReverseBytes(tt) - } - } - b.ReportAllocs() - - // sink is necessary to ensure if the compiler tries - // to smart, that it won't optimize away the benchmarks. - if sink != nil { - _ = sink - } -} diff --git a/keys/hd/hdpath.go b/keys/hd/hdpath.go new file mode 100644 index 000000000..00d0572cc --- /dev/null +++ b/keys/hd/hdpath.go @@ -0,0 +1,168 @@ +// Package hd provides basic functionality Hierarchical Deterministic Wallets. +// +// The user must understand the overall concept of the BIP 32 and the BIP 44 specs: +// https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki +// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki +// +// In combination with the bip39 package in go-crypto this package provides the functionality for deriving keys using a +// BIP 44 HD path, or, more general, by passing a BIP 32 path. +// +// In particular, this package (together with bip39) provides all necessary functionality to derive keys from +// mnemonics generated during the cosmos fundraiser. +package hd + +import ( + "crypto/hmac" + "crypto/sha512" + "encoding/binary" + "errors" + "fmt" + "math/big" + "strconv" + "strings" + + "github.com/btcsuite/btcd/btcec" + "github.com/tendermint/go-crypto" +) + +// BIP44Prefix is the parts of the BIP32 HD path that are fixed by what we used during the fundraiser. +const ( + BIP44Prefix = "44'/118'/" + FullFundraiserPath = BIP44Prefix + "0'/0/0" +) + +// BIP44Params wraps BIP 44 params (5 level BIP 32 path). +// To receive a canonical string representation ala +// m / purpose' / coin_type' / account' / change / address_index +// call String() on a BIP44Params instance. +type BIP44Params struct { + purpose uint32 + coinType uint32 + account uint32 + change bool + addressIdx uint32 +} + +// NewParams creates a BIP 44 parameter object from the params: +// m / purpose' / coin_type' / account' / change / address_index +func NewParams(purpose, coinType, account uint32, change bool, addressIdx uint32) *BIP44Params { + return &BIP44Params{ + purpose: purpose, + coinType: coinType, + account: account, + change: change, + addressIdx: addressIdx, + } +} + +// NewFundraiserParams creates a BIP 44 parameter object from the params: +// m / 44' / 118' / account' / 0 / address_index +// The fixed parameters (purpose', coin_type', and change) are determined by what was used in the fundraiser. +func NewFundraiserParams(account uint32, addressIdx uint32) *BIP44Params { + return NewParams(44, 118, account, false, addressIdx) +} + +func (p BIP44Params) String() string { + var changeStr string + if p.change { + changeStr = "1" + } else { + changeStr = "0" + } + // m / purpose' / coin_type' / account' / change / address_index + return fmt.Sprintf("%d'/%d'/%d'/%s/%d", + p.purpose, + p.coinType, + p.account, + changeStr, + p.addressIdx) +} + +// ComputeMastersFromSeed returns the master public key, master secret, and chain code in hex. +func ComputeMastersFromSeed(seed []byte) (secret [32]byte, chainCode [32]byte) { + masterSecret := []byte("Bitcoin seed") + secret, chainCode = i64(masterSecret, seed) + + return +} + +// DerivePrivateKeyForPath derives the private key by following the BIP 32/44 path from privKeyBytes, +// using the given chainCode. +func DerivePrivateKeyForPath(privKeyBytes [32]byte, chainCode [32]byte, path string) ([32]byte, error) { + data := privKeyBytes + parts := strings.Split(path, "/") + for _, part := range parts { + // do we have an apostrophe? + harden := part[len(part)-1:] == "'" + // harden == private derivation, else public derivation: + if harden { + part = part[:len(part)-1] + } + idx, err := strconv.Atoi(part) + if err != nil { + return [32]byte{}, fmt.Errorf("invalid BIP 32 path: %s", err) + } + if idx < 0 { + return [32]byte{}, errors.New("invalid BIP 32 path: index negative ot too large") + } + data, chainCode = derivePrivateKey(data, chainCode, uint32(idx), harden) + } + var derivedKey [32]byte + n := copy(derivedKey[:], data[:]) + if n != 32 || len(data) != 32 { + return [32]byte{}, fmt.Errorf("expected a (secp256k1) key of length 32, got length: %v", len(data)) + } + + return derivedKey, nil +} + +// derivePrivateKey derives the private key with index and chainCode. +// If harden is true, the derivation is 'hardened'. +// It returns the new private key and new chain code. +// For more information on hardened keys see: +// - https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki +func derivePrivateKey(privKeyBytes [32]byte, chainCode [32]byte, index uint32, harden bool) ([32]byte, [32]byte) { + var data []byte + if harden { + index = index | 0x80000000 + data = append([]byte{byte(0)}, privKeyBytes[:]...) + } else { + // this can't return an error: + pubkey := crypto.PrivKeySecp256k1(privKeyBytes).PubKey() + + public := pubkey.(crypto.PubKeySecp256k1) + data = public[:] + } + data = append(data, uint32ToBytes(index)...) + data2, chainCode2 := i64(chainCode[:], data) + x := addScalars(privKeyBytes[:], data2[:]) + return x, chainCode2 +} + +// modular big endian addition +func addScalars(a []byte, b []byte) [32]byte { + aInt := new(big.Int).SetBytes(a) + bInt := new(big.Int).SetBytes(b) + sInt := new(big.Int).Add(aInt, bInt) + x := sInt.Mod(sInt, btcec.S256().N).Bytes() + x2 := [32]byte{} + copy(x2[32-len(x):], x) + return x2 +} + +func uint32ToBytes(i uint32) []byte { + b := [4]byte{} + binary.BigEndian.PutUint32(b[:], i) + return b[:] +} + +// i64 returns the two halfs of the SHA512 HMAC of key and data. +func i64(key []byte, data []byte) (IL [32]byte, IR [32]byte) { + mac := hmac.New(sha512.New, key) + // sha512 does not err + _, _ = mac.Write(data) + I := mac.Sum(nil) + copy(IL[:], I[:32]) + copy(IR[:], I[32:]) + return +} diff --git a/keys/hd/hdpath_test.go b/keys/hd/hdpath_test.go new file mode 100644 index 000000000..b014ae804 --- /dev/null +++ b/keys/hd/hdpath_test.go @@ -0,0 +1,73 @@ +package hd + +import ( + "encoding/hex" + "fmt" + "github.com/tendermint/go-crypto/keys/bip39" +) + +func ExampleStringifyPathParams() { + path := NewParams(44, 0, 0, false, 0) + fmt.Println(path.String()) + // Output: 44'/0'/0'/0/0 +} + +func ExampleSomeBIP32TestVecs() { + + seed := bip39.MnemonicToSeed("barrel original fuel morning among eternal " + + "filter ball stove pluck matrix mechanic") + master, ch := ComputeMastersFromSeed(seed) + fmt.Println("keys from fundraiser test-vector (cosmos, bitcoin, ether)") + fmt.Println() + // cosmos + priv, _ := DerivePrivateKeyForPath(master, ch, FullFundraiserPath) + fmt.Println(hex.EncodeToString(priv[:])) + // bitcoin + priv, _ = DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/0") + fmt.Println(hex.EncodeToString(priv[:])) + // ether + priv, _ = DerivePrivateKeyForPath(master, ch, "44'/60'/0'/0/0") + fmt.Println(hex.EncodeToString(priv[:])) + + fmt.Println() + fmt.Println("keys generated via https://coinomi.com/recovery-phrase-tool.html") + fmt.Println() + + seed = bip39.MnemonicToSeed( + "advice process birth april short trust crater change bacon monkey medal garment " + + "gorilla ranch hour rival razor call lunar mention taste vacant woman sister") + master, ch = ComputeMastersFromSeed(seed) + priv, _ = DerivePrivateKeyForPath(master, ch, "44'/1'/1'/0/4") + fmt.Println(hex.EncodeToString(priv[:])) + + seed = bip39.MnemonicToSeed("idea naive region square margin day captain habit " + + "gun second farm pact pulse someone armed") + master, ch = ComputeMastersFromSeed(seed) + priv, _ = DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/420") + fmt.Println(hex.EncodeToString(priv[:])) + + fmt.Println() + fmt.Println("BIP 32 example") + fmt.Println() + + // bip32 path: m/0/7 + seed = bip39.MnemonicToSeed("monitor flock loyal sick object grunt duty ride develop assault harsh history") + master, ch = ComputeMastersFromSeed(seed) + priv, _ = DerivePrivateKeyForPath(master, ch, "0/7") + fmt.Println(hex.EncodeToString(priv[:])) + + // Output: keys from fundraiser test-vector (cosmos, bitcoin, ether) + // + // bfcb217c058d8bbafd5e186eae936106ca3e943889b0b4a093ae13822fd3170c + // e77c3de76965ad89997451de97b95bb65ede23a6bf185a55d80363d92ee37c3d + // 7fc4d8a8146dea344ba04c593517d3f377fa6cded36cd55aee0a0bb968e651bc + // + // keys generated via https://coinomi.com/recovery-phrase-tool.html + // + // a61f10c5fecf40c084c94fa54273b6f5d7989386be4a37669e6d6f7b0169c163 + // 32c4599843de3ef161a629a461d12c60b009b676c35050be5f7ded3a3b23501f + // + // BIP 32 example + // + // c4c11d8c03625515905d7e89d25dfc66126fbc629ecca6db489a1a72fc4bda78 +} diff --git a/keys/keybase.go b/keys/keybase.go index 79e6f15fa..b55658d2f 100644 --- a/keys/keybase.go +++ b/keys/keybase.go @@ -7,62 +7,117 @@ import ( "strings" "github.com/pkg/errors" - crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/keys/words" + "github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto/keys/bip39" + "github.com/tendermint/go-crypto/keys/hd" dbm "github.com/tendermint/tmlibs/db" ) -// dbKeybase combines encyption and storage implementation to provide +var _ Keybase = dbKeybase{} + +// Language is a language to create the BIP 39 mnemonic in. +// Currently, only english is supported though. +// Find a list of all supported languages in the BIP 39 spec (word lists). +type Language int + +const ( + // English is the default language to create a mnemonic. + // It is the only supported language by this package. + English Language = iota + 1 + // Japanese is currently not supported. + Japanese + // Korean is currently not supported. + Korean + // Spanish is currently not supported. + Spanish + // ChineseSimplified is currently not supported. + ChineseSimplified + // ChineseTraditional is currently not supported. + ChineseTraditional + // French is currently not supported. + French + // Italian is currently not supported. + Italian +) + +var ( + // ErrUnsupportedSigningAlgo is raised when the caller tries to use a different signing scheme than secp256k1. + ErrUnsupportedSigningAlgo = errors.New("unsupported signing algo: only secp256k1 is supported") + // ErrUnsupportedLanguage is raised when the caller tries to use a different language than english for creating + // a mnemonic sentence. + ErrUnsupportedLanguage = errors.New("unsupported language: only english is supported") +) + +// dbKeybase combines encryption and storage implementation to provide // a full-featured key manager type dbKeybase struct { - db dbm.DB - codec words.Codec + db dbm.DB } -func New(db dbm.DB, codec words.Codec) dbKeybase { +// New creates a new keybase instance using the passed DB for reading and writing keys. +func New(db dbm.DB) Keybase { return dbKeybase{ - db: db, - codec: codec, + db: db, } } -var _ Keybase = dbKeybase{} - // CreateMnemonic generates a new key and persists it to storage, encrypted -// using the passphrase. It returns the generated seedphrase -// (mnemonic) and the key Info. It returns an error if it fails to +// using the provided password. +// It returns the generated mnemonic and the key Info. +// It returns an error if it fails to // generate a key for the given algo type, or if another key is // already stored under the same name. -func (kb dbKeybase) CreateMnemonic(name, passphrase string, algo SignAlgo) (Info, string, error) { - // NOTE: secret is SHA256 hashed by secp256k1 and ed25519. - // 16 byte secret corresponds to 12 BIP39 words. - // XXX: Ledgers use 24 words now - should we ? - secret := crypto.CRandBytes(16) - priv, err := generate(algo, secret) +func (kb dbKeybase) CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, mnemonic string, err error) { + if language != English { + return nil, "", ErrUnsupportedLanguage + } + if algo != Secp256k1 { + err = ErrUnsupportedSigningAlgo + return + } + + // default number of words (24): + mnemonicS, err := bip39.NewMnemonic(bip39.FreshKey) if err != nil { - return nil, "", err + return } + mnemonic = strings.Join(mnemonicS, " ") + seed := bip39.MnemonicToSeed(mnemonic) + info, err = kb.persistDerivedKey(seed, passwd, name, hd.FullFundraiserPath) + return +} - // encrypt and persist the key - info := kb.writeLocalKey(priv, name, passphrase) +// CreateFundraiserKey converts a mnemonic to a private key and persists it, +// encrypted with the given password. +// TODO(ismail) +func (kb dbKeybase) CreateFundraiserKey(name, mnemonic, passwd string) (info Info, err error) { + words := strings.Split(mnemonic, " ") + if len(words) != 12 { + err = fmt.Errorf("recovering only works with 12 word (fundraiser) mnemonics, got: %v words", len(words)) + return + } + seed, err := bip39.MnemonicToSeedWithErrChecking(mnemonic) + if err != nil { + return + } + info, err = kb.persistDerivedKey(seed, passwd, name, hd.FullFundraiserPath) + return +} - // we append the type byte to the serialized secret to help with - // recovery - // ie [secret] = [type] + [secret] - typ := cryptoAlgoToByte(algo) - secret = append([]byte{typ}, secret...) +func (kb dbKeybase) Derive(name, mnemonic, passwd string, params hd.BIP44Params) (info Info, err error) { + seed, err := bip39.MnemonicToSeedWithErrChecking(mnemonic) + if err != nil { + return + } + info, err = kb.persistDerivedKey(seed, passwd, name, params.String()) - // return the mnemonic phrase - words, err := kb.codec.BytesToWords(secret) - seed := strings.Join(words, " ") - return info, seed, err + return } - // CreateLedger creates a new locally-stored reference to a Ledger keypair // It returns the created key info and an error if the Ledger could not be queried -func (kb dbKeybase) CreateLedger(name string, path crypto.DerivationPath, algo SignAlgo) (Info, error) { - if algo != AlgoSecp256k1 { - return nil, fmt.Errorf("Only secp256k1 is supported for Ledger devices") +func (kb dbKeybase) CreateLedger(name string, path crypto.DerivationPath, algo SigningAlgo) (Info, error) { + if algo != Secp256k1 { + return nil, ErrUnsupportedSigningAlgo } priv, err := crypto.NewPrivKeyLedgerSecp256k1(path) if err != nil { @@ -78,29 +133,24 @@ func (kb dbKeybase) CreateOffline(name string, pub crypto.PubKey) (Info, error) return kb.writeOfflineKey(pub, name), nil } -// Recover converts a seedphrase to a private key and persists it, -// encrypted with the given passphrase. Functions like Create, but -// seedphrase is input not output. -func (kb dbKeybase) Recover(name, passphrase, seedphrase string) (Info, error) { - words := strings.Split(strings.TrimSpace(seedphrase), " ") - secret, err := kb.codec.WordsToBytes(words) - if err != nil { - return nil, err - } - // secret is comprised of the actual secret with the type - // appended. - // ie [secret] = [type] + [secret] - typ, secret := secret[0], secret[1:] - algo := byteToSignAlgo(typ) - priv, err := generate(algo, secret) +func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath string) (info Info, err error) { + // create master key and derive first key: + masterPriv, ch := hd.ComputeMastersFromSeed(seed) + derivedPriv, err := hd.DerivePrivateKeyForPath(masterPriv, ch, fullHdPath) if err != nil { - return nil, err + return } - // encrypt and persist key. - public := kb.writeLocalKey(priv, name, passphrase) - return public, nil + // if we have a password, use it to encrypt the private key and store it + // else store the public key only + if passwd != "" { + info = kb.writeLocalKey(crypto.PrivKeySecp256k1(derivedPriv), name, passwd) + } else { + pubk := crypto.PrivKeySecp256k1(derivedPriv).PubKey() + info = kb.writeOfflineKey(pubk, name) + } + return } // List returns the keys from storage in alphabetical order. @@ -173,7 +223,7 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signat func (kb dbKeybase) Export(name string) (armor string, err error) { bz := kb.db.Get(infoKey(name)) if bz == nil { - return "", errors.New("No key to export with name " + name) + return "", fmt.Errorf("no key to export with name %s", name) } return armorInfoBytes(bz), nil } @@ -184,7 +234,7 @@ func (kb dbKeybase) Export(name string) (armor string, err error) { func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) { bz := kb.db.Get(infoKey(name)) if bz == nil { - return "", errors.New("No key to export with name " + name) + return "", fmt.Errorf("no key to export with name %s", name) } info, err := readInfo(bz) if err != nil { @@ -276,7 +326,7 @@ func (kb dbKeybase) Update(name, oldpass, newpass string) error { kb.writeLocalKey(key, name, newpass) return nil default: - return fmt.Errorf("Locally stored key required") + return fmt.Errorf("locally stored key required") } } @@ -307,18 +357,6 @@ func (kb dbKeybase) writeInfo(info Info, name string) { kb.db.SetSync(infoKey(name), writeInfo(info)) } -func generate(algo SignAlgo, secret []byte) (crypto.PrivKey, error) { - switch algo { - case AlgoEd25519: - return crypto.GenPrivKeyEd25519FromSecret(secret), nil - case AlgoSecp256k1: - return crypto.GenPrivKeySecp256k1FromSecret(secret), nil - default: - err := errors.Errorf("Cannot generate keys for algorithm: %s", algo) - return nil, err - } -} - func infoKey(name string) []byte { return []byte(fmt.Sprintf("%s.info", name)) } diff --git a/keys/keybase_test.go b/keys/keybase_test.go index 5caf82af8..a3957f8e9 100644 --- a/keys/keybase_test.go +++ b/keys/keybase_test.go @@ -6,24 +6,21 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - dbm "github.com/tendermint/tmlibs/db" - "github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/words" + "github.com/tendermint/go-crypto/keys/hd" + + dbm "github.com/tendermint/tmlibs/db" ) // TestKeyManagement makes sure we can manipulate these keys well func TestKeyManagement(t *testing.T) { - // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - words.MustLoadCodec("english"), ) - algo := keys.AlgoEd25519 + algo := keys.Secp256k1 n1, n2, n3 := "personal", "business", "other" p1, p2 := "1234", "really-secure!@#$" @@ -32,14 +29,18 @@ func TestKeyManagement(t *testing.T) { require.Nil(t, err) assert.Empty(t, l) + _, _, err = cstore.CreateMnemonic(n1, keys.English, p1, keys.Ed25519) + assert.Error(t, err, "ed25519 keys are currently not supported by keybase") + // create some keys _, err = cstore.Get(n1) - assert.NotNil(t, err) - i, _, err := cstore.CreateMnemonic(n1, p1, algo) + assert.Error(t, err) + i, _, err := cstore.CreateMnemonic(n1, keys.English, p1, algo) + + require.NoError(t, err) require.Equal(t, n1, i.GetName()) - require.Nil(t, err) - _, _, err = cstore.CreateMnemonic(n2, p2, algo) - require.Nil(t, err) + _, _, err = cstore.CreateMnemonic(n2, keys.English, p2, algo) + require.NoError(t, err) // we can get these keys i2, err := cstore.Get(n2) @@ -49,7 +50,7 @@ func TestKeyManagement(t *testing.T) { // list shows them in order keyS, err := cstore.List() - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, 2, len(keyS)) // note these are in alphabetical order assert.Equal(t, n2, keyS[0].GetName()) @@ -60,12 +61,12 @@ func TestKeyManagement(t *testing.T) { err = cstore.Delete("bad name", "foo") require.NotNil(t, err) err = cstore.Delete(n1, p1) - require.Nil(t, err) + require.NoError(t, err) keyS, err = cstore.List() - require.Nil(t, err) + require.NoError(t, err) assert.Equal(t, 1, len(keyS)) _, err = cstore.Get(n1) - assert.NotNil(t, err) + assert.Error(t, err) // create an offline key o1 := "offline" @@ -76,56 +77,45 @@ func TestKeyManagement(t *testing.T) { require.Equal(t, pub1, i.GetPubKey()) require.Equal(t, o1, i.GetName()) keyS, err = cstore.List() + require.NoError(t, err) require.Equal(t, 2, len(keyS)) // delete the offline key err = cstore.Delete(o1, "no") require.NotNil(t, err) err = cstore.Delete(o1, "yes") - require.Nil(t, err) + require.NoError(t, err) keyS, err = cstore.List() + require.NoError(t, err) require.Equal(t, 1, len(keyS)) - - // make sure that it only signs with the right password - // tx := mock.NewSig([]byte("mytransactiondata")) - // err = cstore.Sign(n2, p1, tx) - // assert.NotNil(t, err) - // err = cstore.Sign(n2, p2, tx) - // assert.Nil(t, err, "%+v", err) - // sigs, err := tx.Signers() - // assert.Nil(t, err, "%+v", err) - // if assert.Equal(t, 1, len(sigs)) { - // assert.Equal(t, i2.PubKey, sigs[0]) - // } } // TestSignVerify does some detailed checks on how we sign and validate // signatures func TestSignVerify(t *testing.T) { - - // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - words.MustLoadCodec("english"), ) - algo := keys.AlgoSecp256k1 + algo := keys.Secp256k1 n1, n2, n3 := "some dude", "a dudette", "dude-ish" p1, p2, p3 := "1234", "foobar", "foobar" // create two users and get their info - i1, _, err := cstore.CreateMnemonic(n1, p1, algo) + i1, _, err := cstore.CreateMnemonic(n1, keys.English, p1, algo) require.Nil(t, err) - i2, _, err := cstore.CreateMnemonic(n2, p2, algo) + i2, _, err := cstore.CreateMnemonic(n2, keys.English, p2, algo) require.Nil(t, err) // Import a public key armor, err := cstore.ExportPubKey(n2) require.Nil(t, err) cstore.ImportPubKey(n3, armor) - _, err = cstore.Get(n3) - require.Nil(t, err) + i3, err := cstore.Get(n3) + require.NoError(t, err) + require.Equal(t, i3.GetName(), n3) + // let's try to sign some messages d1 := []byte("my first message") @@ -178,61 +168,6 @@ func TestSignVerify(t *testing.T) { assert.NotNil(t, err) } -/* -// TestSignWithLedger makes sure we have ledger compatibility with -// the crypto store. -// -// This test will only succeed with a ledger attached to the computer -// and the cosmos app open -func TestSignWithLedger(t *testing.T) { - if os.Getenv("WITH_LEDGER") == "" { - t.Skip("Set WITH_LEDGER to run code on real ledger") - } - - // make the storage with reasonable defaults - cstore := keys.New( - dbm.NewMemDB(), - words.MustLoadCodec("english"), - ) - n := "nano-s" - p := "hard2hack" - - // create a nano user - c, _, err := cstore.Create(n, p, nano.KeyLedgerEd25519) - require.Nil(t, err, "%+v", err) - assert.Equal(t, c.Key, n) - _, ok := c.PubKey.Unwrap().(nano.PubKeyLedgerEd25519) - require.True(t, ok) - - // make sure we can get it back - info, err := cstore.Get(n) - require.Nil(t, err, "%+v", err) - assert.Equal(t, info.Key, n) - key := info.PubKey - require.False(t ,key.Empty()) - require.True(t, key.Equals(c.PubKey)) - - // let's try to sign some messages - d1 := []byte("welcome to cosmos") - d2 := []byte("please turn on the app") - - // try signing both data with the ledger... - s1, pub, err := cstore.Sign(n, p, d1) - require.Nil(t, err) - require.Equal(t, info.PubKey, pub) - - s2, pub, err := cstore.Sign(n, p, d2) - require.Nil(t, err) - require.Equal(t, info.PubKey, pub) - - // now, let's check those signatures work - assert.True(t, key.VerifyBytes(d1, s1)) - assert.True(t, key.VerifyBytes(d2, s2)) - // and mismatched signatures don't - assert.False(t, key.VerifyBytes(d1, s2)) -} -*/ - func assertPassword(t *testing.T, cstore keys.Keybase, name, pass, badpass string) { err := cstore.Update(name, badpass, pass) assert.NotNil(t, err) @@ -247,18 +182,16 @@ func TestExportImport(t *testing.T) { db := dbm.NewMemDB() cstore := keys.New( db, - words.MustLoadCodec("english"), ) - info, _, err := cstore.CreateMnemonic("john", "passphrase", keys.AlgoEd25519) + info, _, err := cstore.CreateMnemonic("john", keys.English,"secretcpw", keys.Secp256k1) assert.NoError(t, err) assert.Equal(t, info.GetName(), "john") - addr := info.GetPubKey().Address() john, err := cstore.Get("john") assert.NoError(t, err) - assert.Equal(t, john.GetName(), "john") - assert.Equal(t, john.GetPubKey().Address(), addr) + assert.Equal(t, info.GetName(), "john") + johnAddr := info.GetPubKey().Address() armor, err := cstore.Export("john") assert.NoError(t, err) @@ -269,22 +202,23 @@ func TestExportImport(t *testing.T) { john2, err := cstore.Get("john2") assert.NoError(t, err) - assert.Equal(t, john.GetPubKey().Address(), addr) + assert.Equal(t, john.GetPubKey().Address(), johnAddr) assert.Equal(t, john.GetName(), "john") assert.Equal(t, john, john2) } - +// func TestExportImportPubKey(t *testing.T) { // make the storage with reasonable defaults db := dbm.NewMemDB() cstore := keys.New( db, - words.MustLoadCodec("english"), ) - // Create a private-public key pair and ensure consistency - info, _, err := cstore.CreateMnemonic("john", "passphrase", keys.AlgoEd25519) - assert.NoError(t, err) + // CreateMnemonic a private-public key pair and ensure consistency + notPasswd := "n9y25ah7" + info, _, err := cstore.CreateMnemonic("john", keys.English, notPasswd, keys.Secp256k1) + assert.Nil(t, err) + assert.NotEqual(t, info, "") assert.Equal(t, info.GetName(), "john") addr := info.GetPubKey().Address() john, err := cstore.Get("john") @@ -320,15 +254,14 @@ func TestAdvancedKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - words.MustLoadCodec("english"), ) - algo := keys.AlgoSecp256k1 + algo := keys.Secp256k1 n1, n2 := "old-name", "new name" p1, p2 := "1234", "foobar" // make sure key works with initial password - _, _, err := cstore.CreateMnemonic(n1, p1, algo) + _, _, err := cstore.CreateMnemonic(n1, keys.English, p1, algo) require.Nil(t, err, "%+v", err) assertPassword(t, cstore, n1, p1, p2) @@ -370,18 +303,17 @@ func TestSeedPhrase(t *testing.T) { // make the storage with reasonable defaults cstore := keys.New( dbm.NewMemDB(), - words.MustLoadCodec("english"), ) - algo := keys.AlgoEd25519 + algo := keys.Secp256k1 n1, n2 := "lost-key", "found-again" p1, p2 := "1234", "foobar" // make sure key works with initial password - info, seed, err := cstore.CreateMnemonic(n1, p1, algo) + info, mnemonic, err := cstore.CreateMnemonic(n1, keys.English, p1, algo) require.Nil(t, err, "%+v", err) assert.Equal(t, n1, info.GetName()) - assert.NotEmpty(t, seed) + assert.NotEmpty(t, mnemonic) // now, let us delete this key err = cstore.Delete(n1, p1) @@ -389,9 +321,10 @@ func TestSeedPhrase(t *testing.T) { _, err = cstore.Get(n1) require.NotNil(t, err) - // let us re-create it from the seed-phrase - newInfo, err := cstore.Recover(n2, p2, seed) - require.Nil(t, err, "%+v", err) + // let us re-create it from the mnemonic-phrase + params := *hd.NewFundraiserParams(0 ,0 ) + newInfo, err := cstore.Derive(n2,mnemonic, p2, params) + require.NoError(t, err) assert.Equal(t, n2, newInfo.GetName()) assert.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) assert.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) @@ -401,13 +334,12 @@ func ExampleNew() { // Select the encryption and storage for your cryptostore cstore := keys.New( dbm.NewMemDB(), - words.MustLoadCodec("english"), ) - ed := keys.AlgoEd25519 - sec := keys.AlgoSecp256k1 + + sec := keys.Secp256k1 // Add keys and see they return in alphabetical order - bob, _, err := cstore.CreateMnemonic("Bob", "friend", ed) + bob, _, err := cstore.CreateMnemonic("Bob", keys.English, "friend", sec) if err != nil { // this should never happen fmt.Println(err) @@ -415,8 +347,8 @@ func ExampleNew() { // return info here just like in List fmt.Println(bob.GetName()) } - cstore.CreateMnemonic("Alice", "secret", sec) - cstore.CreateMnemonic("Carl", "mitm", ed) + cstore.CreateMnemonic("Alice", keys.English, "secret", sec) + cstore.CreateMnemonic("Carl", keys.English, "mitm", sec) info, _ := cstore.List() for _, i := range info { fmt.Println(i.GetName()) @@ -429,7 +361,7 @@ func ExampleNew() { fmt.Println("don't accept real passphrase") } - // and we can validate the signature with publically available info + // and we can validate the signature with publicly available info binfo, _ := cstore.Get("Bob") if !binfo.GetPubKey().Equals(bob.GetPubKey()) { fmt.Println("Get and Create return different keys") diff --git a/keys/keys.go b/keys/keys.go index c8e25da3c..b3fad70f3 100644 --- a/keys/keys.go +++ b/keys/keys.go @@ -1,32 +1,12 @@ package keys -import "fmt" - -type SignAlgo string +// SigningAlgo defines an algorithm to derive key-pairs which can be used for cryptographic signing. +type SigningAlgo string const ( - AlgoEd25519 = SignAlgo("ed25519") - AlgoSecp256k1 = SignAlgo("secp256k1") -) - -func cryptoAlgoToByte(key SignAlgo) byte { - switch key { - case AlgoEd25519: - return 0x01 - case AlgoSecp256k1: - return 0x02 - default: - panic(fmt.Sprintf("Unexpected type key %v", key)) - } -} - -func byteToSignAlgo(b byte) SignAlgo { - switch b { - case 0x01: - return AlgoEd25519 - case 0x02: - return AlgoSecp256k1 - default: - panic(fmt.Sprintf("Unexpected type byte %X", b)) - } -} + // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. + Secp256k1 = SigningAlgo("secp256k1") + // Ed25519 represents the Ed25519 signature system. + // It is currently not supported for end-user keys (wallets/ledgers). + Ed25519 = SigningAlgo("ed25519") +) \ No newline at end of file diff --git a/keys/types.go b/keys/types.go index 53821e8bf..09fbb399e 100644 --- a/keys/types.go +++ b/keys/types.go @@ -2,6 +2,7 @@ package keys import ( crypto "github.com/tendermint/go-crypto" + "github.com/tendermint/go-crypto/keys/hd" ) // Keybase exposes operations on a generic keystore @@ -15,13 +16,15 @@ type Keybase interface { // Sign some bytes, looking up the private key to use Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) - // Create a new locally-stored keypair, returning the mnemonic - CreateMnemonic(name, passphrase string, algo SignAlgo) (info Info, seed string, err error) - // Recover takes a seedphrase and loads in the key - Recover(name, passphrase, seedphrase string) (info Info, erro error) - + // CreateMnemonic creates a new mnemonic, and derives a hierarchical deterministic + // key from that. + CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, seed string, err error) + // CreateFundraiserKey takes a mnemonic and derives, a password + CreateFundraiserKey(name, mnemonic, passwd string) (info Info, err error) + // Derive derives a key from the passed mnemonic using a BIP44 path. + Derive(name, mnemonic, passwd string, params hd.BIP44Params) (Info, error) // Create, store, and return a new Ledger key reference - CreateLedger(name string, path crypto.DerivationPath, algo SignAlgo) (info Info, err error) + CreateLedger(name string, path crypto.DerivationPath, algo SigningAlgo) (info Info, err error) // Create, store, and return a new offline key reference CreateOffline(name string, pubkey crypto.PubKey) (info Info, err error) @@ -34,7 +37,7 @@ type Keybase interface { ExportPubKey(name string) (armor string, err error) } -// Publically exposed information about a keypair +// Info is the publicly exposed information about a keypair type Info interface { // Human-readable type for key listing GetType() string diff --git a/keys/words/ecc.go b/keys/words/ecc.go deleted file mode 100644 index c511ad6e4..000000000 --- a/keys/words/ecc.go +++ /dev/null @@ -1,208 +0,0 @@ -package words - -import ( - "encoding/binary" - "errors" - "hash/crc32" - "hash/crc64" - - "github.com/howeyc/crc16" -) - -// ECC is used for anything that calculates an error-correcting code -type ECC interface { - // AddECC calculates an error-correcting code for the input - // returns an output with the code appended - AddECC([]byte) []byte - - // CheckECC verifies if the ECC is proper on the input and returns - // the data with the code removed, or an error - CheckECC([]byte) ([]byte, error) -} - -var errInputTooShort = errors.New("input too short, no checksum present") -var errChecksumDoesntMatch = errors.New("checksum does not match") - -// NoECC is a no-op placeholder, kind of useless... except for tests -type NoECC struct{} - -var _ ECC = NoECC{} - -func (_ NoECC) AddECC(input []byte) []byte { return input } -func (_ NoECC) CheckECC(input []byte) ([]byte, error) { return input, nil } - -// CRC16 does the ieee crc16 polynomial check -type CRC16 struct { - Poly uint16 - table *crc16.Table -} - -var _ ECC = (*CRC16)(nil) - -const crc16ByteCount = 2 - -func NewIBMCRC16() *CRC16 { - return &CRC16{Poly: crc16.IBM} -} - -func NewSCSICRC16() *CRC16 { - return &CRC16{Poly: crc16.SCSI} -} - -func NewCCITTCRC16() *CRC16 { - return &CRC16{Poly: crc16.CCITT} -} - -func (c *CRC16) AddECC(input []byte) []byte { - table := c.getTable() - - // get crc and convert to some bytes... - crc := crc16.Checksum(input, table) - check := make([]byte, crc16ByteCount) - binary.BigEndian.PutUint16(check, crc) - - // append it to the input - output := append(input, check...) - return output -} - -func (c *CRC16) CheckECC(input []byte) ([]byte, error) { - table := c.getTable() - - if len(input) <= crc16ByteCount { - return nil, errInputTooShort - } - cut := len(input) - crc16ByteCount - data, check := input[:cut], input[cut:] - crc := binary.BigEndian.Uint16(check) - calc := crc16.Checksum(data, table) - if crc != calc { - return nil, errChecksumDoesntMatch - } - return data, nil -} - -func (c *CRC16) getTable() *crc16.Table { - if c.table != nil { - return c.table - } - if c.Poly == 0 { - c.Poly = crc16.IBM - } - c.table = crc16.MakeTable(c.Poly) - return c.table -} - -// CRC32 does the ieee crc32 polynomial check -type CRC32 struct { - Poly uint32 - table *crc32.Table -} - -var _ ECC = (*CRC32)(nil) - -func NewIEEECRC32() *CRC32 { - return &CRC32{Poly: crc32.IEEE} -} - -func NewCastagnoliCRC32() *CRC32 { - return &CRC32{Poly: crc32.Castagnoli} -} - -func NewKoopmanCRC32() *CRC32 { - return &CRC32{Poly: crc32.Koopman} -} - -func (c *CRC32) AddECC(input []byte) []byte { - table := c.getTable() - - // get crc and convert to some bytes... - crc := crc32.Checksum(input, table) - check := make([]byte, crc32.Size) - binary.BigEndian.PutUint32(check, crc) - - // append it to the input - output := append(input, check...) - return output -} - -func (c *CRC32) CheckECC(input []byte) ([]byte, error) { - table := c.getTable() - - if len(input) <= crc32.Size { - return nil, errInputTooShort - } - cut := len(input) - crc32.Size - data, check := input[:cut], input[cut:] - crc := binary.BigEndian.Uint32(check) - calc := crc32.Checksum(data, table) - if crc != calc { - return nil, errChecksumDoesntMatch - } - return data, nil -} - -func (c *CRC32) getTable() *crc32.Table { - if c.table == nil { - if c.Poly == 0 { - c.Poly = crc32.IEEE - } - c.table = crc32.MakeTable(c.Poly) - } - return c.table -} - -// CRC64 does the ieee crc64 polynomial check -type CRC64 struct { - Poly uint64 - table *crc64.Table -} - -var _ ECC = (*CRC64)(nil) - -func NewISOCRC64() *CRC64 { - return &CRC64{Poly: crc64.ISO} -} - -func NewECMACRC64() *CRC64 { - return &CRC64{Poly: crc64.ECMA} -} - -func (c *CRC64) AddECC(input []byte) []byte { - table := c.getTable() - - // get crc and convert to some bytes... - crc := crc64.Checksum(input, table) - check := make([]byte, crc64.Size) - binary.BigEndian.PutUint64(check, crc) - - // append it to the input - output := append(input, check...) - return output -} - -func (c *CRC64) CheckECC(input []byte) ([]byte, error) { - table := c.getTable() - - if len(input) <= crc64.Size { - return nil, errInputTooShort - } - cut := len(input) - crc64.Size - data, check := input[:cut], input[cut:] - crc := binary.BigEndian.Uint64(check) - calc := crc64.Checksum(data, table) - if crc != calc { - return nil, errChecksumDoesntMatch - } - return data, nil -} - -func (c *CRC64) getTable() *crc64.Table { - if c.table == nil { - if c.Poly == 0 { - c.Poly = crc64.ISO - } - c.table = crc64.MakeTable(c.Poly) - } - return c.table -} diff --git a/keys/words/ecc_test.go b/keys/words/ecc_test.go deleted file mode 100644 index 9e1772b9f..000000000 --- a/keys/words/ecc_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package words - -import ( - "testing" - - asrt "github.com/stretchr/testify/assert" - - cmn "github.com/tendermint/tmlibs/common" -) - -var codecs = []ECC{ - NewIBMCRC16(), - NewSCSICRC16(), - NewCCITTCRC16(), - NewIEEECRC32(), - NewCastagnoliCRC32(), - NewKoopmanCRC32(), - NewISOCRC64(), - NewECMACRC64(), -} - -// TestECCPasses makes sure that the AddECC/CheckECC methods are symetric -func TestECCPasses(t *testing.T) { - assert := asrt.New(t) - - checks := append(codecs, NoECC{}) - - for _, check := range checks { - for i := 0; i < 2000; i++ { - numBytes := cmn.RandInt()%60 + 1 - data := cmn.RandBytes(numBytes) - - checked := check.AddECC(data) - res, err := check.CheckECC(checked) - if assert.Nil(err, "%#v: %+v", check, err) { - assert.Equal(data, res, "%v", check) - } - } - } -} - -// TestECCFails makes sure random data will (usually) fail the checksum -func TestECCFails(t *testing.T) { - assert := asrt.New(t) - - checks := codecs - attempts := 2000 - - for _, check := range checks { - failed := 0 - for i := 0; i < attempts; i++ { - numBytes := cmn.RandInt()%60 + 1 - data := cmn.RandBytes(numBytes) - _, err := check.CheckECC(data) - if err != nil { - failed += 1 - } - } - // we allow up to 1 falsely accepted checksums, as there are random matches - assert.InDelta(attempts, failed, 1, "%v", check) - } -} diff --git a/keys/words/wordcodec.go b/keys/words/wordcodec.go deleted file mode 100644 index 27032ce32..000000000 --- a/keys/words/wordcodec.go +++ /dev/null @@ -1,200 +0,0 @@ -package words - -import ( - "math/big" - "strings" - - "github.com/pkg/errors" - - "github.com/tendermint/go-crypto/keys/words/wordlist" -) - -const BankSize = 2048 - -// TODO: add error-checking codecs for invalid phrases - -type Codec interface { - BytesToWords([]byte) ([]string, error) - WordsToBytes([]string) ([]byte, error) -} - -type WordCodec struct { - words []string - bytes map[string]int - check ECC -} - -var _ Codec = &WordCodec{} - -func NewCodec(words []string) (codec *WordCodec, err error) { - if len(words) != BankSize { - return codec, errors.Errorf("Bank must have %d words, found %d", BankSize, len(words)) - } - - res := &WordCodec{ - words: words, - // TODO: configure this outside??? - check: NewIEEECRC32(), - // check: NewIBMCRC16(), - } - - return res, nil -} - -// LoadCodec loads a pre-compiled language file -func LoadCodec(bank string) (codec *WordCodec, err error) { - words, err := loadBank(bank) - if err != nil { - return codec, err - } - return NewCodec(words) -} - -// MustLoadCodec panics if word bank is missing, only for tests -func MustLoadCodec(bank string) *WordCodec { - codec, err := LoadCodec(bank) - if err != nil { - panic(err) - } - return codec -} - -// loadBank opens a wordlist file and returns all words inside -func loadBank(bank string) ([]string, error) { - filename := "keys/words/wordlist/" + bank + ".txt" - words, err := wordlist.Asset(filename) - if err != nil { - return nil, err - } - wordsAll := strings.Split(strings.TrimSpace(string(words)), "\n") - return wordsAll, nil -} - -// // TODO: read from go-bind assets -// func getData(filename string) (string, error) { -// f, err := os.Open(filename) -// if err != nil { -// return "", errors.WithStack(err) -// } -// defer f.Close() - -// data, err := ioutil.ReadAll(f) -// if err != nil { -// return "", errors.WithStack(err) -// } - -// return string(data), nil -// } - -// given this many bytes, we will produce this many words -func wordlenFromBytes(numBytes int) int { - // 2048 words per bank, which is 2^11. - // 8 bits per byte, and we add +10 so it rounds up - return (8*numBytes + 10) / 11 -} - -// given this many words, we will produce this many bytes. -// sometimes there are two possibilities. -// if maybeShorter is true, then represents len OR len-1 bytes -func bytelenFromWords(numWords int) (length int, maybeShorter bool) { - // calculate the max number of complete bytes we could store in this word - length = 11 * numWords / 8 - // if one less byte would also generate this length, set maybeShorter - if wordlenFromBytes(length-1) == numWords { - maybeShorter = true - } - return -} - -// TODO: add checksum -func (c *WordCodec) BytesToWords(raw []byte) (words []string, err error) { - // always add a checksum to the data - data := c.check.AddECC(raw) - numWords := wordlenFromBytes(len(data)) - - n2048 := big.NewInt(2048) - nData := big.NewInt(0).SetBytes(data) - nRem := big.NewInt(0) - // Alternative, use condition "nData.BitLen() > 0" - // to allow for shorter words when data has leading 0's - for i := 0; i < numWords; i++ { - nData.DivMod(nData, n2048, nRem) - rem := nRem.Int64() - w := c.words[rem] - // double-check bank on generation... - _, err := c.GetIndex(w) - if err != nil { - return nil, err - } - words = append(words, w) - } - return words, nil -} - -func (c *WordCodec) WordsToBytes(words []string) ([]byte, error) { - l := len(words) - - if l == 0 { - return nil, errors.New("Didn't provide any words") - } - - n2048 := big.NewInt(2048) - nData := big.NewInt(0) - // since we output words based on the remainder, the first word has the lowest - // value... we must load them in reverse order - for i := 1; i <= l; i++ { - rem, err := c.GetIndex(words[l-i]) - if err != nil { - return nil, err - } - nRem := big.NewInt(int64(rem)) - nData.Mul(nData, n2048) - nData.Add(nData, nRem) - } - - // we copy into a slice of the expected size, so it is not shorter if there - // are lots of leading 0s - dataBytes := nData.Bytes() - - // copy into the container we have with the expected size - outLen, flex := bytelenFromWords(len(words)) - toCheck := make([]byte, outLen) - if len(dataBytes) > outLen { - return nil, errors.New("Invalid data, could not have been generated by this codec") - } - copy(toCheck[outLen-len(dataBytes):], dataBytes) - - // validate the checksum... - output, err := c.check.CheckECC(toCheck) - if flex && err != nil { - // if flex, try again one shorter.... - toCheck = toCheck[1:] - output, err = c.check.CheckECC(toCheck) - } - - return output, err -} - -// GetIndex finds the index of the words to create bytes -// Generates a map the first time it is loaded, to avoid needless -// computation when list is not used. -func (c *WordCodec) GetIndex(word string) (int, error) { - // generate the first time - if c.bytes == nil { - b := map[string]int{} - for i, w := range c.words { - if _, ok := b[w]; ok { - return -1, errors.Errorf("Duplicate word in list: %s", w) - } - b[w] = i - } - c.bytes = b - } - - // get the index, or an error - rem, ok := c.bytes[word] - if !ok { - return -1, errors.Errorf("Unrecognized word: %s", word) - } - return rem, nil -} diff --git a/keys/words/wordcodec_test.go b/keys/words/wordcodec_test.go deleted file mode 100644 index 367e3799a..000000000 --- a/keys/words/wordcodec_test.go +++ /dev/null @@ -1,180 +0,0 @@ -package words - -import ( - "testing" - - asrt "github.com/stretchr/testify/assert" - rqr "github.com/stretchr/testify/require" - - cmn "github.com/tendermint/tmlibs/common" -) - -func TestLengthCalc(t *testing.T) { - assert := asrt.New(t) - - cases := []struct { - bytes, words int - flexible bool - }{ - {1, 1, false}, - {2, 2, false}, - // bytes pairs with same word count - {3, 3, true}, - {4, 3, true}, - {5, 4, false}, - // bytes pairs with same word count - {10, 8, true}, - {11, 8, true}, - {12, 9, false}, - {13, 10, false}, - {20, 15, false}, - // bytes pairs with same word count - {21, 16, true}, - {32, 24, true}, - } - - for _, tc := range cases { - wl := wordlenFromBytes(tc.bytes) - assert.Equal(tc.words, wl, "%d", tc.bytes) - - bl, flex := bytelenFromWords(tc.words) - assert.Equal(tc.flexible, flex, "%d", tc.words) - if !flex { - assert.Equal(tc.bytes, bl, "%d", tc.words) - } else { - // check if it is either tc.bytes or tc.bytes +1 - choices := []int{tc.bytes, tc.bytes + 1} - assert.Contains(choices, bl, "%d", tc.words) - } - } -} - -func TestEncodeDecode(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - codec, err := LoadCodec("english") - require.Nil(err, "%+v", err) - - cases := [][]byte{ - {7, 8, 9}, // TODO: 3 words -> 3 or 4 bytes - {12, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes - {0, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes, detect leading 0 - {1, 2, 3, 4, 5}, // normal - {0, 0, 0, 0, 122, 23, 82, 195}, // leading 0s (8 chars, unclear) - {0, 0, 0, 0, 5, 22, 123, 55, 22}, // leading 0s (9 chars, clear) - {22, 44, 55, 1, 13, 0, 0, 0, 0}, // trailing 0s (9 chars, clear) - {0, 5, 253, 2, 0}, // leading and trailing zeros - {255, 196, 172, 234, 192, 255}, // big numbers - {255, 196, 172, 1, 234, 192, 255}, // big numbers, two length choices - // others? - } - - for i, tc := range cases { - w, err := codec.BytesToWords(tc) - if assert.Nil(err, "%d: %v", i, err) { - b, err := codec.WordsToBytes(w) - if assert.Nil(err, "%d: %v", i, err) { - assert.Equal(len(tc), len(b)) - assert.Equal(tc, b) - } - } - } -} - -func TestCheckInvalidLists(t *testing.T) { - assert := asrt.New(t) - - trivial := []string{"abc", "def"} - short := make([]string, 1234) - long := make([]string, BankSize+1) - right := make([]string, BankSize) - dups := make([]string, BankSize) - - for _, list := range [][]string{short, long, right, dups} { - for i := range list { - list[i] = cmn.RandStr(8) - } - } - // create one single duplicate - dups[192] = dups[782] - - cases := []struct { - words []string - loadable bool - valid bool - }{ - {trivial, false, false}, - {short, false, false}, - {long, false, false}, - {dups, true, false}, // we only check dups on first use... - {right, true, true}, - } - - for i, tc := range cases { - codec, err := NewCodec(tc.words) - if !tc.loadable { - assert.NotNil(err, "%d", i) - } else if assert.Nil(err, "%d: %+v", i, err) { - data := cmn.RandBytes(32) - w, err := codec.BytesToWords(data) - if tc.valid { - assert.Nil(err, "%d: %+v", i, err) - b, err1 := codec.WordsToBytes(w) - assert.Nil(err1, "%d: %+v", i, err1) - assert.Equal(data, b) - } else { - assert.NotNil(err, "%d", i) - } - } - } - -} - -func getRandWord(c *WordCodec) string { - idx := cmn.RandInt() % BankSize - return c.words[idx] -} - -func getDiffWord(c *WordCodec, not string) string { - w := getRandWord(c) - if w == not { - w = getRandWord(c) - } - return w -} - -func TestCheckTypoDetection(t *testing.T) { - assert, require := asrt.New(t), rqr.New(t) - - banks := []string{"english", "spanish", "japanese", "chinese_simplified"} - - for _, bank := range banks { - codec, err := LoadCodec(bank) - require.Nil(err, "%s: %+v", bank, err) - for i := 0; i < 1000; i++ { - numBytes := cmn.RandInt()%60 + 4 - data := cmn.RandBytes(numBytes) - - words, err := codec.BytesToWords(data) - assert.Nil(err, "%s: %+v", bank, err) - good, err := codec.WordsToBytes(words) - assert.Nil(err, "%s: %+v", bank, err) - assert.Equal(data, good, bank) - - // now try some tweaks... - cut := words[1:] - _, err = codec.WordsToBytes(cut) - assert.NotNil(err, "%s: %s", bank, words) - - // swap a word within the bank, should fails - words[3] = getDiffWord(codec, words[3]) - _, err = codec.WordsToBytes(words) - assert.NotNil(err, "%s: %s", bank, words) - - // put a random word here, must fail - words[3] = cmn.RandStr(10) - _, err = codec.WordsToBytes(words) - assert.NotNil(err, "%s: %s", bank, words) - } - } -} diff --git a/keys/words/wordcodecbench_test.go b/keys/words/wordcodecbench_test.go deleted file mode 100644 index 04417a936..000000000 --- a/keys/words/wordcodecbench_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package words - -import ( - "testing" - - cmn "github.com/tendermint/tmlibs/common" -) - -func warmupCodec(bank string) *WordCodec { - codec, err := LoadCodec(bank) - if err != nil { - panic(err) - } - _, err = codec.GetIndex(codec.words[123]) - if err != nil { - panic(err) - } - return codec -} - -func BenchmarkCodec(b *testing.B) { - banks := []string{"english", "spanish", "japanese", "chinese_simplified"} - - for _, bank := range banks { - b.Run(bank, func(sub *testing.B) { - codec := warmupCodec(bank) - sub.ResetTimer() - benchSuite(sub, codec) - }) - } -} - -func benchSuite(b *testing.B, codec *WordCodec) { - b.Run("to_words", func(sub *testing.B) { - benchMakeWords(sub, codec) - }) - b.Run("to_bytes", func(sub *testing.B) { - benchParseWords(sub, codec) - }) -} - -func benchMakeWords(b *testing.B, codec *WordCodec) { - numBytes := 32 - data := cmn.RandBytes(numBytes) - for i := 1; i <= b.N; i++ { - _, err := codec.BytesToWords(data) - if err != nil { - panic(err) - } - } -} - -func benchParseWords(b *testing.B, codec *WordCodec) { - // generate a valid test string to parse - numBytes := 32 - data := cmn.RandBytes(numBytes) - words, err := codec.BytesToWords(data) - if err != nil { - panic(err) - } - - for i := 1; i <= b.N; i++ { - _, err := codec.WordsToBytes(words) - if err != nil { - panic(err) - } - } -} diff --git a/keys/words/wordlist/chinese_simplified.txt b/keys/words/wordlist/chinese_simplified.txt deleted file mode 100644 index b90f1ed85..000000000 --- a/keys/words/wordlist/chinese_simplified.txt +++ /dev/null @@ -1,2048 +0,0 @@ -的 -一 -是 -在 -不 -了 -有 -和 -人 -这 -中 -大 -为 -上 -个 -国 -我 -以 -要 -他 -时 -来 -用 -们 -生 -到 -作 -地 -于 -出 -就 -分 -对 -成 -会 -可 -主 -发 -年 -动 -同 -工 -也 -能 -下 -过 -子 -说 -产 -种 -面 -而 -方 -后 -多 -定 -行 -学 -法 -所 -民 -得 -经 -十 -三 -之 -进 -着 -等 -部 -度 -家 -电 -力 -里 -如 -水 -化 -高 -自 -二 -理 -起 -小 -物 -现 -实 -加 -量 -都 -两 -体 -制 -机 -当 -使 -点 -从 -业 -本 -去 -把 -性 -好 -应 -开 -它 -合 -还 -因 -由 -其 -些 -然 -前 -外 -天 -政 -四 -日 -那 -社 -义 -事 -平 -形 -相 -全 -表 -间 -样 -与 -关 -各 -重 -新 -线 -内 -数 -正 -心 -反 -你 -明 -看 -原 -又 -么 -利 -比 -或 -但 -质 -气 -第 -向 -道 -命 -此 -变 -条 -只 -没 -结 -解 -问 -意 -建 -月 -公 -无 -系 -军 -很 -情 -者 -最 -立 -代 -想 -已 -通 -并 -提 -直 -题 -党 -程 -展 -五 -果 -料 -象 -员 -革 -位 -入 -常 -文 -总 -次 -品 -式 -活 -设 -及 -管 -特 -件 -长 -求 -老 -头 -基 -资 -边 -流 -路 -级 -少 -图 -山 -统 -接 -知 -较 -将 -组 -见 -计 -别 -她 -手 -角 -期 -根 -论 -运 -农 -指 -几 -九 -区 -强 -放 -决 -西 -被 -干 -做 -必 -战 -先 -回 -则 -任 -取 -据 -处 -队 -南 -给 -色 -光 -门 -即 -保 -治 -北 -造 -百 -规 -热 -领 -七 -海 -口 -东 -导 -器 -压 -志 -世 -金 -增 -争 -济 -阶 -油 -思 -术 -极 -交 -受 -联 -什 -认 -六 -共 -权 -收 -证 -改 -清 -美 -再 -采 -转 -更 -单 -风 -切 -打 -白 -教 -速 -花 -带 -安 -场 -身 -车 -例 -真 -务 -具 -万 -每 -目 -至 -达 -走 -积 -示 -议 -声 -报 -斗 -完 -类 -八 -离 -华 -名 -确 -才 -科 -张 -信 -马 -节 -话 -米 -整 -空 -元 -况 -今 -集 -温 -传 -土 -许 -步 -群 -广 -石 -记 -需 -段 -研 -界 -拉 -林 -律 -叫 -且 -究 -观 -越 -织 -装 -影 -算 -低 -持 -音 -众 -书 -布 -复 -容 -儿 -须 -际 -商 -非 -验 -连 -断 -深 -难 -近 -矿 -千 -周 -委 -素 -技 -备 -半 -办 -青 -省 -列 -习 -响 -约 -支 -般 -史 -感 -劳 -便 -团 -往 -酸 -历 -市 -克 -何 -除 -消 -构 -府 -称 -太 -准 -精 -值 -号 -率 -族 -维 -划 -选 -标 -写 -存 -候 -毛 -亲 -快 -效 -斯 -院 -查 -江 -型 -眼 -王 -按 -格 -养 -易 -置 -派 -层 -片 -始 -却 -专 -状 -育 -厂 -京 -识 -适 -属 -圆 -包 -火 -住 -调 -满 -县 -局 -照 -参 -红 -细 -引 -听 -该 -铁 -价 -严 -首 -底 -液 -官 -德 -随 -病 -苏 -失 -尔 -死 -讲 -配 -女 -黄 -推 -显 -谈 -罪 -神 -艺 -呢 -席 -含 -企 -望 -密 -批 -营 -项 -防 -举 -球 -英 -氧 -势 -告 -李 -台 -落 -木 -帮 -轮 -破 -亚 -师 -围 -注 -远 -字 -材 -排 -供 -河 -态 -封 -另 -施 -减 -树 -溶 -怎 -止 -案 -言 -士 -均 -武 -固 -叶 -鱼 -波 -视 -仅 -费 -紧 -爱 -左 -章 -早 -朝 -害 -续 -轻 -服 -试 -食 -充 -兵 -源 -判 -护 -司 -足 -某 -练 -差 -致 -板 -田 -降 -黑 -犯 -负 -击 -范 -继 -兴 -似 -余 -坚 -曲 -输 -修 -故 -城 -夫 -够 -送 -笔 -船 -占 -右 -财 -吃 -富 -春 -职 -觉 -汉 -画 -功 -巴 -跟 -虽 -杂 -飞 -检 -吸 -助 -升 -阳 -互 -初 -创 -抗 -考 -投 -坏 -策 -古 -径 -换 -未 -跑 -留 -钢 -曾 -端 -责 -站 -简 -述 -钱 -副 -尽 -帝 -射 -草 -冲 -承 -独 -令 -限 -阿 -宣 -环 -双 -请 -超 -微 -让 -控 -州 -良 -轴 -找 -否 -纪 -益 -依 -优 -顶 -础 -载 -倒 -房 -突 -坐 -粉 -敌 -略 -客 -袁 -冷 -胜 -绝 -析 -块 -剂 -测 -丝 -协 -诉 -念 -陈 -仍 -罗 -盐 -友 -洋 -错 -苦 -夜 -刑 -移 -频 -逐 -靠 -混 -母 -短 -皮 -终 -聚 -汽 -村 -云 -哪 -既 -距 -卫 -停 -烈 -央 -察 -烧 -迅 -境 -若 -印 -洲 -刻 -括 -激 -孔 -搞 -甚 -室 -待 -核 -校 -散 -侵 -吧 -甲 -游 -久 -菜 -味 -旧 -模 -湖 -货 -损 -预 -阻 -毫 -普 -稳 -乙 -妈 -植 -息 -扩 -银 -语 -挥 -酒 -守 -拿 -序 -纸 -医 -缺 -雨 -吗 -针 -刘 -啊 -急 -唱 -误 -训 -愿 -审 -附 -获 -茶 -鲜 -粮 -斤 -孩 -脱 -硫 -肥 -善 -龙 -演 -父 -渐 -血 -欢 -械 -掌 -歌 -沙 -刚 -攻 -谓 -盾 -讨 -晚 -粒 -乱 -燃 -矛 -乎 -杀 -药 -宁 -鲁 -贵 -钟 -煤 -读 -班 -伯 -香 -介 -迫 -句 -丰 -培 -握 -兰 -担 -弦 -蛋 -沉 -假 -穿 -执 -答 -乐 -谁 -顺 -烟 -缩 -征 -脸 -喜 -松 -脚 -困 -异 -免 -背 -星 -福 -买 -染 -井 -概 -慢 -怕 -磁 -倍 -祖 -皇 -促 -静 -补 -评 -翻 -肉 -践 -尼 -衣 -宽 -扬 -棉 -希 -伤 -操 -垂 -秋 -宜 -氢 -套 -督 -振 -架 -亮 -末 -宪 -庆 -编 -牛 -触 -映 -雷 -销 -诗 -座 -居 -抓 -裂 -胞 -呼 -娘 -景 -威 -绿 -晶 -厚 -盟 -衡 -鸡 -孙 -延 -危 -胶 -屋 -乡 -临 -陆 -顾 -掉 -呀 -灯 -岁 -措 -束 -耐 -剧 -玉 -赵 -跳 -哥 -季 -课 -凯 -胡 -额 -款 -绍 -卷 -齐 -伟 -蒸 -殖 -永 -宗 -苗 -川 -炉 -岩 -弱 -零 -杨 -奏 -沿 -露 -杆 -探 -滑 -镇 -饭 -浓 -航 -怀 -赶 -库 -夺 -伊 -灵 -税 -途 -灭 -赛 -归 -召 -鼓 -播 -盘 -裁 -险 -康 -唯 -录 -菌 -纯 -借 -糖 -盖 -横 -符 -私 -努 -堂 -域 -枪 -润 -幅 -哈 -竟 -熟 -虫 -泽 -脑 -壤 -碳 -欧 -遍 -侧 -寨 -敢 -彻 -虑 -斜 -薄 -庭 -纳 -弹 -饲 -伸 -折 -麦 -湿 -暗 -荷 -瓦 -塞 -床 -筑 -恶 -户 -访 -塔 -奇 -透 -梁 -刀 -旋 -迹 -卡 -氯 -遇 -份 -毒 -泥 -退 -洗 -摆 -灰 -彩 -卖 -耗 -夏 -择 -忙 -铜 -献 -硬 -予 -繁 -圈 -雪 -函 -亦 -抽 -篇 -阵 -阴 -丁 -尺 -追 -堆 -雄 -迎 -泛 -爸 -楼 -避 -谋 -吨 -野 -猪 -旗 -累 -偏 -典 -馆 -索 -秦 -脂 -潮 -爷 -豆 -忽 -托 -惊 -塑 -遗 -愈 -朱 -替 -纤 -粗 -倾 -尚 -痛 -楚 -谢 -奋 -购 -磨 -君 -池 -旁 -碎 -骨 -监 -捕 -弟 -暴 -割 -贯 -殊 -释 -词 -亡 -壁 -顿 -宝 -午 -尘 -闻 -揭 -炮 -残 -冬 -桥 -妇 -警 -综 -招 -吴 -付 -浮 -遭 -徐 -您 -摇 -谷 -赞 -箱 -隔 -订 -男 -吹 -园 -纷 -唐 -败 -宋 -玻 -巨 -耕 -坦 -荣 -闭 -湾 -键 -凡 -驻 -锅 -救 -恩 -剥 -凝 -碱 -齿 -截 -炼 -麻 -纺 -禁 -废 -盛 -版 -缓 -净 -睛 -昌 -婚 -涉 -筒 -嘴 -插 -岸 -朗 -庄 -街 -藏 -姑 -贸 -腐 -奴 -啦 -惯 -乘 -伙 -恢 -匀 -纱 -扎 -辩 -耳 -彪 -臣 -亿 -璃 -抵 -脉 -秀 -萨 -俄 -网 -舞 -店 -喷 -纵 -寸 -汗 -挂 -洪 -贺 -闪 -柬 -爆 -烯 -津 -稻 -墙 -软 -勇 -像 -滚 -厘 -蒙 -芳 -肯 -坡 -柱 -荡 -腿 -仪 -旅 -尾 -轧 -冰 -贡 -登 -黎 -削 -钻 -勒 -逃 -障 -氨 -郭 -峰 -币 -港 -伏 -轨 -亩 -毕 -擦 -莫 -刺 -浪 -秘 -援 -株 -健 -售 -股 -岛 -甘 -泡 -睡 -童 -铸 -汤 -阀 -休 -汇 -舍 -牧 -绕 -炸 -哲 -磷 -绩 -朋 -淡 -尖 -启 -陷 -柴 -呈 -徒 -颜 -泪 -稍 -忘 -泵 -蓝 -拖 -洞 -授 -镜 -辛 -壮 -锋 -贫 -虚 -弯 -摩 -泰 -幼 -廷 -尊 -窗 -纲 -弄 -隶 -疑 -氏 -宫 -姐 -震 -瑞 -怪 -尤 -琴 -循 -描 -膜 -违 -夹 -腰 -缘 -珠 -穷 -森 -枝 -竹 -沟 -催 -绳 -忆 -邦 -剩 -幸 -浆 -栏 -拥 -牙 -贮 -礼 -滤 -钠 -纹 -罢 -拍 -咱 -喊 -袖 -埃 -勤 -罚 -焦 -潜 -伍 -墨 -欲 -缝 -姓 -刊 -饱 -仿 -奖 -铝 -鬼 -丽 -跨 -默 -挖 -链 -扫 -喝 -袋 -炭 -污 -幕 -诸 -弧 -励 -梅 -奶 -洁 -灾 -舟 -鉴 -苯 -讼 -抱 -毁 -懂 -寒 -智 -埔 -寄 -届 -跃 -渡 -挑 -丹 -艰 -贝 -碰 -拔 -爹 -戴 -码 -梦 -芽 -熔 -赤 -渔 -哭 -敬 -颗 -奔 -铅 -仲 -虎 -稀 -妹 -乏 -珍 -申 -桌 -遵 -允 -隆 -螺 -仓 -魏 -锐 -晓 -氮 -兼 -隐 -碍 -赫 -拨 -忠 -肃 -缸 -牵 -抢 -博 -巧 -壳 -兄 -杜 -讯 -诚 -碧 -祥 -柯 -页 -巡 -矩 -悲 -灌 -龄 -伦 -票 -寻 -桂 -铺 -圣 -恐 -恰 -郑 -趣 -抬 -荒 -腾 -贴 -柔 -滴 -猛 -阔 -辆 -妻 -填 -撤 -储 -签 -闹 -扰 -紫 -砂 -递 -戏 -吊 -陶 -伐 -喂 -疗 -瓶 -婆 -抚 -臂 -摸 -忍 -虾 -蜡 -邻 -胸 -巩 -挤 -偶 -弃 -槽 -劲 -乳 -邓 -吉 -仁 -烂 -砖 -租 -乌 -舰 -伴 -瓜 -浅 -丙 -暂 -燥 -橡 -柳 -迷 -暖 -牌 -秧 -胆 -详 -簧 -踏 -瓷 -谱 -呆 -宾 -糊 -洛 -辉 -愤 -竞 -隙 -怒 -粘 -乃 -绪 -肩 -籍 -敏 -涂 -熙 -皆 -侦 -悬 -掘 -享 -纠 -醒 -狂 -锁 -淀 -恨 -牲 -霸 -爬 -赏 -逆 -玩 -陵 -祝 -秒 -浙 -貌 -役 -彼 -悉 -鸭 -趋 -凤 -晨 -畜 -辈 -秩 -卵 -署 -梯 -炎 -滩 -棋 -驱 -筛 -峡 -冒 -啥 -寿 -译 -浸 -泉 -帽 -迟 -硅 -疆 -贷 -漏 -稿 -冠 -嫩 -胁 -芯 -牢 -叛 -蚀 -奥 -鸣 -岭 -羊 -凭 -串 -塘 -绘 -酵 -融 -盆 -锡 -庙 -筹 -冻 -辅 -摄 -袭 -筋 -拒 -僚 -旱 -钾 -鸟 -漆 -沈 -眉 -疏 -添 -棒 -穗 -硝 -韩 -逼 -扭 -侨 -凉 -挺 -碗 -栽 -炒 -杯 -患 -馏 -劝 -豪 -辽 -勃 -鸿 -旦 -吏 -拜 -狗 -埋 -辊 -掩 -饮 -搬 -骂 -辞 -勾 -扣 -估 -蒋 -绒 -雾 -丈 -朵 -姆 -拟 -宇 -辑 -陕 -雕 -偿 -蓄 -崇 -剪 -倡 -厅 -咬 -驶 -薯 -刷 -斥 -番 -赋 -奉 -佛 -浇 -漫 -曼 -扇 -钙 -桃 -扶 -仔 -返 -俗 -亏 -腔 -鞋 -棱 -覆 -框 -悄 -叔 -撞 -骗 -勘 -旺 -沸 -孤 -吐 -孟 -渠 -屈 -疾 -妙 -惜 -仰 -狠 -胀 -谐 -抛 -霉 -桑 -岗 -嘛 -衰 -盗 -渗 -脏 -赖 -涌 -甜 -曹 -阅 -肌 -哩 -厉 -烃 -纬 -毅 -昨 -伪 -症 -煮 -叹 -钉 -搭 -茎 -笼 -酷 -偷 -弓 -锥 -恒 -杰 -坑 -鼻 -翼 -纶 -叙 -狱 -逮 -罐 -络 -棚 -抑 -膨 -蔬 -寺 -骤 -穆 -冶 -枯 -册 -尸 -凸 -绅 -坯 -牺 -焰 -轰 -欣 -晋 -瘦 -御 -锭 -锦 -丧 -旬 -锻 -垄 -搜 -扑 -邀 -亭 -酯 -迈 -舒 -脆 -酶 -闲 -忧 -酚 -顽 -羽 -涨 -卸 -仗 -陪 -辟 -惩 -杭 -姚 -肚 -捉 -飘 -漂 -昆 -欺 -吾 -郎 -烷 -汁 -呵 -饰 -萧 -雅 -邮 -迁 -燕 -撒 -姻 -赴 -宴 -烦 -债 -帐 -斑 -铃 -旨 -醇 -董 -饼 -雏 -姿 -拌 -傅 -腹 -妥 -揉 -贤 -拆 -歪 -葡 -胺 -丢 -浩 -徽 -昂 -垫 -挡 -览 -贪 -慰 -缴 -汪 -慌 -冯 -诺 -姜 -谊 -凶 -劣 -诬 -耀 -昏 -躺 -盈 -骑 -乔 -溪 -丛 -卢 -抹 -闷 -咨 -刮 -驾 -缆 -悟 -摘 -铒 -掷 -颇 -幻 -柄 -惠 -惨 -佳 -仇 -腊 -窝 -涤 -剑 -瞧 -堡 -泼 -葱 -罩 -霍 -捞 -胎 -苍 -滨 -俩 -捅 -湘 -砍 -霞 -邵 -萄 -疯 -淮 -遂 -熊 -粪 -烘 -宿 -档 -戈 -驳 -嫂 -裕 -徙 -箭 -捐 -肠 -撑 -晒 -辨 -殿 -莲 -摊 -搅 -酱 -屏 -疫 -哀 -蔡 -堵 -沫 -皱 -畅 -叠 -阁 -莱 -敲 -辖 -钩 -痕 -坝 -巷 -饿 -祸 -丘 -玄 -溜 -曰 -逻 -彭 -尝 -卿 -妨 -艇 -吞 -韦 -怨 -矮 -歇 diff --git a/keys/words/wordlist/english.txt b/keys/words/wordlist/english.txt deleted file mode 100644 index 942040ed5..000000000 --- a/keys/words/wordlist/english.txt +++ /dev/null @@ -1,2048 +0,0 @@ -abandon -ability -able -about -above -absent -absorb -abstract -absurd -abuse -access -accident -account -accuse -achieve -acid -acoustic -acquire -across -act -action -actor -actress -actual -adapt -add -addict -address -adjust -admit -adult -advance -advice -aerobic -affair -afford -afraid -again -age -agent -agree -ahead -aim -air -airport -aisle -alarm -album -alcohol -alert -alien -all -alley -allow -almost -alone -alpha -already -also -alter -always -amateur -amazing -among -amount -amused -analyst -anchor -ancient -anger -angle -angry -animal -ankle -announce -annual -another -answer -antenna -antique -anxiety -any -apart -apology -appear -apple -approve -april -arch -arctic -area -arena -argue -arm -armed -armor -army -around -arrange -arrest -arrive -arrow -art -artefact -artist -artwork -ask -aspect -assault -asset -assist -assume -asthma -athlete -atom -attack -attend -attitude -attract -auction -audit -august -aunt -author -auto -autumn -average -avocado -avoid -awake -aware -away -awesome -awful -awkward -axis -baby -bachelor -bacon -badge -bag -balance -balcony -ball -bamboo -banana -banner -bar -barely -bargain -barrel -base -basic -basket -battle -beach -bean -beauty -because -become -beef -before -begin -behave -behind -believe -below -belt -bench -benefit -best -betray -better -between -beyond -bicycle -bid -bike -bind -biology -bird -birth -bitter -black -blade -blame -blanket -blast -bleak -bless -blind -blood -blossom -blouse -blue -blur -blush -board -boat -body -boil -bomb -bone -bonus -book -boost -border -boring -borrow -boss -bottom -bounce -box -boy -bracket -brain -brand -brass -brave -bread -breeze -brick -bridge -brief -bright -bring -brisk -broccoli -broken -bronze -broom -brother -brown -brush -bubble -buddy -budget -buffalo -build -bulb -bulk -bullet -bundle -bunker -burden -burger -burst -bus -business -busy -butter -buyer -buzz -cabbage -cabin -cable -cactus -cage -cake -call -calm -camera -camp -can -canal -cancel -candy -cannon -canoe -canvas -canyon -capable -capital -captain -car -carbon -card -cargo -carpet -carry -cart -case -cash -casino -castle -casual -cat -catalog -catch -category -cattle -caught -cause -caution -cave -ceiling -celery -cement -census -century -cereal -certain -chair -chalk -champion -change -chaos -chapter -charge -chase -chat -cheap -check -cheese -chef -cherry -chest -chicken -chief -child -chimney -choice -choose -chronic -chuckle -chunk -churn -cigar -cinnamon -circle -citizen -city -civil -claim -clap -clarify -claw -clay -clean -clerk -clever -click -client -cliff -climb -clinic -clip -clock -clog -close -cloth -cloud -clown -club -clump -cluster -clutch -coach -coast -coconut -code -coffee -coil -coin -collect -color -column -combine -come -comfort -comic -common -company -concert -conduct -confirm -congress -connect -consider -control -convince -cook -cool -copper -copy -coral -core -corn -correct -cost -cotton -couch -country -couple -course -cousin -cover -coyote -crack -cradle -craft -cram -crane -crash -crater -crawl -crazy -cream -credit -creek -crew -cricket -crime -crisp -critic -crop -cross -crouch -crowd -crucial -cruel -cruise -crumble -crunch -crush -cry -crystal -cube -culture -cup -cupboard -curious -current -curtain -curve -cushion -custom -cute -cycle -dad -damage -damp -dance -danger -daring -dash -daughter -dawn -day -deal -debate -debris -decade -december -decide -decline -decorate -decrease -deer -defense -define -defy -degree -delay -deliver -demand -demise -denial -dentist -deny -depart -depend -deposit -depth -deputy -derive -describe -desert -design -desk -despair -destroy -detail -detect -develop -device -devote -diagram -dial -diamond -diary -dice -diesel -diet -differ -digital -dignity -dilemma -dinner -dinosaur -direct -dirt -disagree -discover -disease -dish -dismiss -disorder -display -distance -divert -divide -divorce -dizzy -doctor -document -dog -doll -dolphin -domain -donate -donkey -donor -door -dose -double -dove -draft -dragon -drama -drastic -draw -dream -dress -drift -drill -drink -drip -drive -drop -drum -dry -duck -dumb -dune -during -dust -dutch -duty -dwarf -dynamic -eager -eagle -early -earn -earth -easily -east -easy -echo -ecology -economy -edge -edit -educate -effort -egg -eight -either -elbow -elder -electric -elegant -element -elephant -elevator -elite -else -embark -embody -embrace -emerge -emotion -employ -empower -empty -enable -enact -end -endless -endorse -enemy -energy -enforce -engage -engine -enhance -enjoy -enlist -enough -enrich -enroll -ensure -enter -entire -entry -envelope -episode -equal -equip -era -erase -erode -erosion -error -erupt -escape -essay -essence -estate -eternal -ethics -evidence -evil -evoke -evolve -exact -example -excess -exchange -excite -exclude -excuse -execute -exercise -exhaust -exhibit -exile -exist -exit -exotic -expand -expect -expire -explain -expose -express -extend -extra -eye -eyebrow -fabric -face -faculty -fade -faint -faith -fall -false -fame -family -famous -fan -fancy -fantasy -farm -fashion -fat -fatal -father -fatigue -fault -favorite -feature -february -federal -fee -feed -feel -female -fence -festival -fetch -fever -few -fiber -fiction -field -figure -file -film -filter -final -find -fine -finger -finish -fire -firm -first -fiscal -fish -fit -fitness -fix -flag -flame -flash -flat -flavor -flee -flight -flip -float -flock -floor -flower -fluid -flush -fly -foam -focus -fog -foil -fold -follow -food -foot -force -forest -forget -fork -fortune -forum -forward -fossil -foster -found -fox -fragile -frame -frequent -fresh -friend -fringe -frog -front -frost -frown -frozen -fruit -fuel -fun -funny -furnace -fury -future -gadget -gain -galaxy -gallery -game -gap -garage -garbage -garden -garlic -garment -gas -gasp -gate -gather -gauge -gaze -general -genius -genre -gentle -genuine -gesture -ghost -giant -gift -giggle -ginger -giraffe -girl -give -glad -glance -glare -glass -glide -glimpse -globe -gloom -glory -glove -glow -glue -goat -goddess -gold -good -goose -gorilla -gospel -gossip -govern -gown -grab -grace -grain -grant -grape -grass -gravity -great -green -grid -grief -grit -grocery -group -grow -grunt -guard -guess -guide -guilt -guitar -gun -gym -habit -hair -half -hammer -hamster -hand -happy -harbor -hard -harsh -harvest -hat -have -hawk -hazard -head -health -heart -heavy -hedgehog -height -hello -helmet -help -hen -hero -hidden -high -hill -hint -hip -hire -history -hobby -hockey -hold -hole -holiday -hollow -home -honey -hood -hope -horn -horror -horse -hospital -host -hotel -hour -hover -hub -huge -human -humble -humor -hundred -hungry -hunt -hurdle -hurry -hurt -husband -hybrid -ice -icon -idea -identify -idle -ignore -ill -illegal -illness -image -imitate -immense -immune -impact -impose -improve -impulse -inch -include -income -increase -index -indicate -indoor -industry -infant -inflict -inform -inhale -inherit -initial -inject -injury -inmate -inner -innocent -input -inquiry -insane -insect -inside -inspire -install -intact -interest -into -invest -invite -involve -iron -island -isolate -issue -item -ivory -jacket -jaguar -jar -jazz -jealous -jeans -jelly -jewel -job -join -joke -journey -joy -judge -juice -jump -jungle -junior -junk -just -kangaroo -keen -keep -ketchup -key -kick -kid -kidney -kind -kingdom -kiss -kit -kitchen -kite -kitten -kiwi -knee -knife -knock -know -lab -label -labor -ladder -lady -lake -lamp -language -laptop -large -later -latin -laugh -laundry -lava -law -lawn -lawsuit -layer -lazy -leader -leaf -learn -leave -lecture -left -leg -legal -legend -leisure -lemon -lend -length -lens -leopard -lesson -letter -level -liar -liberty -library -license -life -lift -light -like -limb -limit -link -lion -liquid -list -little -live -lizard -load -loan -lobster -local -lock -logic -lonely -long -loop -lottery -loud -lounge -love -loyal -lucky -luggage -lumber -lunar -lunch -luxury -lyrics -machine -mad -magic -magnet -maid -mail -main -major -make -mammal -man -manage -mandate -mango -mansion -manual -maple -marble -march -margin -marine -market -marriage -mask -mass -master -match -material -math -matrix -matter -maximum -maze -meadow -mean -measure -meat -mechanic -medal -media -melody -melt -member -memory -mention -menu -mercy -merge -merit -merry -mesh -message -metal -method -middle -midnight -milk -million -mimic -mind -minimum -minor -minute -miracle -mirror -misery -miss -mistake -mix -mixed -mixture -mobile -model -modify -mom -moment -monitor -monkey -monster -month -moon -moral -more -morning -mosquito -mother -motion -motor -mountain -mouse -move -movie -much -muffin -mule -multiply -muscle -museum -mushroom -music -must -mutual -myself -mystery -myth -naive -name -napkin -narrow -nasty -nation -nature -near -neck -need -negative -neglect -neither -nephew -nerve -nest -net -network -neutral -never -news -next -nice -night -noble -noise -nominee -noodle -normal -north -nose -notable -note -nothing -notice -novel -now -nuclear -number -nurse -nut -oak -obey -object -oblige -obscure -observe -obtain -obvious -occur -ocean -october -odor -off -offer -office -often -oil -okay -old -olive -olympic -omit -once -one -onion -online -only -open -opera -opinion -oppose -option -orange -orbit -orchard -order -ordinary -organ -orient -original -orphan -ostrich -other -outdoor -outer -output -outside -oval -oven -over -own -owner -oxygen -oyster -ozone -pact -paddle -page -pair -palace -palm -panda -panel -panic -panther -paper -parade -parent -park -parrot -party -pass -patch -path -patient -patrol -pattern -pause -pave -payment -peace -peanut -pear -peasant -pelican -pen -penalty -pencil -people -pepper -perfect -permit -person -pet -phone -photo -phrase -physical -piano -picnic -picture -piece -pig -pigeon -pill -pilot -pink -pioneer -pipe -pistol -pitch -pizza -place -planet -plastic -plate -play -please -pledge -pluck -plug -plunge -poem -poet -point -polar -pole -police -pond -pony -pool -popular -portion -position -possible -post -potato -pottery -poverty -powder -power -practice -praise -predict -prefer -prepare -present -pretty -prevent -price -pride -primary -print -priority -prison -private -prize -problem -process -produce -profit -program -project -promote -proof -property -prosper -protect -proud -provide -public -pudding -pull -pulp -pulse -pumpkin -punch -pupil -puppy -purchase -purity -purpose -purse -push -put -puzzle -pyramid -quality -quantum -quarter -question -quick -quit -quiz -quote -rabbit -raccoon -race -rack -radar -radio -rail -rain -raise -rally -ramp -ranch -random -range -rapid -rare -rate -rather -raven -raw -razor -ready -real -reason -rebel -rebuild -recall -receive -recipe -record -recycle -reduce -reflect -reform -refuse -region -regret -regular -reject -relax -release -relief -rely -remain -remember -remind -remove -render -renew -rent -reopen -repair -repeat -replace -report -require -rescue -resemble -resist -resource -response -result -retire -retreat -return -reunion -reveal -review -reward -rhythm -rib -ribbon -rice -rich -ride -ridge -rifle -right -rigid -ring -riot -ripple -risk -ritual -rival -river -road -roast -robot -robust -rocket -romance -roof -rookie -room -rose -rotate -rough -round -route -royal -rubber -rude -rug -rule -run -runway -rural -sad -saddle -sadness -safe -sail -salad -salmon -salon -salt -salute -same -sample -sand -satisfy -satoshi -sauce -sausage -save -say -scale -scan -scare -scatter -scene -scheme -school -science -scissors -scorpion -scout -scrap -screen -script -scrub -sea -search -season -seat -second -secret -section -security -seed -seek -segment -select -sell -seminar -senior -sense -sentence -series -service -session -settle -setup -seven -shadow -shaft -shallow -share -shed -shell -sheriff -shield -shift -shine -ship -shiver -shock -shoe -shoot -shop -short -shoulder -shove -shrimp -shrug -shuffle -shy -sibling -sick -side -siege -sight -sign -silent -silk -silly -silver -similar -simple -since -sing -siren -sister -situate -six -size -skate -sketch -ski -skill -skin -skirt -skull -slab -slam -sleep -slender -slice -slide -slight -slim -slogan -slot -slow -slush -small -smart -smile -smoke -smooth -snack -snake -snap -sniff -snow -soap -soccer -social -sock -soda -soft -solar -soldier -solid -solution -solve -someone -song -soon -sorry -sort -soul -sound -soup -source -south -space -spare -spatial -spawn -speak -special -speed -spell -spend -sphere -spice -spider -spike -spin -spirit -split -spoil -sponsor -spoon -sport -spot -spray -spread -spring -spy -square -squeeze -squirrel -stable -stadium -staff -stage -stairs -stamp -stand -start -state -stay -steak -steel -stem -step -stereo -stick -still -sting -stock -stomach -stone -stool -story -stove -strategy -street -strike -strong -struggle -student -stuff -stumble -style -subject -submit -subway -success -such -sudden -suffer -sugar -suggest -suit -summer -sun -sunny -sunset -super -supply -supreme -sure -surface -surge -surprise -surround -survey -suspect -sustain -swallow -swamp -swap -swarm -swear -sweet -swift -swim -swing -switch -sword -symbol -symptom -syrup -system -table -tackle -tag -tail -talent -talk -tank -tape -target -task -taste -tattoo -taxi -teach -team -tell -ten -tenant -tennis -tent -term -test -text -thank -that -theme -then -theory -there -they -thing -this -thought -three -thrive -throw -thumb -thunder -ticket -tide -tiger -tilt -timber -time -tiny -tip -tired -tissue -title -toast -tobacco -today -toddler -toe -together -toilet -token -tomato -tomorrow -tone -tongue -tonight -tool -tooth -top -topic -topple -torch -tornado -tortoise -toss -total -tourist -toward -tower -town -toy -track -trade -traffic -tragic -train -transfer -trap -trash -travel -tray -treat -tree -trend -trial -tribe -trick -trigger -trim -trip -trophy -trouble -truck -true -truly -trumpet -trust -truth -try -tube -tuition -tumble -tuna -tunnel -turkey -turn -turtle -twelve -twenty -twice -twin -twist -two -type -typical -ugly -umbrella -unable -unaware -uncle -uncover -under -undo -unfair -unfold -unhappy -uniform -unique -unit -universe -unknown -unlock -until -unusual -unveil -update -upgrade -uphold -upon -upper -upset -urban -urge -usage -use -used -useful -useless -usual -utility -vacant -vacuum -vague -valid -valley -valve -van -vanish -vapor -various -vast -vault -vehicle -velvet -vendor -venture -venue -verb -verify -version -very -vessel -veteran -viable -vibrant -vicious -victory -video -view -village -vintage -violin -virtual -virus -visa -visit -visual -vital -vivid -vocal -voice -void -volcano -volume -vote -voyage -wage -wagon -wait -walk -wall -walnut -want -warfare -warm -warrior -wash -wasp -waste -water -wave -way -wealth -weapon -wear -weasel -weather -web -wedding -weekend -weird -welcome -west -wet -whale -what -wheat -wheel -when -where -whip -whisper -wide -width -wife -wild -will -win -window -wine -wing -wink -winner -winter -wire -wisdom -wise -wish -witness -wolf -woman -wonder -wood -wool -word -work -world -worry -worth -wrap -wreck -wrestle -wrist -write -wrong -yard -year -yellow -you -young -youth -zebra -zero -zone -zoo diff --git a/keys/words/wordlist/japanese.txt b/keys/words/wordlist/japanese.txt deleted file mode 100644 index c4c9dca4e..000000000 --- a/keys/words/wordlist/japanese.txt +++ /dev/null @@ -1,2048 +0,0 @@ -あいこくしん -あいさつ -あいだ -あおぞら -あかちゃん -あきる -あけがた -あける -あこがれる -あさい -あさひ -あしあと -あじわう -あずかる -あずき -あそぶ -あたえる -あたためる -あたりまえ -あたる -あつい -あつかう -あっしゅく -あつまり -あつめる -あてな -あてはまる -あひる -あぶら -あぶる -あふれる -あまい -あまど -あまやかす -あまり -あみもの -あめりか -あやまる -あゆむ -あらいぐま -あらし -あらすじ -あらためる -あらゆる -あらわす -ありがとう -あわせる -あわてる -あんい -あんがい -あんこ -あんぜん -あんてい -あんない -あんまり -いいだす -いおん -いがい -いがく -いきおい -いきなり -いきもの -いきる -いくじ -いくぶん -いけばな -いけん -いこう -いこく -いこつ -いさましい -いさん -いしき -いじゅう -いじょう -いじわる -いずみ -いずれ -いせい -いせえび -いせかい -いせき -いぜん -いそうろう -いそがしい -いだい -いだく -いたずら -いたみ -いたりあ -いちおう -いちじ -いちど -いちば -いちぶ -いちりゅう -いつか -いっしゅん -いっせい -いっそう -いったん -いっち -いってい -いっぽう -いてざ -いてん -いどう -いとこ -いない -いなか -いねむり -いのち -いのる -いはつ -いばる -いはん -いびき -いひん -いふく -いへん -いほう -いみん -いもうと -いもたれ -いもり -いやがる -いやす -いよかん -いよく -いらい -いらすと -いりぐち -いりょう -いれい -いれもの -いれる -いろえんぴつ -いわい -いわう -いわかん -いわば -いわゆる -いんげんまめ -いんさつ -いんしょう -いんよう -うえき -うえる -うおざ -うがい -うかぶ -うかべる -うきわ -うくらいな -うくれれ -うけたまわる -うけつけ -うけとる -うけもつ -うける -うごかす -うごく -うこん -うさぎ -うしなう -うしろがみ -うすい -うすぎ -うすぐらい -うすめる -うせつ -うちあわせ -うちがわ -うちき -うちゅう -うっかり -うつくしい -うったえる -うつる -うどん -うなぎ -うなじ -うなずく -うなる -うねる -うのう -うぶげ -うぶごえ -うまれる -うめる -うもう -うやまう -うよく -うらがえす -うらぐち -うらない -うりあげ -うりきれ -うるさい -うれしい -うれゆき -うれる -うろこ -うわき -うわさ -うんこう -うんちん -うんてん -うんどう -えいえん -えいが -えいきょう -えいご -えいせい -えいぶん -えいよう -えいわ -えおり -えがお -えがく -えきたい -えくせる -えしゃく -えすて -えつらん -えのぐ -えほうまき -えほん -えまき -えもじ -えもの -えらい -えらぶ -えりあ -えんえん -えんかい -えんぎ -えんげき -えんしゅう -えんぜつ -えんそく -えんちょう -えんとつ -おいかける -おいこす -おいしい -おいつく -おうえん -おうさま -おうじ -おうせつ -おうたい -おうふく -おうべい -おうよう -おえる -おおい -おおう -おおどおり -おおや -おおよそ -おかえり -おかず -おがむ -おかわり -おぎなう -おきる -おくさま -おくじょう -おくりがな -おくる -おくれる -おこす -おこなう -おこる -おさえる -おさない -おさめる -おしいれ -おしえる -おじぎ -おじさん -おしゃれ -おそらく -おそわる -おたがい -おたく -おだやか -おちつく -おっと -おつり -おでかけ -おとしもの -おとなしい -おどり -おどろかす -おばさん -おまいり -おめでとう -おもいで -おもう -おもたい -おもちゃ -おやつ -おやゆび -およぼす -おらんだ -おろす -おんがく -おんけい -おんしゃ -おんせん -おんだん -おんちゅう -おんどけい -かあつ -かいが -がいき -がいけん -がいこう -かいさつ -かいしゃ -かいすいよく -かいぜん -かいぞうど -かいつう -かいてん -かいとう -かいふく -がいへき -かいほう -かいよう -がいらい -かいわ -かえる -かおり -かかえる -かがく -かがし -かがみ -かくご -かくとく -かざる -がぞう -かたい -かたち -がちょう -がっきゅう -がっこう -がっさん -がっしょう -かなざわし -かのう -がはく -かぶか -かほう -かほご -かまう -かまぼこ -かめれおん -かゆい -かようび -からい -かるい -かろう -かわく -かわら -がんか -かんけい -かんこう -かんしゃ -かんそう -かんたん -かんち -がんばる -きあい -きあつ -きいろ -ぎいん -きうい -きうん -きえる -きおう -きおく -きおち -きおん -きかい -きかく -きかんしゃ -ききて -きくばり -きくらげ -きけんせい -きこう -きこえる -きこく -きさい -きさく -きさま -きさらぎ -ぎじかがく -ぎしき -ぎじたいけん -ぎじにってい -ぎじゅつしゃ -きすう -きせい -きせき -きせつ -きそう -きぞく -きぞん -きたえる -きちょう -きつえん -ぎっちり -きつつき -きつね -きてい -きどう -きどく -きない -きなが -きなこ -きぬごし -きねん -きのう -きのした -きはく -きびしい -きひん -きふく -きぶん -きぼう -きほん -きまる -きみつ -きむずかしい -きめる -きもだめし -きもち -きもの -きゃく -きやく -ぎゅうにく -きよう -きょうりゅう -きらい -きらく -きりん -きれい -きれつ -きろく -ぎろん -きわめる -ぎんいろ -きんかくじ -きんじょ -きんようび -ぐあい -くいず -くうかん -くうき -くうぐん -くうこう -ぐうせい -くうそう -ぐうたら -くうふく -くうぼ -くかん -くきょう -くげん -ぐこう -くさい -くさき -くさばな -くさる -くしゃみ -くしょう -くすのき -くすりゆび -くせげ -くせん -ぐたいてき -くださる -くたびれる -くちこみ -くちさき -くつした -ぐっすり -くつろぐ -くとうてん -くどく -くなん -くねくね -くのう -くふう -くみあわせ -くみたてる -くめる -くやくしょ -くらす -くらべる -くるま -くれる -くろう -くわしい -ぐんかん -ぐんしょく -ぐんたい -ぐんて -けあな -けいかく -けいけん -けいこ -けいさつ -げいじゅつ -けいたい -げいのうじん -けいれき -けいろ -けおとす -けおりもの -げきか -げきげん -げきだん -げきちん -げきとつ -げきは -げきやく -げこう -げこくじょう -げざい -けさき -げざん -けしき -けしごむ -けしょう -げすと -けたば -けちゃっぷ -けちらす -けつあつ -けつい -けつえき -けっこん -けつじょ -けっせき -けってい -けつまつ -げつようび -げつれい -けつろん -げどく -けとばす -けとる -けなげ -けなす -けなみ -けぬき -げねつ -けねん -けはい -げひん -けぶかい -げぼく -けまり -けみかる -けむし -けむり -けもの -けらい -けろけろ -けわしい -けんい -けんえつ -けんお -けんか -げんき -けんげん -けんこう -けんさく -けんしゅう -けんすう -げんそう -けんちく -けんてい -けんとう -けんない -けんにん -げんぶつ -けんま -けんみん -けんめい -けんらん -けんり -こあくま -こいぬ -こいびと -ごうい -こうえん -こうおん -こうかん -ごうきゅう -ごうけい -こうこう -こうさい -こうじ -こうすい -ごうせい -こうそく -こうたい -こうちゃ -こうつう -こうてい -こうどう -こうない -こうはい -ごうほう -ごうまん -こうもく -こうりつ -こえる -こおり -ごかい -ごがつ -ごかん -こくご -こくさい -こくとう -こくない -こくはく -こぐま -こけい -こける -ここのか -こころ -こさめ -こしつ -こすう -こせい -こせき -こぜん -こそだて -こたい -こたえる -こたつ -こちょう -こっか -こつこつ -こつばん -こつぶ -こてい -こてん -ことがら -ことし -ことば -ことり -こなごな -こねこね -このまま -このみ -このよ -ごはん -こひつじ -こふう -こふん -こぼれる -ごまあぶら -こまかい -ごますり -こまつな -こまる -こむぎこ -こもじ -こもち -こもの -こもん -こやく -こやま -こゆう -こゆび -こよい -こよう -こりる -これくしょん -ころっけ -こわもて -こわれる -こんいん -こんかい -こんき -こんしゅう -こんすい -こんだて -こんとん -こんなん -こんびに -こんぽん -こんまけ -こんや -こんれい -こんわく -ざいえき -さいかい -さいきん -ざいげん -ざいこ -さいしょ -さいせい -ざいたく -ざいちゅう -さいてき -ざいりょう -さうな -さかいし -さがす -さかな -さかみち -さがる -さぎょう -さくし -さくひん -さくら -さこく -さこつ -さずかる -ざせき -さたん -さつえい -ざつおん -ざっか -ざつがく -さっきょく -ざっし -さつじん -ざっそう -さつたば -さつまいも -さてい -さといも -さとう -さとおや -さとし -さとる -さのう -さばく -さびしい -さべつ -さほう -さほど -さます -さみしい -さみだれ -さむけ -さめる -さやえんどう -さゆう -さよう -さよく -さらだ -ざるそば -さわやか -さわる -さんいん -さんか -さんきゃく -さんこう -さんさい -ざんしょ -さんすう -さんせい -さんそ -さんち -さんま -さんみ -さんらん -しあい -しあげ -しあさって -しあわせ -しいく -しいん -しうち -しえい -しおけ -しかい -しかく -じかん -しごと -しすう -じだい -したうけ -したぎ -したて -したみ -しちょう -しちりん -しっかり -しつじ -しつもん -してい -してき -してつ -じてん -じどう -しなぎれ -しなもの -しなん -しねま -しねん -しのぐ -しのぶ -しはい -しばかり -しはつ -しはらい -しはん -しひょう -しふく -じぶん -しへい -しほう -しほん -しまう -しまる -しみん -しむける -じむしょ -しめい -しめる -しもん -しゃいん -しゃうん -しゃおん -じゃがいも -しやくしょ -しゃくほう -しゃけん -しゃこ -しゃざい -しゃしん -しゃせん -しゃそう -しゃたい -しゃちょう -しゃっきん -じゃま -しゃりん -しゃれい -じゆう -じゅうしょ -しゅくはく -じゅしん -しゅっせき -しゅみ -しゅらば -じゅんばん -しょうかい -しょくたく -しょっけん -しょどう -しょもつ -しらせる -しらべる -しんか -しんこう -じんじゃ -しんせいじ -しんちく -しんりん -すあげ -すあし -すあな -ずあん -すいえい -すいか -すいとう -ずいぶん -すいようび -すうがく -すうじつ -すうせん -すおどり -すきま -すくう -すくない -すける -すごい -すこし -ずさん -すずしい -すすむ -すすめる -すっかり -ずっしり -ずっと -すてき -すてる -すねる -すのこ -すはだ -すばらしい -ずひょう -ずぶぬれ -すぶり -すふれ -すべて -すべる -ずほう -すぼん -すまい -すめし -すもう -すやき -すらすら -するめ -すれちがう -すろっと -すわる -すんぜん -すんぽう -せあぶら -せいかつ -せいげん -せいじ -せいよう -せおう -せかいかん -せきにん -せきむ -せきゆ -せきらんうん -せけん -せこう -せすじ -せたい -せたけ -せっかく -せっきゃく -ぜっく -せっけん -せっこつ -せっさたくま -せつぞく -せつだん -せつでん -せっぱん -せつび -せつぶん -せつめい -せつりつ -せなか -せのび -せはば -せびろ -せぼね -せまい -せまる -せめる -せもたれ -せりふ -ぜんあく -せんい -せんえい -せんか -せんきょ -せんく -せんげん -ぜんご -せんさい -せんしゅ -せんすい -せんせい -せんぞ -せんたく -せんちょう -せんてい -せんとう -せんぬき -せんねん -せんぱい -ぜんぶ -ぜんぽう -せんむ -せんめんじょ -せんもん -せんやく -せんゆう -せんよう -ぜんら -ぜんりゃく -せんれい -せんろ -そあく -そいとげる -そいね -そうがんきょう -そうき -そうご -そうしん -そうだん -そうなん -そうび -そうめん -そうり -そえもの -そえん -そがい -そげき -そこう -そこそこ -そざい -そしな -そせい -そせん -そそぐ -そだてる -そつう -そつえん -そっかん -そつぎょう -そっけつ -そっこう -そっせん -そっと -そとがわ -そとづら -そなえる -そなた -そふぼ -そぼく -そぼろ -そまつ -そまる -そむく -そむりえ -そめる -そもそも -そよかぜ -そらまめ -そろう -そんかい -そんけい -そんざい -そんしつ -そんぞく -そんちょう -ぞんび -ぞんぶん -そんみん -たあい -たいいん -たいうん -たいえき -たいおう -だいがく -たいき -たいぐう -たいけん -たいこ -たいざい -だいじょうぶ -だいすき -たいせつ -たいそう -だいたい -たいちょう -たいてい -だいどころ -たいない -たいねつ -たいのう -たいはん -だいひょう -たいふう -たいへん -たいほ -たいまつばな -たいみんぐ -たいむ -たいめん -たいやき -たいよう -たいら -たいりょく -たいる -たいわん -たうえ -たえる -たおす -たおる -たおれる -たかい -たかね -たきび -たくさん -たこく -たこやき -たさい -たしざん -だじゃれ -たすける -たずさわる -たそがれ -たたかう -たたく -ただしい -たたみ -たちばな -だっかい -だっきゃく -だっこ -だっしゅつ -だったい -たてる -たとえる -たなばた -たにん -たぬき -たのしみ -たはつ -たぶん -たべる -たぼう -たまご -たまる -だむる -ためいき -ためす -ためる -たもつ -たやすい -たよる -たらす -たりきほんがん -たりょう -たりる -たると -たれる -たれんと -たろっと -たわむれる -だんあつ -たんい -たんおん -たんか -たんき -たんけん -たんご -たんさん -たんじょうび -だんせい -たんそく -たんたい -だんち -たんてい -たんとう -だんな -たんにん -だんねつ -たんのう -たんぴん -だんぼう -たんまつ -たんめい -だんれつ -だんろ -だんわ -ちあい -ちあん -ちいき -ちいさい -ちえん -ちかい -ちから -ちきゅう -ちきん -ちけいず -ちけん -ちこく -ちさい -ちしき -ちしりょう -ちせい -ちそう -ちたい -ちたん -ちちおや -ちつじょ -ちてき -ちてん -ちぬき -ちぬり -ちのう -ちひょう -ちへいせん -ちほう -ちまた -ちみつ -ちみどろ -ちめいど -ちゃんこなべ -ちゅうい -ちゆりょく -ちょうし -ちょさくけん -ちらし -ちらみ -ちりがみ -ちりょう -ちるど -ちわわ -ちんたい -ちんもく -ついか -ついたち -つうか -つうじょう -つうはん -つうわ -つかう -つかれる -つくね -つくる -つけね -つける -つごう -つたえる -つづく -つつじ -つつむ -つとめる -つながる -つなみ -つねづね -つのる -つぶす -つまらない -つまる -つみき -つめたい -つもり -つもる -つよい -つるぼ -つるみく -つわもの -つわり -てあし -てあて -てあみ -ていおん -ていか -ていき -ていけい -ていこく -ていさつ -ていし -ていせい -ていたい -ていど -ていねい -ていひょう -ていへん -ていぼう -てうち -ておくれ -てきとう -てくび -でこぼこ -てさぎょう -てさげ -てすり -てそう -てちがい -てちょう -てつがく -てつづき -でっぱ -てつぼう -てつや -でぬかえ -てぬき -てぬぐい -てのひら -てはい -てぶくろ -てふだ -てほどき -てほん -てまえ -てまきずし -てみじか -てみやげ -てらす -てれび -てわけ -てわたし -でんあつ -てんいん -てんかい -てんき -てんぐ -てんけん -てんごく -てんさい -てんし -てんすう -でんち -てんてき -てんとう -てんない -てんぷら -てんぼうだい -てんめつ -てんらんかい -でんりょく -でんわ -どあい -といれ -どうかん -とうきゅう -どうぐ -とうし -とうむぎ -とおい -とおか -とおく -とおす -とおる -とかい -とかす -ときおり -ときどき -とくい -とくしゅう -とくてん -とくに -とくべつ -とけい -とける -とこや -とさか -としょかん -とそう -とたん -とちゅう -とっきゅう -とっくん -とつぜん -とつにゅう -とどける -ととのえる -とない -となえる -となり -とのさま -とばす -どぶがわ -とほう -とまる -とめる -ともだち -ともる -どようび -とらえる -とんかつ -どんぶり -ないかく -ないこう -ないしょ -ないす -ないせん -ないそう -なおす -ながい -なくす -なげる -なこうど -なさけ -なたでここ -なっとう -なつやすみ -ななおし -なにごと -なにもの -なにわ -なのか -なふだ -なまいき -なまえ -なまみ -なみだ -なめらか -なめる -なやむ -ならう -ならび -ならぶ -なれる -なわとび -なわばり -にあう -にいがた -にうけ -におい -にかい -にがて -にきび -にくしみ -にくまん -にげる -にさんかたんそ -にしき -にせもの -にちじょう -にちようび -にっか -にっき -にっけい -にっこう -にっさん -にっしょく -にっすう -にっせき -にってい -になう -にほん -にまめ -にもつ -にやり -にゅういん -にりんしゃ -にわとり -にんい -にんか -にんき -にんげん -にんしき -にんずう -にんそう -にんたい -にんち -にんてい -にんにく -にんぷ -にんまり -にんむ -にんめい -にんよう -ぬいくぎ -ぬかす -ぬぐいとる -ぬぐう -ぬくもり -ぬすむ -ぬまえび -ぬめり -ぬらす -ぬんちゃく -ねあげ -ねいき -ねいる -ねいろ -ねぐせ -ねくたい -ねくら -ねこぜ -ねこむ -ねさげ -ねすごす -ねそべる -ねだん -ねつい -ねっしん -ねつぞう -ねったいぎょ -ねぶそく -ねふだ -ねぼう -ねほりはほり -ねまき -ねまわし -ねみみ -ねむい -ねむたい -ねもと -ねらう -ねわざ -ねんいり -ねんおし -ねんかん -ねんきん -ねんぐ -ねんざ -ねんし -ねんちゃく -ねんど -ねんぴ -ねんぶつ -ねんまつ -ねんりょう -ねんれい -のいず -のおづま -のがす -のきなみ -のこぎり -のこす -のこる -のせる -のぞく -のぞむ -のたまう -のちほど -のっく -のばす -のはら -のべる -のぼる -のみもの -のやま -のらいぬ -のらねこ -のりもの -のりゆき -のれん -のんき -ばあい -はあく -ばあさん -ばいか -ばいく -はいけん -はいご -はいしん -はいすい -はいせん -はいそう -はいち -ばいばい -はいれつ -はえる -はおる -はかい -ばかり -はかる -はくしゅ -はけん -はこぶ -はさみ -はさん -はしご -ばしょ -はしる -はせる -ぱそこん -はそん -はたん -はちみつ -はつおん -はっかく -はづき -はっきり -はっくつ -はっけん -はっこう -はっさん -はっしん -はったつ -はっちゅう -はってん -はっぴょう -はっぽう -はなす -はなび -はにかむ -はぶらし -はみがき -はむかう -はめつ -はやい -はやし -はらう -はろうぃん -はわい -はんい -はんえい -はんおん -はんかく -はんきょう -ばんぐみ -はんこ -はんしゃ -はんすう -はんだん -ぱんち -ぱんつ -はんてい -はんとし -はんのう -はんぱ -はんぶん -はんぺん -はんぼうき -はんめい -はんらん -はんろん -ひいき -ひうん -ひえる -ひかく -ひかり -ひかる -ひかん -ひくい -ひけつ -ひこうき -ひこく -ひさい -ひさしぶり -ひさん -びじゅつかん -ひしょ -ひそか -ひそむ -ひたむき -ひだり -ひたる -ひつぎ -ひっこし -ひっし -ひつじゅひん -ひっす -ひつぜん -ぴったり -ぴっちり -ひつよう -ひてい -ひとごみ -ひなまつり -ひなん -ひねる -ひはん -ひびく -ひひょう -ひほう -ひまわり -ひまん -ひみつ -ひめい -ひめじし -ひやけ -ひやす -ひよう -びょうき -ひらがな -ひらく -ひりつ -ひりょう -ひるま -ひるやすみ -ひれい -ひろい -ひろう -ひろき -ひろゆき -ひんかく -ひんけつ -ひんこん -ひんしゅ -ひんそう -ぴんち -ひんぱん -びんぼう -ふあん -ふいうち -ふうけい -ふうせん -ぷうたろう -ふうとう -ふうふ -ふえる -ふおん -ふかい -ふきん -ふくざつ -ふくぶくろ -ふこう -ふさい -ふしぎ -ふじみ -ふすま -ふせい -ふせぐ -ふそく -ぶたにく -ふたん -ふちょう -ふつう -ふつか -ふっかつ -ふっき -ふっこく -ぶどう -ふとる -ふとん -ふのう -ふはい -ふひょう -ふへん -ふまん -ふみん -ふめつ -ふめん -ふよう -ふりこ -ふりる -ふるい -ふんいき -ぶんがく -ぶんぐ -ふんしつ -ぶんせき -ふんそう -ぶんぽう -へいあん -へいおん -へいがい -へいき -へいげん -へいこう -へいさ -へいしゃ -へいせつ -へいそ -へいたく -へいてん -へいねつ -へいわ -へきが -へこむ -べにいろ -べにしょうが -へらす -へんかん -べんきょう -べんごし -へんさい -へんたい -べんり -ほあん -ほいく -ぼうぎょ -ほうこく -ほうそう -ほうほう -ほうもん -ほうりつ -ほえる -ほおん -ほかん -ほきょう -ぼきん -ほくろ -ほけつ -ほけん -ほこう -ほこる -ほしい -ほしつ -ほしゅ -ほしょう -ほせい -ほそい -ほそく -ほたて -ほたる -ぽちぶくろ -ほっきょく -ほっさ -ほったん -ほとんど -ほめる -ほんい -ほんき -ほんけ -ほんしつ -ほんやく -まいにち -まかい -まかせる -まがる -まける -まこと -まさつ -まじめ -ますく -まぜる -まつり -まとめ -まなぶ -まぬけ -まねく -まほう -まもる -まゆげ -まよう -まろやか -まわす -まわり -まわる -まんが -まんきつ -まんぞく -まんなか -みいら -みうち -みえる -みがく -みかた -みかん -みけん -みこん -みじかい -みすい -みすえる -みせる -みっか -みつかる -みつける -みてい -みとめる -みなと -みなみかさい -みねらる -みのう -みのがす -みほん -みもと -みやげ -みらい -みりょく -みわく -みんか -みんぞく -むいか -むえき -むえん -むかい -むかう -むかえ -むかし -むぎちゃ -むける -むげん -むさぼる -むしあつい -むしば -むじゅん -むしろ -むすう -むすこ -むすぶ -むすめ -むせる -むせん -むちゅう -むなしい -むのう -むやみ -むよう -むらさき -むりょう -むろん -めいあん -めいうん -めいえん -めいかく -めいきょく -めいさい -めいし -めいそう -めいぶつ -めいれい -めいわく -めぐまれる -めざす -めした -めずらしい -めだつ -めまい -めやす -めんきょ -めんせき -めんどう -もうしあげる -もうどうけん -もえる -もくし -もくてき -もくようび -もちろん -もどる -もらう -もんく -もんだい -やおや -やける -やさい -やさしい -やすい -やすたろう -やすみ -やせる -やそう -やたい -やちん -やっと -やっぱり -やぶる -やめる -ややこしい -やよい -やわらかい -ゆうき -ゆうびんきょく -ゆうべ -ゆうめい -ゆけつ -ゆしゅつ -ゆせん -ゆそう -ゆたか -ゆちゃく -ゆでる -ゆにゅう -ゆびわ -ゆらい -ゆれる -ようい -ようか -ようきゅう -ようじ -ようす -ようちえん -よかぜ -よかん -よきん -よくせい -よくぼう -よけい -よごれる -よさん -よしゅう -よそう -よそく -よっか -よてい -よどがわく -よねつ -よやく -よゆう -よろこぶ -よろしい -らいう -らくがき -らくご -らくさつ -らくだ -らしんばん -らせん -らぞく -らたい -らっか -られつ -りえき -りかい -りきさく -りきせつ -りくぐん -りくつ -りけん -りこう -りせい -りそう -りそく -りてん -りねん -りゆう -りゅうがく -りよう -りょうり -りょかん -りょくちゃ -りょこう -りりく -りれき -りろん -りんご -るいけい -るいさい -るいじ -るいせき -るすばん -るりがわら -れいかん -れいぎ -れいせい -れいぞうこ -れいとう -れいぼう -れきし -れきだい -れんあい -れんけい -れんこん -れんさい -れんしゅう -れんぞく -れんらく -ろうか -ろうご -ろうじん -ろうそく -ろくが -ろこつ -ろじうら -ろしゅつ -ろせん -ろてん -ろめん -ろれつ -ろんぎ -ろんぱ -ろんぶん -ろんり -わかす -わかめ -わかやま -わかれる -わしつ -わじまし -わすれもの -わらう -われる diff --git a/keys/words/wordlist/spanish.txt b/keys/words/wordlist/spanish.txt deleted file mode 100644 index d0900c2c7..000000000 --- a/keys/words/wordlist/spanish.txt +++ /dev/null @@ -1,2048 +0,0 @@ -ábaco -abdomen -abeja -abierto -abogado -abono -aborto -abrazo -abrir -abuelo -abuso -acabar -academia -acceso -acción -aceite -acelga -acento -aceptar -ácido -aclarar -acné -acoger -acoso -activo -acto -actriz -actuar -acudir -acuerdo -acusar -adicto -admitir -adoptar -adorno -aduana -adulto -aéreo -afectar -afición -afinar -afirmar -ágil -agitar -agonía -agosto -agotar -agregar -agrio -agua -agudo -águila -aguja -ahogo -ahorro -aire -aislar -ajedrez -ajeno -ajuste -alacrán -alambre -alarma -alba -álbum -alcalde -aldea -alegre -alejar -alerta -aleta -alfiler -alga -algodón -aliado -aliento -alivio -alma -almeja -almíbar -altar -alteza -altivo -alto -altura -alumno -alzar -amable -amante -amapola -amargo -amasar -ámbar -ámbito -ameno -amigo -amistad -amor -amparo -amplio -ancho -anciano -ancla -andar -andén -anemia -ángulo -anillo -ánimo -anís -anotar -antena -antiguo -antojo -anual -anular -anuncio -añadir -añejo -año -apagar -aparato -apetito -apio -aplicar -apodo -aporte -apoyo -aprender -aprobar -apuesta -apuro -arado -araña -arar -árbitro -árbol -arbusto -archivo -arco -arder -ardilla -arduo -área -árido -aries -armonía -arnés -aroma -arpa -arpón -arreglo -arroz -arruga -arte -artista -asa -asado -asalto -ascenso -asegurar -aseo -asesor -asiento -asilo -asistir -asno -asombro -áspero -astilla -astro -astuto -asumir -asunto -atajo -ataque -atar -atento -ateo -ático -atleta -átomo -atraer -atroz -atún -audaz -audio -auge -aula -aumento -ausente -autor -aval -avance -avaro -ave -avellana -avena -avestruz -avión -aviso -ayer -ayuda -ayuno -azafrán -azar -azote -azúcar -azufre -azul -baba -babor -bache -bahía -baile -bajar -balanza -balcón -balde -bambú -banco -banda -baño -barba -barco -barniz -barro -báscula -bastón -basura -batalla -batería -batir -batuta -baúl -bazar -bebé -bebida -bello -besar -beso -bestia -bicho -bien -bingo -blanco -bloque -blusa -boa -bobina -bobo -boca -bocina -boda -bodega -boina -bola -bolero -bolsa -bomba -bondad -bonito -bono -bonsái -borde -borrar -bosque -bote -botín -bóveda -bozal -bravo -brazo -brecha -breve -brillo -brinco -brisa -broca -broma -bronce -brote -bruja -brusco -bruto -buceo -bucle -bueno -buey -bufanda -bufón -búho -buitre -bulto -burbuja -burla -burro -buscar -butaca -buzón -caballo -cabeza -cabina -cabra -cacao -cadáver -cadena -caer -café -caída -caimán -caja -cajón -cal -calamar -calcio -caldo -calidad -calle -calma -calor -calvo -cama -cambio -camello -camino -campo -cáncer -candil -canela -canguro -canica -canto -caña -cañón -caoba -caos -capaz -capitán -capote -captar -capucha -cara -carbón -cárcel -careta -carga -cariño -carne -carpeta -carro -carta -casa -casco -casero -caspa -castor -catorce -catre -caudal -causa -cazo -cebolla -ceder -cedro -celda -célebre -celoso -célula -cemento -ceniza -centro -cerca -cerdo -cereza -cero -cerrar -certeza -césped -cetro -chacal -chaleco -champú -chancla -chapa -charla -chico -chiste -chivo -choque -choza -chuleta -chupar -ciclón -ciego -cielo -cien -cierto -cifra -cigarro -cima -cinco -cine -cinta -ciprés -circo -ciruela -cisne -cita -ciudad -clamor -clan -claro -clase -clave -cliente -clima -clínica -cobre -cocción -cochino -cocina -coco -código -codo -cofre -coger -cohete -cojín -cojo -cola -colcha -colegio -colgar -colina -collar -colmo -columna -combate -comer -comida -cómodo -compra -conde -conejo -conga -conocer -consejo -contar -copa -copia -corazón -corbata -corcho -cordón -corona -correr -coser -cosmos -costa -cráneo -cráter -crear -crecer -creído -crema -cría -crimen -cripta -crisis -cromo -crónica -croqueta -crudo -cruz -cuadro -cuarto -cuatro -cubo -cubrir -cuchara -cuello -cuento -cuerda -cuesta -cueva -cuidar -culebra -culpa -culto -cumbre -cumplir -cuna -cuneta -cuota -cupón -cúpula -curar -curioso -curso -curva -cutis -dama -danza -dar -dardo -dátil -deber -débil -década -decir -dedo -defensa -definir -dejar -delfín -delgado -delito -demora -denso -dental -deporte -derecho -derrota -desayuno -deseo -desfile -desnudo -destino -desvío -detalle -detener -deuda -día -diablo -diadema -diamante -diana -diario -dibujo -dictar -diente -dieta -diez -difícil -digno -dilema -diluir -dinero -directo -dirigir -disco -diseño -disfraz -diva -divino -doble -doce -dolor -domingo -don -donar -dorado -dormir -dorso -dos -dosis -dragón -droga -ducha -duda -duelo -dueño -dulce -dúo -duque -durar -dureza -duro -ébano -ebrio -echar -eco -ecuador -edad -edición -edificio -editor -educar -efecto -eficaz -eje -ejemplo -elefante -elegir -elemento -elevar -elipse -élite -elixir -elogio -eludir -embudo -emitir -emoción -empate -empeño -empleo -empresa -enano -encargo -enchufe -encía -enemigo -enero -enfado -enfermo -engaño -enigma -enlace -enorme -enredo -ensayo -enseñar -entero -entrar -envase -envío -época -equipo -erizo -escala -escena -escolar -escribir -escudo -esencia -esfera -esfuerzo -espada -espejo -espía -esposa -espuma -esquí -estar -este -estilo -estufa -etapa -eterno -ética -etnia -evadir -evaluar -evento -evitar -exacto -examen -exceso -excusa -exento -exigir -exilio -existir -éxito -experto -explicar -exponer -extremo -fábrica -fábula -fachada -fácil -factor -faena -faja -falda -fallo -falso -faltar -fama -familia -famoso -faraón -farmacia -farol -farsa -fase -fatiga -fauna -favor -fax -febrero -fecha -feliz -feo -feria -feroz -fértil -fervor -festín -fiable -fianza -fiar -fibra -ficción -ficha -fideo -fiebre -fiel -fiera -fiesta -figura -fijar -fijo -fila -filete -filial -filtro -fin -finca -fingir -finito -firma -flaco -flauta -flecha -flor -flota -fluir -flujo -flúor -fobia -foca -fogata -fogón -folio -folleto -fondo -forma -forro -fortuna -forzar -fosa -foto -fracaso -frágil -franja -frase -fraude -freír -freno -fresa -frío -frito -fruta -fuego -fuente -fuerza -fuga -fumar -función -funda -furgón -furia -fusil -fútbol -futuro -gacela -gafas -gaita -gajo -gala -galería -gallo -gamba -ganar -gancho -ganga -ganso -garaje -garza -gasolina -gastar -gato -gavilán -gemelo -gemir -gen -género -genio -gente -geranio -gerente -germen -gesto -gigante -gimnasio -girar -giro -glaciar -globo -gloria -gol -golfo -goloso -golpe -goma -gordo -gorila -gorra -gota -goteo -gozar -grada -gráfico -grano -grasa -gratis -grave -grieta -grillo -gripe -gris -grito -grosor -grúa -grueso -grumo -grupo -guante -guapo -guardia -guerra -guía -guiño -guion -guiso -guitarra -gusano -gustar -haber -hábil -hablar -hacer -hacha -hada -hallar -hamaca -harina -haz -hazaña -hebilla -hebra -hecho -helado -helio -hembra -herir -hermano -héroe -hervir -hielo -hierro -hígado -higiene -hijo -himno -historia -hocico -hogar -hoguera -hoja -hombre -hongo -honor -honra -hora -hormiga -horno -hostil -hoyo -hueco -huelga -huerta -hueso -huevo -huida -huir -humano -húmedo -humilde -humo -hundir -huracán -hurto -icono -ideal -idioma -ídolo -iglesia -iglú -igual -ilegal -ilusión -imagen -imán -imitar -impar -imperio -imponer -impulso -incapaz -índice -inerte -infiel -informe -ingenio -inicio -inmenso -inmune -innato -insecto -instante -interés -íntimo -intuir -inútil -invierno -ira -iris -ironía -isla -islote -jabalí -jabón -jamón -jarabe -jardín -jarra -jaula -jazmín -jefe -jeringa -jinete -jornada -joroba -joven -joya -juerga -jueves -juez -jugador -jugo -juguete -juicio -junco -jungla -junio -juntar -júpiter -jurar -justo -juvenil -juzgar -kilo -koala -labio -lacio -lacra -lado -ladrón -lagarto -lágrima -laguna -laico -lamer -lámina -lámpara -lana -lancha -langosta -lanza -lápiz -largo -larva -lástima -lata -látex -latir -laurel -lavar -lazo -leal -lección -leche -lector -leer -legión -legumbre -lejano -lengua -lento -leña -león -leopardo -lesión -letal -letra -leve -leyenda -libertad -libro -licor -líder -lidiar -lienzo -liga -ligero -lima -límite -limón -limpio -lince -lindo -línea -lingote -lino -linterna -líquido -liso -lista -litera -litio -litro -llaga -llama -llanto -llave -llegar -llenar -llevar -llorar -llover -lluvia -lobo -loción -loco -locura -lógica -logro -lombriz -lomo -lonja -lote -lucha -lucir -lugar -lujo -luna -lunes -lupa -lustro -luto -luz -maceta -macho -madera -madre -maduro -maestro -mafia -magia -mago -maíz -maldad -maleta -malla -malo -mamá -mambo -mamut -manco -mando -manejar -manga -maniquí -manjar -mano -manso -manta -mañana -mapa -máquina -mar -marco -marea -marfil -margen -marido -mármol -marrón -martes -marzo -masa -máscara -masivo -matar -materia -matiz -matriz -máximo -mayor -mazorca -mecha -medalla -medio -médula -mejilla -mejor -melena -melón -memoria -menor -mensaje -mente -menú -mercado -merengue -mérito -mes -mesón -meta -meter -método -metro -mezcla -miedo -miel -miembro -miga -mil -milagro -militar -millón -mimo -mina -minero -mínimo -minuto -miope -mirar -misa -miseria -misil -mismo -mitad -mito -mochila -moción -moda -modelo -moho -mojar -molde -moler -molino -momento -momia -monarca -moneda -monja -monto -moño -morada -morder -moreno -morir -morro -morsa -mortal -mosca -mostrar -motivo -mover -móvil -mozo -mucho -mudar -mueble -muela -muerte -muestra -mugre -mujer -mula -muleta -multa -mundo -muñeca -mural -muro -músculo -museo -musgo -música -muslo -nácar -nación -nadar -naipe -naranja -nariz -narrar -nasal -natal -nativo -natural -náusea -naval -nave -navidad -necio -néctar -negar -negocio -negro -neón -nervio -neto -neutro -nevar -nevera -nicho -nido -niebla -nieto -niñez -niño -nítido -nivel -nobleza -noche -nómina -noria -norma -norte -nota -noticia -novato -novela -novio -nube -nuca -núcleo -nudillo -nudo -nuera -nueve -nuez -nulo -número -nutria -oasis -obeso -obispo -objeto -obra -obrero -observar -obtener -obvio -oca -ocaso -océano -ochenta -ocho -ocio -ocre -octavo -octubre -oculto -ocupar -ocurrir -odiar -odio -odisea -oeste -ofensa -oferta -oficio -ofrecer -ogro -oído -oír -ojo -ola -oleada -olfato -olivo -olla -olmo -olor -olvido -ombligo -onda -onza -opaco -opción -ópera -opinar -oponer -optar -óptica -opuesto -oración -orador -oral -órbita -orca -orden -oreja -órgano -orgía -orgullo -oriente -origen -orilla -oro -orquesta -oruga -osadía -oscuro -osezno -oso -ostra -otoño -otro -oveja -óvulo -óxido -oxígeno -oyente -ozono -pacto -padre -paella -página -pago -país -pájaro -palabra -palco -paleta -pálido -palma -paloma -palpar -pan -panal -pánico -pantera -pañuelo -papá -papel -papilla -paquete -parar -parcela -pared -parir -paro -párpado -parque -párrafo -parte -pasar -paseo -pasión -paso -pasta -pata -patio -patria -pausa -pauta -pavo -payaso -peatón -pecado -pecera -pecho -pedal -pedir -pegar -peine -pelar -peldaño -pelea -peligro -pellejo -pelo -peluca -pena -pensar -peñón -peón -peor -pepino -pequeño -pera -percha -perder -pereza -perfil -perico -perla -permiso -perro -persona -pesa -pesca -pésimo -pestaña -pétalo -petróleo -pez -pezuña -picar -pichón -pie -piedra -pierna -pieza -pijama -pilar -piloto -pimienta -pino -pintor -pinza -piña -piojo -pipa -pirata -pisar -piscina -piso -pista -pitón -pizca -placa -plan -plata -playa -plaza -pleito -pleno -plomo -pluma -plural -pobre -poco -poder -podio -poema -poesía -poeta -polen -policía -pollo -polvo -pomada -pomelo -pomo -pompa -poner -porción -portal -posada -poseer -posible -poste -potencia -potro -pozo -prado -precoz -pregunta -premio -prensa -preso -previo -primo -príncipe -prisión -privar -proa -probar -proceso -producto -proeza -profesor -programa -prole -promesa -pronto -propio -próximo -prueba -público -puchero -pudor -pueblo -puerta -puesto -pulga -pulir -pulmón -pulpo -pulso -puma -punto -puñal -puño -pupa -pupila -puré -quedar -queja -quemar -querer -queso -quieto -química -quince -quitar -rábano -rabia -rabo -ración -radical -raíz -rama -rampa -rancho -rango -rapaz -rápido -rapto -rasgo -raspa -rato -rayo -raza -razón -reacción -realidad -rebaño -rebote -recaer -receta -rechazo -recoger -recreo -recto -recurso -red -redondo -reducir -reflejo -reforma -refrán -refugio -regalo -regir -regla -regreso -rehén -reino -reír -reja -relato -relevo -relieve -relleno -reloj -remar -remedio -remo -rencor -rendir -renta -reparto -repetir -reposo -reptil -res -rescate -resina -respeto -resto -resumen -retiro -retorno -retrato -reunir -revés -revista -rey -rezar -rico -riego -rienda -riesgo -rifa -rígido -rigor -rincón -riñón -río -riqueza -risa -ritmo -rito -rizo -roble -roce -rociar -rodar -rodeo -rodilla -roer -rojizo -rojo -romero -romper -ron -ronco -ronda -ropa -ropero -rosa -rosca -rostro -rotar -rubí -rubor -rudo -rueda -rugir -ruido -ruina -ruleta -rulo -rumbo -rumor -ruptura -ruta -rutina -sábado -saber -sabio -sable -sacar -sagaz -sagrado -sala -saldo -salero -salir -salmón -salón -salsa -salto -salud -salvar -samba -sanción -sandía -sanear -sangre -sanidad -sano -santo -sapo -saque -sardina -sartén -sastre -satán -sauna -saxofón -sección -seco -secreto -secta -sed -seguir -seis -sello -selva -semana -semilla -senda -sensor -señal -señor -separar -sepia -sequía -ser -serie -sermón -servir -sesenta -sesión -seta -setenta -severo -sexo -sexto -sidra -siesta -siete -siglo -signo -sílaba -silbar -silencio -silla -símbolo -simio -sirena -sistema -sitio -situar -sobre -socio -sodio -sol -solapa -soldado -soledad -sólido -soltar -solución -sombra -sondeo -sonido -sonoro -sonrisa -sopa -soplar -soporte -sordo -sorpresa -sorteo -sostén -sótano -suave -subir -suceso -sudor -suegra -suelo -sueño -suerte -sufrir -sujeto -sultán -sumar -superar -suplir -suponer -supremo -sur -surco -sureño -surgir -susto -sutil -tabaco -tabique -tabla -tabú -taco -tacto -tajo -talar -talco -talento -talla -talón -tamaño -tambor -tango -tanque -tapa -tapete -tapia -tapón -taquilla -tarde -tarea -tarifa -tarjeta -tarot -tarro -tarta -tatuaje -tauro -taza -tazón -teatro -techo -tecla -técnica -tejado -tejer -tejido -tela -teléfono -tema -temor -templo -tenaz -tender -tener -tenis -tenso -teoría -terapia -terco -término -ternura -terror -tesis -tesoro -testigo -tetera -texto -tez -tibio -tiburón -tiempo -tienda -tierra -tieso -tigre -tijera -tilde -timbre -tímido -timo -tinta -tío -típico -tipo -tira -tirón -titán -títere -título -tiza -toalla -tobillo -tocar -tocino -todo -toga -toldo -tomar -tono -tonto -topar -tope -toque -tórax -torero -tormenta -torneo -toro -torpedo -torre -torso -tortuga -tos -tosco -toser -tóxico -trabajo -tractor -traer -tráfico -trago -traje -tramo -trance -trato -trauma -trazar -trébol -tregua -treinta -tren -trepar -tres -tribu -trigo -tripa -triste -triunfo -trofeo -trompa -tronco -tropa -trote -trozo -truco -trueno -trufa -tubería -tubo -tuerto -tumba -tumor -túnel -túnica -turbina -turismo -turno -tutor -ubicar -úlcera -umbral -unidad -unir -universo -uno -untar -uña -urbano -urbe -urgente -urna -usar -usuario -útil -utopía -uva -vaca -vacío -vacuna -vagar -vago -vaina -vajilla -vale -válido -valle -valor -válvula -vampiro -vara -variar -varón -vaso -vecino -vector -vehículo -veinte -vejez -vela -velero -veloz -vena -vencer -venda -veneno -vengar -venir -venta -venus -ver -verano -verbo -verde -vereda -verja -verso -verter -vía -viaje -vibrar -vicio -víctima -vida -vídeo -vidrio -viejo -viernes -vigor -vil -villa -vinagre -vino -viñedo -violín -viral -virgo -virtud -visor -víspera -vista -vitamina -viudo -vivaz -vivero -vivir -vivo -volcán -volumen -volver -voraz -votar -voto -voz -vuelo -vulgar -yacer -yate -yegua -yema -yerno -yeso -yodo -yoga -yogur -zafiro -zanja -zapato -zarza -zona -zorro -zumo -zurdo diff --git a/keys/words/wordlist/wordlist.go b/keys/words/wordlist/wordlist.go deleted file mode 100644 index 9ffbb1539..000000000 --- a/keys/words/wordlist/wordlist.go +++ /dev/null @@ -1,310 +0,0 @@ -// Code generated by go-bindata. -// sources: -// keys/words/wordlist/chinese_simplified.txt -// keys/words/wordlist/english.txt -// keys/words/wordlist/japanese.txt -// keys/words/wordlist/spanish.txt -// DO NOT EDIT! - -package wordlist - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _keysWordsWordlistChinese_simplifiedTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x1c\x97\x55\x76\xeb\x30\x14\x45\xff\xf7\xa8\xc3\xcc\x49\xc3\x69\x98\xda\x86\xd9\x0e\x4c\xc6\xf7\x4a\x9a\xc5\x5b\x7e\x7f\x5d\x5d\x6d\x6c\x45\x07\xf6\x31\xdd\x04\xc1\x3d\x82\xb6\x77\x48\x7f\x45\x70\x2f\x12\x78\x29\xb4\x9f\x45\x6a\x05\x02\xcf\xc3\x7e\x3a\x04\xf7\x0d\x32\x5b\x12\xdc\x3d\x82\x7b\x8e\xe0\xfe\x83\xf4\x5e\x68\xa6\x4a\xe0\xcf\xb1\x8b\x28\x81\xdf\x44\x5b\x57\x74\x30\xc7\x34\x56\x04\xfe\x1f\xa6\x31\x44\x32\x7b\x82\x57\x1f\xe9\xef\x09\xbc\x12\x92\xf6\x90\xfd\x01\xc9\xa4\x90\xdd\x03\xcd\x54\x08\x9e\x5d\xa4\xbc\x23\xb8\xfb\x48\xb9\x8a\x3c\xce\x48\x6e\x85\x54\x0a\xc8\x6d\x4e\xf0\x18\x62\xe3\x2f\x82\x7b\x1e\xfb\x49\x23\x9b\x0a\x76\x77\x26\xf0\x96\x98\x65\x11\x37\x98\x60\x23\x05\xb4\xf9\x40\x2a\x25\x64\xd6\x45\xb6\x5d\xec\xb8\x80\x6c\x16\xe8\xe9\x0b\xcd\x46\xd0\x7d\x15\x79\xb7\x30\x7e\x19\x29\x46\x09\xee\x59\x82\x47\xf8\x99\x3d\xcc\x20\x82\xd9\x64\x71\xf1\x15\xe2\x2d\x90\xed\x15\xd3\xb8\x20\xb9\x1e\x2e\x5d\x40\x16\x31\x74\x7f\x46\x0a\x4d\xdc\x6f\x1b\x9b\xfe\x21\xf0\x0a\x98\x4a\x0a\x7b\xb9\x21\xfb\x32\x26\xbb\xc6\x94\xf6\xc8\xf6\x1b\xc9\x8d\x70\xe9\x32\xee\xff\x7b\xcf\x08\x5e\x75\x24\x73\x45\xfb\x1e\xf2\xaa\x13\xbc\x3e\x98\xd8\x83\xc0\x2f\x11\xdc\xbb\x68\xff\x0f\x29\xf9\x68\x2e\x87\x46\x96\xc8\xfc\x85\x78\x0d\xe4\x19\x41\xb6\x71\xa4\x92\xc1\x7e\xda\x48\x6f\x84\x69\x1c\x90\xe4\x95\xc0\xeb\x61\x12\x57\x24\x5b\x44\x66\x4d\x64\xb6\x46\x1b\x1f\xa4\xd7\x43\x5b\x73\x5c\x6c\x8a\x99\xbd\x09\x1e\x59\x02\x2f\x8f\x3c\x4e\xc8\x6b\x82\xe9\xdd\x91\xe4\x0a\x3b\x5e\xe1\x5a\x67\x74\x74\x23\xb8\x97\x90\xe4\x09\xa9\x24\x70\xe9\x22\xda\xdc\x63\xbc\x0f\x92\x4a\xa2\x5f\x7b\x74\x33\x45\x3e\x71\xa4\x5c\x24\x78\x8d\xd0\x76\x09\xd3\xcf\x23\xa5\x21\x52\xce\x10\x3c\x32\x48\x66\x8d\xee\x1a\x68\xa6\x49\xf0\x4a\x61\xcf\x2b\x74\xdf\xc0\xfc\xfd\x21\x95\x2a\x2e\x5a\x47\xaa\x2f\x74\x33\x43\xca\x6d\x74\x30\x46\xca\x3f\xe8\x71\x8c\xf1\xeb\xd8\xe5\x14\xd7\xda\xa2\x89\x32\xe2\x7b\x68\x3f\x83\x24\xff\xd0\xd6\x08\x73\xf2\x91\x54\x0f\x79\x67\xd0\x78\x12\x1b\x49\xa2\xfd\x08\xe6\x37\x4f\xe0\x4f\xd1\xf8\x09\xb9\x1d\x71\x91\x2e\xf2\xb8\xa2\xe5\x0a\xa6\x77\xc6\x4d\xda\x48\xb2\x8b\x59\xe5\x91\xc3\x17\x81\xd7\x40\xbf\xfb\x68\xb3\x83\x3d\x8c\x91\x6a\x1b\x37\x58\x13\xbc\x8a\x48\x72\x8e\xdc\xef\x68\x33\x8d\x46\x7c\xf4\x6f\x8c\xd4\xa3\xc8\xb3\x8c\x9e\x7d\xec\xf6\x8d\x94\x73\x98\xed\x18\x93\x0d\xef\xee\x8a\xfb\xfa\xa0\x87\x18\x36\x12\x45\x66\x67\x64\xe8\x61\x2f\x09\xec\xfb\x81\x5e\xa2\xd8\xdb\x0e\xe3\x2d\x91\x50\x7b\xbd\x37\x72\x38\x60\xfc\x21\x5a\x9a\x63\x86\x73\xec\x3b\x8e\xec\x53\x18\x3f\x81\x5d\x46\xb1\xdb\x31\x92\xf9\x45\xe6\x0f\x34\x9b\xc7\x2e\x6b\x68\x7f\x88\x8e\x1e\xd8\x6d\xe8\xc7\x0a\x92\xea\xa3\x85\x34\x92\x1e\x11\x3c\x06\x48\xc1\x43\x9e\x1e\xda\x78\x23\xa9\x13\x76\xfe\xc1\x4e\x7e\x91\xc7\x11\x89\x76\x91\x4f\x12\xcd\x84\xdf\x43\x06\xe9\x7d\x23\x99\x0e\x81\x1f\x7a\xad\x89\x16\xb7\xc8\x2c\x81\x6b\x0f\x91\x62\xe8\x8d\x0e\x36\x7b\x44\x92\x59\x5c\x6b\x85\x14\x4f\x04\x9f\x01\x7a\xf4\x91\x42\x0b\x17\x19\x61\x3a\x6f\xec\x32\x81\x89\x6f\x70\x93\x14\xc1\x3d\x8e\x86\x1e\x28\x4f\x09\xee\x7d\x64\xf7\x44\x3a\x2b\xa4\x94\x47\x3e\x2d\x82\x7b\x13\x97\xae\x22\x93\x6f\x02\x2f\x8b\x5e\x4a\xb8\xf6\x15\x3d\x3e\xd0\xc8\x00\xed\xef\xd0\xef\x28\x81\x17\xea\xa2\x85\x8d\x36\x08\xfc\x08\x76\x3b\x43\x92\x1b\x24\x79\x40\x07\x71\xb4\x71\xc5\xee\xa2\x68\xe3\x81\xde\x93\x98\x77\x09\x49\x15\x71\xe9\x34\xf6\xf5\x87\xf6\xce\x48\xf1\x0b\x37\x2d\x21\x99\x34\x9a\xad\x63\x3a\x2f\xf4\xab\x83\x8b\x0c\xb1\xb9\x03\x72\x0f\xbd\x9d\x45\xfa\x1e\xd6\xfb\xc5\xbe\x16\x04\xef\x3c\xa6\x3f\x44\x72\x63\x24\x19\x7a\x21\x8d\xee\xca\x98\xde\x16\x9b\x3e\x61\xdf\x6f\xec\x65\x8f\x59\xee\x30\x33\x0f\xbb\xdd\x22\xd3\x3d\x9a\x9b\xa3\xcd\x16\xb2\x2d\x60\x0e\x3e\x92\xfc\xc5\x2c\x7c\xa4\x58\x42\x2a\x45\xcc\x78\x8b\x66\x8b\x98\x65\x15\x79\x8e\x08\x3e\x63\xdc\xfa\x0f\x9b\x8b\x61\x77\x03\xcc\xe1\x84\x7e\x9d\x31\x6b\x0f\x49\xc6\x91\xd4\x85\xc0\xcf\xe1\x7a\x29\xf4\xbe\x26\x78\x8e\x90\xfe\x10\xbb\xbd\xa3\x9b\x39\xe6\x3d\x43\x1e\x1f\xcc\xf0\x84\xdd\xee\x71\xfd\x08\xba\xbd\x60\x46\x0d\xcc\x57\x01\xcd\x67\xd1\xef\x16\xf2\xce\x23\xe5\x5f\x82\x7b\x03\xb3\xbe\x62\x97\x31\xec\x35\x87\xf1\xd3\xd8\x69\x12\x79\x1d\x30\xdb\x16\xc1\xab\x84\x16\xa2\xb8\xe1\x89\xe0\xd9\x22\x78\x2c\x90\x7b\x1c\x99\x15\x91\xed\x03\x49\x7c\x70\x63\x1f\xd7\x49\x22\x5f\x29\xdc\xe0\x1b\xf7\x53\xc0\x7e\xbe\xd1\xe6\x06\xbd\x1d\x70\xdd\x37\xf6\x53\xc5\x0c\x3f\x48\x31\x8e\x54\x57\xc8\xb2\x81\x39\x8f\xd0\x5c\x04\x99\xa5\x91\x62\x0e\xc9\x7d\xe3\x06\x35\x4c\x3f\x8a\x64\xc2\x67\x8d\x90\x7a\x11\xe3\x2d\xd0\xc6\x0e\x9b\xf9\x43\xca\x47\x34\x11\xde\xc3\x89\xe0\x1d\xe6\xd8\x04\x79\x47\x70\xc9\x3b\x52\x4a\x21\xf7\x18\x92\xcc\x13\xbc\xbe\x70\x9d\x19\x7a\xcd\xa0\xdf\x09\xc4\xeb\x63\x96\x7b\x64\xf6\x83\xa4\x53\x98\xe3\x1b\x89\x3c\x91\xf2\x0d\x53\x4a\xa3\xad\x32\xc6\x3f\x23\x99\x1a\x2e\x92\x45\x47\x69\x24\xd5\x41\x36\x6d\x24\xd2\x41\x77\x3d\x02\xef\x88\x7c\x7e\xd1\xaf\x0c\xda\xdc\xe1\x3a\x13\x74\x38\x47\x0f\x43\xe4\x3b\xd4\xc7\x13\x53\xca\xa3\x85\xf0\xff\x9f\x48\xd2\x47\xdb\x75\xcc\x6b\x8b\x9e\x43\x5f\xc7\x30\xd9\x34\xb2\xcc\x23\xc5\x33\xc1\xbd\x8e\xc9\x5d\xb1\xb1\x23\x52\x8a\x11\x78\x7f\xd8\x5d\x0a\x17\x89\x21\x87\x6f\xa4\x9f\x42\x0a\x49\x4c\xf4\x97\xe0\x55\xc6\xee\xe3\xa8\x3f\x46\x4a\x1f\xe4\x10\xc1\x24\x97\x48\x39\x86\xf1\x26\x18\x3f\x85\x3c\xbf\x90\x4a\xf8\x19\x73\x5c\x3d\xec\xdb\x50\xa7\x73\xdc\xa2\x89\x78\x5f\xe8\xf5\x88\x6c\xdb\xc8\xfb\x86\xeb\x96\x31\xad\x24\x36\x5f\x46\x66\x07\x64\xdf\x40\x37\x61\x7e\x1d\x71\xc9\x22\x32\x3f\xe1\xfc\x04\x5a\x5a\xa1\xed\x37\x76\x9f\xc1\xbc\x7e\x30\xf3\x6f\x6c\xd6\x43\xaa\x13\x24\xec\xfc\xca\x2f\xc1\x33\x8a\xf6\x7b\xc8\x2e\x85\x66\x1f\xd8\xca\x1c\x37\x7e\xe0\xda\x47\x82\xfb\x1b\x53\x89\x63\xf3\x07\x74\xbf\x44\x72\x1f\xa4\x9a\x43\x07\x25\xa4\xbc\xc7\x56\x5e\x68\x7f\x85\xdc\xb7\xd8\xd7\x16\x33\x0a\x3b\xbb\x8b\xdc\xc3\x1c\x3a\xa3\xa7\x15\xf6\xd3\x47\x36\x2d\x74\x50\x41\x4b\x35\x82\x77\x0f\x3d\x9e\xd0\x30\x4f\xf7\x51\xa4\xbc\x40\x9b\x2f\x24\x5d\x46\x47\x55\xd4\xbb\xa2\x91\x12\xba\x99\xa0\xe3\x0c\x76\x15\x41\xa6\xbf\xc8\x20\x8d\x6e\x16\x48\xcf\x43\xca\x57\xdc\xe1\x89\x9e\x26\xd8\x65\x8a\xc0\x4f\x62\xcf\x0f\xcc\x79\x89\xc9\x1c\x90\xdb\x02\xf3\x3b\x42\x5b\x6b\xb4\x3f\x40\xb6\x27\x8c\xbf\xc1\xbe\x7c\xb4\x5f\xc4\xee\xc2\x0c\x19\x22\xc9\x24\x92\xbc\xa0\x5e\x05\xc9\xcc\xd0\x5c\x98\x4f\x77\xec\xf5\x84\x0e\x2b\x18\x3f\x8e\xdc\xc2\x8c\x38\xa3\x83\x0f\xa6\xb1\xc7\x75\x8a\x38\xbf\x8a\xc9\xed\xb0\xe7\x21\x92\xf6\xb1\x85\x38\xc6\x5f\x22\xc9\x33\xc1\xf3\x49\xf0\xea\x20\x83\x2e\xda\x3b\x62\xdf\x75\x82\xcf\x16\xfd\x4a\x22\xc3\x90\x5d\x7e\x91\xd9\x10\x17\x89\x62\xfe\x1a\xd8\xcc\x03\x29\x8e\x90\xf2\x09\x7b\x9e\x20\x95\x38\xb2\x2b\xa0\xed\x39\x36\x5a\xc0\x2e\xb3\xe8\x21\x8b\x69\xf8\x48\x6e\x88\xdc\xce\xd8\xdb\x10\x1b\xe6\xde\x20\x86\x9b\x7e\xa3\xd3\x08\x52\xb9\x23\xb9\x35\x52\x4c\xe3\xda\x27\x02\xaf\x86\x64\x06\x48\xa6\x87\xe6\x5a\xd8\x48\x1c\xcd\x7d\x21\x83\x32\x66\xd3\x44\xca\x33\xe4\x9d\x40\x8b\x13\xb4\xff\x83\xbd\x55\x31\x61\x8e\xd6\x26\x68\xef\x8d\xf9\x0d\xcf\x37\xc5\xfc\x76\x30\xdb\x08\xf6\xb3\xc7\xd5\x0e\x48\x76\x87\xec\x5f\xc8\x7d\x80\xec\x13\xd8\x62\x16\x49\x1d\xd1\xec\x07\x93\xff\x23\xf0\x67\xb8\x4e\x05\xd7\xfe\x20\xdb\x29\xa6\xb4\x43\xca\x05\xec\xee\x86\xbd\x26\x91\xf7\x16\xbb\x5d\xa3\xa5\x25\x72\x0b\xf5\xb8\xc3\xbe\xce\x68\xf6\x8d\x54\x16\x18\xef\x07\xd3\xcb\x11\xbc\x07\x04\xcf\x36\x6e\x7c\xc5\x8c\x23\xd8\xd7\x0b\x89\xd4\xd0\xcc\x07\xf3\x13\x45\x06\x15\xcc\x31\x8b\x7e\x15\x30\x5f\x73\x64\x3b\xc1\x4e\xa2\x48\xea\x86\x8d\xf7\x31\xfe\x00\xfd\xae\x20\x83\x16\x92\x8d\xa1\x97\x3c\x41\xf8\xce\xc5\x32\x76\x97\x45\x3e\x17\x5c\x27\x43\xe0\x17\x31\xaf\x16\xa6\x57\x41\xca\x79\xf4\x9c\xc7\x35\x3a\xd8\xfc\x02\x99\xf5\x91\x4c\x15\xb3\xf4\x71\x93\x2a\x2e\x52\xc1\x0d\x46\xe8\xed\x86\xee\x8a\x98\xe1\x06\xd3\xdd\x62\xfc\x0c\x36\xda\x45\x0f\xe1\x9d\x54\x09\xbc\x2a\x52\xff\x41\x5b\x13\xec\x2d\x7c\xe6\x2f\x12\xed\x63\xe2\x19\x64\xb6\x45\x76\x43\x4c\x7c\x89\xfd\x24\x91\x49\xe8\xaf\x39\x52\xdc\xa3\xe7\x23\x92\xf1\xd1\xfc\x1f\xfa\x89\x20\x9b\x06\x5a\xf9\xc6\x34\x42\xde\x0d\xef\x2b\x89\x8e\xee\xe8\x68\x8c\x7e\x4d\x09\xde\x17\xa4\xb2\xc4\x34\x8e\xe8\xfd\x4e\xf0\x48\x62\xcb\x7d\xa4\x7a\x42\x5b\x4b\x74\x35\x46\x1f\x4d\xec\x79\x89\x16\x87\xb8\x49\xc8\x01\x3e\xba\xfb\x45\x3b\x5b\xcc\xea\x44\xf0\xe8\x20\x8b\x0c\x3a\x2b\xa2\xd1\x1d\x9a\x5d\xe3\xea\x61\x0f\x6f\xd0\xc2\x1c\x97\xac\x21\xdb\x0c\x9a\xff\x20\x5e\x19\xe3\xdd\x91\x82\x8f\x79\x7a\xb8\x5e\xc8\xf0\x2d\x5c\x2d\x64\xc3\x36\xf2\x15\xb2\xed\x1c\x69\x1c\xb0\xbb\x1d\x76\xbb\x41\x13\xa1\x0e\xc6\xb8\x4e\x02\x5b\xba\x61\x0b\x57\xdc\xb1\x8f\x39\x6e\xd1\xe6\x0c\xd9\xac\xb1\x89\x03\x66\xfc\x8b\x8d\xcd\x91\x66\x02\xf7\xee\xa0\xcf\x06\x26\xe4\xe9\x7b\x05\x3b\x8e\xa0\x7f\x13\x74\xb2\x47\x4b\x05\x74\x53\x40\x8f\x1d\x24\xd3\x45\x1b\x3e\x76\x5f\xc7\xf4\xde\xd8\xed\x0a\xed\x74\x31\xc7\x1a\xc1\xe3\x80\x49\xc7\x31\xc3\x1e\xc1\xa3\x84\x0e\x22\xd8\xe2\x0e\xd9\x46\x71\xc7\x28\xf6\x7c\xc1\xd5\x86\x98\xe4\x0c\xbb\xf3\x31\xe5\x0d\xc1\x73\x87\x5b\x84\xec\x14\x6e\x86\x5f\xa4\x3c\x27\xb8\xef\x91\xe1\x03\x2d\x87\xec\xb0\x47\xf3\x49\xe4\xb9\xc0\xf6\xf2\xe8\x31\x8b\x44\xd3\x98\xf5\x07\xcd\x2e\x31\x9b\x06\xc1\xa3\x82\xdd\x47\x71\x63\x0f\x13\x1f\x62\x9e\x6b\xe4\x1d\xc5\x26\xee\x48\xb3\x8f\x0e\xde\xd8\x44\x17\xe9\xed\x91\x67\xd8\x77\x45\x6c\x3c\xf4\xfb\x10\xb3\x28\x13\x3c\xf6\xe8\xb0\x4e\x10\x66\x7e\xb8\x49\x92\x13\x34\xf2\x85\x99\x46\x91\x48\x11\x33\x6f\x62\xba\x69\x82\x4f\x1c\x37\xe8\x60\xc7\x73\xec\x2e\x81\xf9\xf8\xd8\x58\x16\x7b\xbb\x20\xfb\x27\x76\x3c\x45\xb6\x2f\x34\xfb\x87\x4e\xb3\xc8\xbd\x40\xf0\x9c\xa1\xf5\x22\xf2\x1d\xc3\x84\x3d\xb6\xed\xa3\xfb\x09\x32\x6f\x61\x06\x53\xb4\x10\x72\x5a\xb8\x3b\xb6\x68\xff\x17\xd9\xfe\x20\x5e\x0a\xf3\x6c\x62\xb2\x3d\xec\x72\x81\xb6\x47\xb8\xde\x0d\xd7\x88\x60\x77\x2d\x24\x64\xdf\x43\x12\xcd\xd5\xb1\xd3\x18\x36\xfe\x8d\x54\x9f\xc8\xaa\x8d\x76\x76\xc8\x2a\x8a\xf1\x3f\x68\xe7\x8a\x94\xba\x98\xde\x10\x3b\x1e\xe3\xee\x63\x64\xd3\x41\xfc\x2b\x52\x3c\x60\xe3\x57\xe4\x90\x27\x78\x8c\x09\xee\x67\x5c\x27\x85\x1b\xbf\xd1\x52\x16\xa9\x46\x30\xd1\x1d\x72\x8c\xa2\xa5\x1f\x74\x30\xc4\x46\x2a\x48\xf8\x9d\x97\xb2\xd8\xcb\x05\x7b\x3b\x21\xf5\x39\xb2\x99\x62\x77\x6f\x24\xbd\xc3\xc6\xc7\xb8\xc9\x00\xfd\x7b\x63\xfc\x22\x52\xbc\xe1\x5e\xe1\x1e\x1d\x62\x6b\x77\x74\xdb\x44\xf7\x77\x64\xdb\xc2\xe6\x5b\xc8\x6d\x80\x89\x65\x91\xe3\x1a\x79\x1e\x70\xbd\x70\xef\xae\x90\x79\x19\x3d\x7e\x70\xfd\x23\x3a\x48\xa1\xa5\x09\xea\x57\x71\x5f\x69\xdc\x7c\x83\x5e\xea\xd8\xcc\x0f\x1a\x89\x60\x2f\x57\xc4\xab\x23\x33\x8f\xe0\x99\xc3\x44\x2f\x98\x55\x09\x17\x69\x60\xa2\x1b\xec\xa5\x87\xbc\x6a\x48\xf9\x0f\xf7\xac\xa3\xb5\x0d\xa6\xd7\xc6\x4e\xa3\xb8\xce\x1a\xf1\x6e\x48\x63\x87\xbc\xbe\xb0\xe5\x02\xc6\xdb\x21\x91\x21\xe6\xd4\xc4\xf4\x9a\xe8\xea\x07\xf3\xb7\xc0\x2c\xa3\x48\xee\x07\x19\xc5\x90\xe1\x10\xfd\xfe\x41\xaf\x0b\xe4\x91\x44\xea\x19\xcc\xef\x10\x93\x0a\x7b\xe2\x17\x3d\xbd\xb0\x89\x2a\x32\x9d\x61\x26\x27\xf4\x6f\x89\x8b\x16\x09\xde\x4b\x64\xb7\x42\xbf\x26\xc8\xcb\xc7\x76\xaa\x68\xb3\x8f\x6d\x86\xcc\xb5\xc1\x78\x27\xe4\xf9\xc0\xcd\x8f\x04\xcf\x3b\x9a\x6b\xe3\x42\x9e\x7b\x7c\xd0\x6e\x0b\x5b\xbc\x61\xea\x0b\x64\xfc\x8d\x78\x39\xcc\xa6\x8a\x46\xaf\x68\xe6\x86\xdd\x7e\x90\x71\x03\x99\xa7\x71\x91\x32\x1a\x66\x73\x26\x82\xb6\x42\x6f\x85\x9d\x37\x46\xf7\x3b\x5c\x34\x4d\xe0\xbf\xd0\x5d\x0d\x3d\xcd\x71\x91\x08\x7a\x6e\xa1\xd5\x14\x26\xba\x47\x5e\x61\xa7\x35\xb1\x91\x16\x32\x2b\xa3\xf9\x35\xf2\xe9\xe0\xea\x7d\x4c\x61\x8b\x19\xff\x11\x78\x19\xcc\x23\x8a\xf4\x33\xb8\x5e\xc8\x88\x2f\x82\xf0\x3d\x73\x2f\xcc\x2e\xec\xc3\x0b\xae\x1d\x32\x5b\xc8\x1c\xe1\xc6\x7a\x21\xa3\x14\xae\x97\xc0\x7e\x4a\xe8\xa9\x87\xc9\xdc\xd1\xf9\x13\x17\xfd\x60\xf7\x79\xa4\xb2\xc2\xa5\x4b\x98\x42\x98\xe3\x2d\xcc\x79\x87\x44\xcb\x48\xf2\x8e\x5b\xa4\x30\xe7\x09\x66\xb9\xc0\x26\x62\x68\xc8\x3e\xe1\x99\x0f\x29\xe4\x13\x7a\xae\x8d\xc6\x73\xc8\x38\xdc\xc4\x2d\x34\x91\x41\xfb\x07\xb4\xf7\xc1\x78\x33\xcc\xb1\x85\x44\xde\xc8\xbe\x8b\x69\xf5\xd0\x79\x17\xfb\xdf\x87\x79\xec\x79\x83\x99\x86\xb9\xda\x43\x0f\x21\xc3\x44\x31\x93\x12\xee\x67\x85\xe9\x55\xd1\xe2\x17\xf2\x1c\xa2\xdd\x33\x92\x3d\x62\xcf\x3b\x74\x9b\xc3\xa5\x73\xd8\x5d\x91\xc0\x1b\x23\xa1\x96\xc6\x61\xee\x86\xdd\x93\x41\xf6\x6d\x5c\xcb\x47\xcb\x1b\x4c\x6c\x8b\x6e\xf3\x48\xea\x0f\x1d\xcf\x91\x45\x1a\xbb\x59\x60\xfc\x27\x9a\xef\x21\x95\x33\x81\xdf\x46\x2f\x5b\x5c\x74\x83\xbc\x2b\x68\x6c\x85\x56\xd3\xd8\xfd\x0d\x7b\xf9\xc6\x6c\xc3\x5d\xd0\xc0\x6e\x27\x98\xc6\x0d\xa9\x3c\x90\x5e\xa8\x97\x50\xbb\x15\xec\x39\xec\xe3\x3c\xa6\xe4\x23\xb7\x15\x36\x12\x72\xc7\x02\x5b\x0c\xf7\xff\x06\x7d\xbc\x71\x8d\x2d\x92\x0e\xf7\x92\x8f\x6b\x24\xd1\xaf\x50\x3b\x6b\x24\x3b\x47\xd2\x03\xcc\xe4\x80\x7b\x7d\xd0\xcc\x0f\x26\xf6\xc4\x79\x3e\xc6\xf3\x30\x8b\x28\xe2\x0d\x31\xbd\x1e\x26\x9b\xc1\x3c\xeb\x48\x3a\x82\x19\xf4\xd0\x76\x01\x59\x77\xd1\x6b\x16\xb3\xa9\x21\xed\x33\x5a\xae\x21\xc7\x3b\xda\x0f\xb3\x2a\x81\x1d\xb7\xb0\xad\x32\xb2\xac\x62\xcf\x77\x6c\xb2\x82\xcc\xcf\xc8\xd7\x02\x8d\xef\x08\x1e\x6d\x82\x67\x07\x8d\x4e\x90\x42\x04\xe3\x1d\xd0\x6c\x09\xfb\x5e\x63\x23\x27\xe4\xf5\x83\x4d\x4f\x09\xbc\x0f\xa6\x16\x32\xd5\x05\x9b\xc8\x62\x96\x11\x6c\x65\x45\xf0\x49\x60\x5e\x55\x6c\x26\xf4\x44\x0b\x69\xde\x30\xde\x05\xd9\xdd\xd1\x43\x0b\x2d\xc4\xd0\xf3\x0f\xf6\xec\xe1\x5a\x3f\xe8\xf0\x0f\x93\x49\x61\xe2\x3b\xf4\x3c\xc7\xac\x7c\x64\xd2\xc1\xbe\x76\x48\x3e\x8d\xc4\xcb\xa8\xdf\x45\x4a\x6d\x6c\xad\x83\xcd\x9d\xb0\xb1\x1d\x32\x18\xa3\xc3\x03\xb6\x38\xc6\x26\x3f\x04\x7e\xa8\xd3\x24\xb2\x7f\x63\x5f\x4b\x24\xb5\xc7\x9e\xc7\x98\x8e\x8f\xf3\x4b\x48\x36\x87\xab\xf9\x48\x3e\xdc\x48\x71\x5c\x37\xcc\xfe\x15\x2e\xbe\x41\x4e\x7b\xe4\x1e\x45\xef\x3b\x82\x67\x19\xfb\x5a\x11\x78\x6b\x74\xf7\x85\xd6\x17\xd8\xd2\x2f\x92\xf1\xd0\xcb\x0f\x66\xd9\x46\xcb\x67\x74\xf4\x83\x44\xc3\xae\xdf\x62\x63\x63\xe4\xd8\xc3\x34\xda\xe8\x69\x8c\x19\x8c\x31\xbf\xe1\x8e\x09\xcf\x3c\xc3\xb5\x23\x04\xcf\x2a\x7a\x48\x63\x33\x45\x4c\x98\xdb\xfe\x17\x26\x76\x47\xea\x47\xcc\xf4\x86\xf1\x43\x56\xcf\xa3\xb7\x31\xb2\x6f\x22\x95\x70\xa3\xdd\xd0\xe1\x19\xa9\x66\x90\x77\x0d\x37\xe9\xa3\xa7\x1f\xcc\xaa\x88\x7c\xc2\x67\x5d\xb0\xf5\x01\x9a\x6f\xa2\xe7\x6f\xb4\x94\xc1\x7d\xf5\xb1\xef\x1e\x32\xdd\xe2\x1a\xa1\x9f\x7e\xb1\x9d\x2e\xf2\xdc\xa1\xd5\x35\x1a\x9e\xf5\xf1\x44\xfc\x1b\xb2\xcf\x61\x7e\x5a\x98\x70\x1b\x3e\x13\xb8\xee\x15\xd3\xac\xa2\xfb\x32\xb2\xfd\x45\x96\x15\x5c\x3f\x8d\xa9\x7e\xa3\x91\x1f\x64\x3f\xc3\x54\xce\xc8\xfb\x07\x2d\x97\xb1\xa9\x3e\xf6\x33\x40\x66\x0f\x6c\x72\x8f\x79\xb6\x31\xe5\x11\x66\x7d\x43\xa7\x5b\xf4\x7b\x80\xf9\x7d\xa0\xc7\x21\x12\xfb\xc3\xf8\x27\xe4\x93\xc2\xc5\x16\x48\x76\x8d\x3c\xee\xe8\x25\x85\x8e\xc2\x5c\x9b\x63\xb2\x1d\xec\x79\x8b\x99\x3d\xd1\x90\xa3\x6b\x23\x8c\xf7\xc0\xbc\x26\x68\xbe\x88\x84\xfc\xdd\xcc\x61\x27\x4d\x64\x18\x47\xf2\x33\xcc\xab\x8b\x49\x2c\xd0\x57\x9f\xe0\x59\x44\x26\x2b\xf4\xef\x88\x79\x0e\x90\x65\x1d\xc9\xe4\x70\xf3\x03\x81\xff\x41\xe6\x4d\x5c\x7d\x80\xfb\x7b\x12\xdc\x5f\xd8\xdb\x0a\x17\x7a\xbd\x10\xfe\xfe\x8d\x66\x7f\x91\xe6\x00\x3b\xc9\x63\x62\x1b\xf4\x30\x46\x1e\x5f\xd8\xdd\x1d\x79\x86\xfb\xef\x80\x4e\x92\xc8\xfc\x8a\x9e\xa3\x98\xe8\x1b\x9b\x19\xe2\xb2\x67\x6c\x3e\xe4\xbd\x27\x1a\xfe\xcd\x2e\x8a\xa6\x63\x48\x98\xe9\x1d\x0f\x19\x36\x90\x5d\x02\x39\xe4\xb0\xb7\x38\x7a\x1f\xa3\x85\x2a\xc1\xfd\x81\xcd\x86\x3a\x0d\xfd\x1e\xb2\x55\xc8\x7c\x0f\x34\x73\xc6\x8c\xa2\xe8\x64\x81\x0d\x33\x3c\xd5\xc0\x5e\x66\xe8\xbd\x81\xd4\x37\xe8\xd7\x1f\x6e\xd2\x42\xe6\x0d\x5c\x3d\x49\xe0\x1f\xb1\x9d\x12\x26\xdc\x8a\x8b\x07\xc1\xa3\x8c\x29\x17\x31\x8d\x13\x3a\x2e\xe0\xa2\x17\x24\x19\xc5\x75\x53\xd8\x6f\x8f\xc0\xaf\xe3\x36\x65\x5c\xa3\x82\x76\xea\xe8\x7e\x8b\x24\x9f\xb8\x6e\x05\x33\x29\x62\x2f\xbf\x68\x7e\x85\x7c\x46\xd8\x58\x1c\xf3\xbc\x63\xb2\x17\x34\x37\x41\x8a\x5d\xe4\xb6\x44\xa6\x27\x24\x99\x40\x07\x7d\xec\x76\x87\xdd\x75\x31\x93\x25\x66\x3e\x47\x87\x3b\xdc\xf8\x82\xdc\xc6\x98\xe1\x1a\x8d\x1d\x31\xd1\x02\xee\x9d\x20\x78\x2e\x30\xf3\x15\xb2\xf3\xd1\x71\x0c\x57\xf7\x90\xfe\x14\x8d\x56\xd0\xe8\x1e\x17\xaf\x62\xaf\x53\x34\xf7\x87\x2d\xd6\xb0\xc9\x37\xf6\x7c\x46\x87\x0d\xd4\x3f\x63\x0a\x3d\x5c\xbb\x81\x7d\xa7\x90\x85\x8f\x8c\x7f\xd1\xda\x0c\x89\xad\x30\x9b\x37\xae\xf5\x40\xb3\x7b\xcc\xf9\x17\x33\x8a\xe1\xfe\x6f\xa6\x32\x52\xc9\xe1\x3a\x57\x82\x67\x05\x69\xc6\x30\xcd\x16\xa6\x7e\x45\xd6\x29\x34\xd7\xc5\xa6\x63\x68\xf5\x8e\x7c\x8a\xd8\xce\x1b\xdb\x1f\xe3\x62\x3e\x36\x7e\x47\x6e\x6b\xb4\x30\x43\xa2\x57\xe4\x19\x47\x97\x2f\x24\x77\x24\x78\x9c\x70\xb1\x3a\x52\xc9\x12\xf8\x51\x4c\x3c\x86\x19\x35\x31\xcb\x21\xc1\xa3\x80\xcd\xec\x09\x9e\x67\x4c\xbd\x8f\x5e\x92\x04\xf7\x0e\xda\x8d\x61\xd2\x73\x74\x1d\xe6\xd7\x09\xfb\xb9\xa1\xdd\x90\x2f\x0b\x98\xe5\x12\x1b\x4f\x61\x77\x0b\xcc\x7e\x89\xbd\x97\x31\xf5\x1b\x76\x7f\x40\xaa\x29\x64\xfb\xc6\x9c\x72\xe8\xb9\x87\x7d\x67\xd1\xc4\x0c\xf3\xfb\x8d\xeb\x76\xd0\x48\x0d\x73\x6c\x13\x3c\xc2\x2d\xfe\x83\x8d\xad\x31\x87\x22\xfa\x55\x46\xaf\x31\x4c\xaa\x83\xe9\xa6\x08\xde\x0b\x34\xf6\x87\x96\xda\x04\xde\x2f\xc6\x1b\xe1\x52\x35\x4c\x3e\x86\x6b\x44\xd1\x5b\x04\x8d\xae\x30\xd9\x23\xae\x7f\xc7\x64\xfe\xb0\x97\x32\x2e\x92\xc2\x94\xd6\xb8\xce\x05\x33\x1f\x60\x96\x35\xf4\xd2\xc1\x1e\x0b\xc8\xeb\x81\xbc\x9e\x68\x2c\x8b\xbb\x6f\xb0\xd7\x3c\x92\x9e\xa1\x9d\x15\xe6\x7f\x1e\x65\x30\xcb\x90\x63\x2e\x98\xd7\x11\x9d\xec\x30\xb1\x12\x1a\x66\xde\x34\x8f\x5b\x1f\x30\x9b\x1e\x72\x1a\x23\xa9\x1a\x12\xee\xd9\xdd\x07\xbb\xab\xa2\x97\x3b\x7a\x0a\xf9\xfd\x85\xfd\x0c\x31\xe3\x24\xa6\x99\xc2\x9e\x6f\xe8\xb3\x8c\x59\x7d\x90\xd4\x08\xf9\x5d\x63\xe3\x51\x6c\x6e\x87\xc9\x4e\x90\x72\x0f\xdb\x8d\x20\xf3\x39\xee\x3e\x45\x8e\x1b\xcc\x3b\x87\xa4\x37\x04\xf7\x23\x32\x6e\x63\xfc\x36\x2e\x79\xc1\x7e\x17\x31\xbd\x14\xae\x31\x46\xbc\x0e\x66\xf3\x40\x52\x3e\x36\xdc\x9b\xd5\x04\x76\xb2\xc1\x6c\xf2\x68\xbe\x86\xc4\xbb\x68\xeb\x80\xab\xbd\x71\xf7\x21\xfa\x4c\xa1\xc7\x0c\xa6\x9f\xc5\x34\xcb\xe8\xcd\x47\xa7\x35\xcc\xba\x85\x19\x0f\x70\xc3\x35\x2e\xf2\x44\xb3\x1b\x82\xf7\x0a\x49\x67\xd1\x82\x87\x99\xb4\xd0\xd1\x0b\x13\xab\xa1\x83\x1d\x1a\x9b\xe2\x16\x65\x24\x37\xc0\x1e\x7e\xb0\xef\x17\x92\x8f\xe3\xee\x1f\xb4\xb5\x40\x2a\x61\x46\xf6\x31\x21\xa7\x0f\xf3\xd8\x77\x0e\x0d\xef\x63\xbe\x45\x2b\x7f\xb8\x9f\x18\xf6\xfd\x8d\xe4\xc3\x1c\x9b\x12\x3c\xf7\xd8\x5a\x1e\xe3\xd7\x70\xbd\x37\xc1\x3d\x64\xb0\x0b\xb2\x4c\xa1\xf9\x21\xb2\x4d\x63\xdf\x55\x5c\xe7\x0b\xd7\xfb\x42\x42\xee\xab\x27\x90\x73\x1a\xc9\xfe\x20\x91\x31\x52\x4a\x22\xb5\x3f\xdc\xfa\x8a\x6d\xee\x90\xcc\x0d\x6d\xce\x31\x5f\x3f\xd8\x4b\x1e\x99\x67\x09\x5e\x3d\xf4\x92\x46\x9f\xbf\x68\x2f\x3c\x67\x1a\x57\xeb\xa0\xe3\x38\x9a\xbd\x12\xf8\x0d\xec\xa7\x41\xf0\x69\x11\x78\x65\x6c\xb2\x81\xfb\xce\xa3\xd3\x03\x76\x91\x42\xc7\x29\x34\x96\x40\xca\x0d\xb4\xf6\x8d\xfb\x69\x21\xf9\x36\xda\xf2\xd0\xe3\x1d\xd9\xcc\x90\x4a\x05\xd9\x0c\xd1\xfb\x08\x39\x64\x30\xcd\x37\xb2\xe8\xa0\xf1\x3e\x81\xbf\xc7\xe4\x47\xd8\x78\x04\xbb\xaf\xa0\xb9\x1e\xae\x9f\x45\xc7\x55\x24\xe4\xcc\x76\x0f\x3b\xde\x63\x7a\x2d\xf4\xde\xc2\x26\xca\xd8\x4b\x13\xbd\x16\x30\x8d\x3e\xda\x7b\xe0\xda\x49\x6c\xac\x80\xd4\xd7\x48\x29\x8b\x89\xc7\x31\xde\x1f\xba\x4b\xa2\xed\x15\xc1\xf3\x07\xd3\x4a\x63\x92\x5b\xa4\xfc\xc0\xd5\xb2\x68\x65\x83\x2d\x94\x30\x7f\x4f\x5c\xf2\x86\x44\x6f\xc8\xb3\x8e\x6b\xcc\xd1\x68\x78\xa7\x7b\x64\x50\xc5\x3d\x7d\xcc\xe7\x89\xf1\xae\x48\xb9\x83\xc9\x1f\x70\x91\x2d\xe6\x55\xc1\xf8\x7d\x74\xda\x45\x73\x55\x6c\x6a\x85\x6d\xfc\x21\x3b\x0f\xf7\x33\xc3\xac\x53\x48\xea\x8a\x7e\xef\x90\x54\x01\x09\x77\x5a\xfa\x8e\xf1\x93\xc8\x20\xd4\xb8\x87\x49\xec\xb1\xaf\x3d\xfa\x37\x45\x3b\x79\x4c\x7b\x81\xbc\xc7\xb8\xc6\x06\xd7\x58\x10\xdc\x97\x68\xeb\x0f\xd7\xf0\x91\xef\x04\x5a\xe9\xa3\xd9\x2a\x2e\x16\x21\xf0\x36\xb8\xe4\x0e\xfb\xc9\x60\x33\x35\x6c\x22\x85\x4b\x5e\x71\xad\x23\xf2\x59\xe2\x92\x5d\xdc\xf8\x85\x79\xbf\xd0\xeb\x0a\x29\xde\x09\xfc\x16\xae\x13\x6a\x73\x88\xc6\xd7\xe8\x60\x83\x2c\xbb\xd8\x58\x17\x2d\x66\x71\xd3\x36\xfa\x8c\xa1\xed\x14\xfa\xe7\x21\x95\x37\x2e\x5e\xc2\xc4\x6f\xe8\x21\x8a\x54\x2f\xb8\xf9\x1e\x5b\x59\xe2\x7a\x49\x5c\x6c\x8b\xfd\x44\x31\xe9\x2f\xb4\x56\x43\x96\x3e\xf6\x72\x46\xb6\x67\x4c\x7c\x81\x44\x3c\xe4\x5e\x41\x9b\x55\x5c\x3d\x8e\xb6\x56\xb8\x54\x1a\x5b\x9d\xe2\xc2\xad\xd2\x0b\x39\xf6\x83\xe6\x0b\x48\x2c\x89\x4d\x3e\x90\xc5\x1c\x2d\x67\xb1\xe7\x19\x9a\x4f\xa1\x9b\x1f\x6c\x75\x8c\x8d\x7b\x04\xf7\x09\x7a\x59\x23\xe1\x99\xda\x31\xe4\xfb\x17\x2d\x8c\xb1\xcb\x0c\xf6\xfc\x83\xfe\x67\x98\x33\x7a\x08\x7f\x2e\x20\xa9\xb0\xd7\x3c\x64\xd9\xc7\xee\xc3\xec\xb8\x22\xb9\x70\x5f\xff\x61\xc3\x9d\xd6\x2e\x63\x43\x26\xef\x65\x70\x3f\x55\x82\x47\x03\xf5\x7e\x08\xee\x3d\xa4\x38\x41\x73\x0f\x5c\xeb\x86\xd4\x56\x48\x66\x8b\x5b\xbf\x31\x61\x5e\xc4\x86\x68\xb5\x8d\xab\xd7\xd0\xd2\x0d\x37\x49\x23\x0f\x1f\x1d\x26\xd0\xf8\x08\x8d\xaf\x08\x5e\x27\x02\x3f\x8d\x4d\x86\x8c\x36\x40\xaf\x33\x24\x5b\xc5\x7c\x2f\x91\xd1\x18\x3d\x3d\xb1\xd5\x03\xe6\xb5\xc6\xf5\x8b\x68\xf1\x1b\x1b\x2f\x61\xf3\x45\xd4\x0f\x39\x7c\x8d\x16\x93\xe8\xa3\x8d\x19\x15\x71\xfd\x6f\x5c\xec\x82\xad\x24\x30\xcd\x1d\x7a\x0b\xf7\x4d\xd8\x0b\x39\xcc\xf1\x07\x13\x6f\x23\xdb\x0f\x3a\x9e\xa2\x99\x0c\x6e\x7d\x42\x7e\x63\xd8\xe9\x17\xf2\xee\x60\xb6\x1b\xb4\x58\xc1\xc6\x46\x68\xad\x8a\x76\x6a\xd8\xf7\x0a\xdd\x7e\xb0\xa5\x23\x5a\xcd\xa1\x95\x24\x2e\x79\x40\x0e\x65\x4c\xf3\x17\xa9\x47\xb0\x61\xa6\x8e\x2e\xe8\xf1\x17\xd3\x3d\x60\xbe\x92\x48\x79\x84\x6b\x47\xb1\xa5\x03\xfa\x75\xc4\xbe\x9b\xb8\xda\x1a\xd3\x0a\x77\xd2\x00\xb9\xdd\x70\xf3\x0f\x66\x7e\x27\xb8\xb7\x31\xa5\x04\xea\x85\x5e\xdd\xe3\x22\x3e\xf2\xda\x20\xfb\x70\xdb\x7d\x90\xc5\x0a\x9b\x4d\x23\x95\x6f\xdc\x70\x81\x46\x56\x98\xe1\x16\xdd\xa4\xf9\x17\x00\x00\xff\xff\xbf\x1b\x72\xe3\x00\x20\x00\x00") - -func keysWordsWordlistChinese_simplifiedTxtBytes() ([]byte, error) { - return bindataRead( - _keysWordsWordlistChinese_simplifiedTxt, - "keys/words/wordlist/chinese_simplified.txt", - ) -} - -func keysWordsWordlistChinese_simplifiedTxt() (*asset, error) { - bytes, err := keysWordsWordlistChinese_simplifiedTxtBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "keys/words/wordlist/chinese_simplified.txt", size: 8192, mode: os.FileMode(420), modTime: time.Unix(1523115814, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _keysWordsWordlistEnglishTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\x5b\xdd\xbe\xbc\x2a\x08\xbd\xf7\x2d\xc9\xa8\xd8\xa3\xe2\x41\x9d\x76\xfb\xe9\xcf\x6f\xad\xfe\x17\x83\xe5\x07\x2a\x22\x2c\xcc\x91\x4d\xda\xee\x2d\xc9\x66\xc5\xe6\x93\x64\x2b\x9a\x64\xf3\x35\x41\xbf\x78\x1e\xda\xf0\x32\x3c\x36\x24\x33\x24\xf3\x7d\xc5\x9e\x64\x5b\x43\x93\xe4\xac\x63\x20\xb1\x9d\x95\x73\xf6\xf5\xa6\x6f\xf1\x65\x0a\x56\xd9\xf6\x24\xd9\xd7\x98\x96\x93\xe4\xff\x96\x05\x72\xc3\xd9\x18\xf5\xa7\x61\x2c\x79\x7a\x80\xc6\xcb\x75\x2e\x29\x49\x76\xe9\x33\xc9\xbe\xe3\x67\x99\x8f\x6f\xf9\xfe\xb3\x06\x5e\xab\x81\xae\x02\xfa\x95\x96\x15\xa9\x21\xd1\xf0\x0d\x3d\x1e\x87\x58\x20\x71\x0c\xfd\x08\xc1\x78\x4e\xb1\x96\xe4\x54\xfc\x30\xe6\x33\x54\x93\x5c\x2a\x7b\x12\xab\x89\x2d\x2c\xba\xc7\x4c\x62\x03\xd2\x29\x12\x35\x49\xd9\x16\x68\xf6\xcb\x4b\x92\xa2\x28\x2f\xa6\x2d\x49\xc1\x7b\xd1\x07\xd4\xef\x24\xa5\x3a\x06\x58\xbc\xa1\x71\xbf\x24\x49\x09\x95\x1d\x15\x86\x27\x29\x53\x23\x49\xb9\xe5\x19\x49\xaa\x4c\x5d\x81\xf4\xcf\xda\x99\xa4\xfa\x4b\x29\xcf\xba\x86\xee\x49\x9a\x94\x07\x1c\x5b\xbe\x20\xa8\x96\x8d\x23\x6f\x27\xf8\xb4\x13\x63\x6c\x67\x3c\x49\x9a\x55\x88\xae\x7d\x98\xd5\x7c\x51\x2a\xad\x51\xa0\xcd\xe7\xc5\x06\xe3\x66\x32\xb5\x35\x41\x6a\xff\x2d\xd4\xfa\x35\x85\x42\xb4\x27\x49\x17\xcc\xae\x7b\xf1\x13\x6f\x5d\x25\x90\x80\x6b\xef\x41\x35\xe9\x61\x25\x49\xe4\x0b\x84\xeb\x1b\x2a\x20\xe0\x19\x27\x38\x42\x6a\x51\x31\x81\xa8\x18\x77\xd4\x27\x49\xf8\x6a\xc8\x09\x0c\x1f\xa9\x62\x66\x11\xf6\xe5\x1b\xe4\x87\xbe\x63\xea\x41\x15\x89\x69\xac\x30\x6f\x8f\x4f\x92\x81\x5f\x57\x94\x8c\x21\x5c\xfc\x31\x94\x94\xf5\xc6\x58\x55\x93\x8c\x79\x55\x49\x32\xaf\xa2\x53\x93\x4c\xaf\x49\xe6\x94\xfc\x41\xa2\x18\xc0\x9c\x36\xd7\x8e\xb2\x7f\x0a\xbe\xfe\x29\xe3\xda\xa1\x57\xeb\xa4\x92\x71\x15\xd6\xa4\xd8\xd7\x74\x90\x55\x5b\x92\xaf\x06\x55\xe8\xeb\x59\x76\x47\x0a\xd5\xba\xe5\xa3\xa0\x41\xfa\x24\xb9\x75\x38\x86\x73\x1f\xab\x24\xb9\x3f\xb7\x40\x11\x7f\x6d\xa4\x4d\xb6\x27\x6d\x92\x2f\x2d\x1e\x78\xf0\x96\x36\xd9\x4f\x4d\x9b\x9c\x69\x93\x42\x85\xde\xa0\x6f\x0d\x15\x4b\x49\x9b\xd4\xcd\x3d\x6d\xd2\xa4\x09\x92\xa6\x68\xc9\x9f\x16\x54\x0a\xea\xf6\x06\xa1\xa2\xfa\x00\x83\x61\x19\xf4\xa3\x33\x6d\x32\x67\xd1\xb4\xa9\xe4\x0b\xb4\x81\xac\xf9\xa4\x4d\xb3\x60\xe3\x6e\x9a\x31\xdc\x4d\xf5\x48\x9b\x1e\x1e\x78\x3e\xc1\x52\x2f\xf9\xe2\xe5\xb2\xb6\xa7\x4d\x0b\xf7\xf7\xa6\x50\xf7\x4d\xcb\x4c\x9b\x36\xf2\x6c\x7a\x18\xde\x06\xc8\x0c\x01\xef\x09\x75\xdf\x74\xde\xaa\xe0\xf4\x38\x58\x58\x7e\x32\xc6\x62\x78\xfe\xe0\x81\xb9\xaf\xc6\x6d\x16\x78\x89\x79\xa5\xcd\xde\xe6\x05\x6b\xb7\x15\xd9\x15\xb4\x92\x36\x4e\xaa\x08\x3a\x2b\x2a\x28\x87\x81\xd8\x0a\x79\x15\x77\xd2\x31\xbc\x22\xe5\x04\xcb\x22\x01\xc3\x35\xae\xb4\x39\x16\x64\x73\x99\x69\xf3\xfd\x49\x9b\x5b\x49\x9b\xd7\x2d\x6d\xd8\xbc\x9b\xb7\x35\xd2\xe6\xfe\x01\x41\x37\x1e\x3b\x46\xe3\x81\xbd\xba\x39\xf5\x75\x83\x39\xdb\x7c\x42\xc9\xb6\x77\xcb\x6d\xfe\x9b\x36\x7f\xd2\x16\x92\x39\xc8\xe0\xc2\x84\x60\x60\x21\xa8\x1f\x14\x28\xcc\x02\xa8\xfe\xe1\xc5\x30\xc7\x30\x6a\x41\x18\x16\x21\xec\xbc\xd0\x9c\xdd\x85\x0d\x94\x7b\xce\x5e\x0c\x0f\x1f\x08\x34\xbc\xb1\xb1\xa3\xfb\x78\xf7\xf8\x16\x7e\xa3\x88\x73\x5c\x1b\x6c\xfc\xb6\x76\x4c\x70\xed\x27\xc6\xb3\x8e\x43\x8a\xa7\x6d\x59\xd9\xd3\xb6\xca\x06\xf2\x01\x29\x2c\x6e\x3b\x9b\xb4\x0f\x98\xad\xd8\xd1\xd1\x8a\xf3\x7d\x83\x20\x20\x97\x35\xac\x51\xe0\x6b\x80\xf3\xbb\x50\xeb\x21\xfd\xfb\x4b\x59\xb6\x0d\x9b\x24\xcb\x66\x0d\xb4\xe0\x39\xcf\x35\x52\x7e\xf3\x3f\x20\xa5\x80\xd4\x94\xa5\x6a\x08\x92\x9e\xb2\xa0\x41\x13\x14\xb5\xac\x4c\xf6\x07\xb4\x39\x4b\x1c\x2d\xdb\x57\xc0\xaa\x3d\xcc\xeb\xff\x3a\xe8\x36\xd9\xae\x4f\x61\xb7\x81\xdf\xc6\x2a\xb1\x83\x9c\x0e\xda\x75\x22\x09\x70\x0d\x3c\x0e\x34\x1e\x17\x88\x35\x54\x19\x93\xfc\xc6\x22\x3b\x54\x99\x52\xfc\x44\x9a\x51\x6d\xea\xe9\x6c\x3e\xdf\x8a\x0b\x4b\xf5\x6e\xa4\x2c\x8b\xc6\x24\x63\x91\xb3\x5a\xc1\xfa\x65\x2d\x8a\xfa\x5a\x61\xbd\xb3\xb6\x01\x49\x68\x9b\x8b\xb9\xa1\xe8\x47\xe3\x1d\xf6\x05\x3f\x94\x2f\x29\x1f\xd0\xda\xc9\xed\xa2\xcd\xcc\x97\xf8\x00\xed\x10\x78\xbe\x24\xde\xcc\x41\x3a\x53\xbe\x54\x3a\x68\x46\x5b\x55\xe6\xeb\x01\xc2\xe9\x5e\xd8\x9d\xf9\xb2\x0c\xf5\x81\xab\x46\x11\xf4\x20\x5f\x56\x9b\xa2\x86\xc3\x8d\xe6\xcb\x9d\x6d\xc3\x9b\xe5\x94\xaf\x95\xe1\x57\xf2\xb5\x1a\x18\xaf\x68\x29\xdb\x09\xf9\x5a\x6b\xf0\x5b\x29\x5b\x60\x53\x67\x9b\xf6\x07\xde\x00\x18\xd9\xbe\x56\x52\x2e\xf0\xad\xb9\x60\x60\x45\xc2\x8e\x07\xe9\x0d\x82\x27\xd8\xa2\x5c\x34\x3e\xa0\x5f\xcc\xaa\x60\x2f\xe4\x42\x47\x97\x8b\x1d\x07\x68\xdd\x40\x39\x98\x62\xe0\xe4\xac\x84\x35\x29\x1c\x6a\xf1\x79\x81\xae\x1d\xf4\x06\xd3\x85\x36\x0b\x3a\x55\xd6\xa0\xc0\xca\xe2\xfa\xb9\xbc\x14\xc2\xf0\xec\x6d\x21\xdd\x35\x65\x3f\x0e\x45\x82\x61\x3b\xd6\xc2\x4b\x81\xc3\xc9\x0e\x53\x9d\xbd\xc0\x03\x64\xaf\x9b\x35\x54\xab\x24\x07\xf0\x42\xf6\x8a\xb1\x79\xa5\x30\xbc\x76\x38\xd3\xec\x0d\xab\x8a\x74\x5f\x64\xd3\x0e\x8b\x8a\xf4\x24\xa0\xc9\xde\xda\xcb\xbf\x0d\x83\x79\xc9\xde\x66\x38\x7a\x6f\x5f\x83\x39\xc9\xb0\x40\xd9\x99\xd5\x3b\x6b\x74\x30\x0e\x68\x0c\xac\x74\x76\x2c\x86\x47\xbc\x7c\x38\xa5\x39\x39\x88\xc5\x59\xae\x36\xb1\xf4\xbe\xe0\xc3\xb3\xaf\x18\x4c\x06\xa7\x47\x81\xfb\xe3\x53\x53\x86\xc1\x02\xc5\xfe\xcf\x21\xc7\x04\xad\x20\x8d\x19\xd8\x20\x21\x94\x63\xc8\x5d\x40\xff\x9e\x94\x43\x59\x49\xe1\x3b\x73\xa8\x82\x87\xde\x29\xc3\xa4\x61\xa3\x85\x41\x4c\x61\xa3\x83\x02\x2e\xe4\x70\x3c\xc3\x76\xe6\x78\x47\x19\x7e\xef\x29\xc7\xca\x86\x79\xc5\x52\x52\xc3\x50\x63\x55\xee\xee\x58\x8d\x35\x17\xc7\x81\x8e\x9f\xc1\xed\xbe\x36\x4d\x79\x95\xb9\x20\x8d\xd5\xf1\x7b\x8d\x7b\x5e\x61\x8e\x8d\xb6\x22\xa8\x4c\xeb\xdf\x0e\x5b\x81\xbd\xb9\xc6\xc5\xad\xb5\x06\xcc\x77\x5e\x90\x01\x3d\xd3\x2e\x7b\xda\xa5\xc2\x50\xed\x30\x49\x3b\x1d\xf2\xfe\x82\xae\x5d\x68\x91\x77\x88\x63\xe7\xc6\x67\xe6\xdd\xd2\x2e\x4f\xda\xb1\x93\x77\xdd\x64\x2a\x92\xb0\x91\x76\xcd\x70\x5d\xbb\x66\xad\x1b\xea\x2a\xa0\x33\x92\x02\x2d\xda\x15\x8b\xc9\xea\x10\xe5\xc0\x03\x6b\x1d\xda\xf8\x72\xbc\xb5\x0e\x30\x27\x60\xdd\xb5\xb0\xa7\x62\x5f\x56\xac\x70\x2d\xbb\x56\x63\xf5\x66\x1c\x41\x23\x76\xda\xb5\xa1\x26\x31\xdd\xae\x5d\x59\xb1\xfb\x30\xbe\xce\x0b\x14\x28\x60\x57\x82\xb0\x5d\x47\x0e\xdb\xf8\xa0\x6c\x32\xec\x6c\x48\x3e\x20\x1d\x86\x69\xd7\x31\xc3\xd1\x64\x8a\xa1\xa7\x09\xc5\xdb\xf5\xab\xc5\x3b\x52\xd8\x8f\x5d\xbf\x50\xa9\xdd\xe4\x84\x0a\xed\x1c\x93\xc1\x50\xec\x48\xe3\x49\x3b\xab\x99\x0e\x45\x89\xce\xb4\xdb\x71\x60\x3a\x76\xd2\x88\xef\x76\x36\xd8\x90\xdd\x8a\xd6\x2a\x69\x37\x62\x9e\xdd\x9a\x0f\x59\x78\xa0\xc2\xef\x86\x61\xda\x78\xa1\xfc\x6e\xe3\x55\xe9\xdd\xc6\x2b\x4a\xc3\x2a\xd9\xa8\x36\x06\xd2\xd7\x87\xef\x36\x3a\x45\x68\x63\xbe\x4b\x0b\x49\x82\xcf\x97\x2b\x63\x5f\x0f\xe6\xfe\xfd\x3d\x69\x77\x86\x28\xbb\xe7\x45\xe3\xbd\xfb\x99\x76\x2f\x05\xa4\x5f\xd6\xd2\xee\x55\x98\x34\xae\xa2\xb7\x8f\xa2\x55\x63\x23\x12\x0c\xc4\x17\x94\x78\x07\x7e\xde\xb9\xb7\xf6\x90\xd3\x1b\x12\xcc\x2e\x84\x81\xd2\x1e\x72\xa7\x9d\x3b\xea\x8d\x78\xf6\x30\xd6\x35\x74\x18\xd6\x3e\xa0\x1d\x84\x8c\x20\xf1\x58\xa8\xfc\xa4\x7d\xe5\x4f\xda\x57\xdd\xd2\xbe\xa0\x31\xeb\xd5\x53\x60\xd9\x9d\x66\x6f\xe7\x4a\xdf\x12\x47\xda\x9f\x26\xb0\x57\x2a\x50\x69\x15\xc4\x11\x2a\x51\x1e\xd0\x06\x32\xaf\xa4\x32\x8c\x39\x63\x82\x3c\x49\xf3\xe5\x49\xf3\x0b\xd4\x34\x7b\xf3\xfa\x24\x05\x64\xe1\xe6\xd7\x7d\xc1\x33\x26\x3d\x68\x11\xf5\x3c\x93\x12\xc3\xa8\x11\x99\x68\xd9\xfc\x4e\x5a\x76\x3e\x6b\x9e\x81\x11\x14\x3d\xa5\x4d\xa4\x14\xaf\x16\xed\xd7\xbf\x8c\xaf\x40\xf2\x5a\x0c\x4c\xcb\xd0\xa4\x75\x93\xf8\x20\x01\x62\xd3\x0a\x8c\x85\x5c\x85\x1b\xd4\xea\x74\xbc\x5a\x7b\x71\x94\x76\x47\xb0\xa3\xb5\xcf\x27\x69\x23\x44\xd0\x06\xbc\x8f\x6d\xa0\x80\x39\x63\x20\x75\x58\x44\x6d\x8a\xc9\x34\x0d\xcc\xad\x1d\xd4\x00\x6d\x27\x8c\x80\xb6\x13\x7b\x50\xdb\x45\x6d\xd1\xf6\x03\xfe\xad\x60\x87\x69\xf3\x75\x5e\x49\x5b\x58\x66\x02\xd5\x80\x7f\x0f\x54\x84\x6d\xc0\x56\x7c\x5f\x02\xad\xb8\x4f\x34\x69\xb7\x01\x97\xa3\xff\x01\x63\xe8\x7f\xcb\x7a\x02\x06\xd2\x80\xde\x6a\xb0\x2c\x7c\x70\x46\x11\x90\x43\xac\x3e\x93\x8e\x2c\x68\x3e\x86\x3c\xa0\xca\x11\x8d\x49\xc1\x4f\x0d\x00\x27\x9d\x97\xe5\x91\x14\xda\xcc\x62\xb8\x61\xfd\xfa\x07\x8f\x5e\xbe\x9a\xf4\x97\x72\xf8\x95\x0a\xa7\xa0\xbf\x8c\xe9\xf5\xf7\x1f\xca\xd0\xdf\x4c\x91\xff\xe6\x82\x30\x49\x7f\x19\xda\xeb\xaf\xd2\x46\xea\xaf\x46\x36\x66\x5c\x02\xed\xd2\xdf\xcb\x36\xac\xff\xaf\x91\x19\xc5\xf2\xcb\x0c\x87\x52\xeb\x6f\x87\x85\xd2\x5f\xc6\x6e\xfa\xdb\x29\x8e\xdf\x5e\xb0\x6d\xf4\xb7\x3b\x79\xf5\x78\xc7\xc0\x10\x4d\x7f\x27\x64\xf1\x28\x7e\x40\xb4\xe9\x10\x60\xe4\x74\x60\xc1\x0f\x81\xb9\x7f\xd2\x01\xbb\x7a\x88\xb5\x09\x3a\xaf\x74\x00\x51\x1e\x02\x55\x39\x10\x28\x1c\x52\xa1\xc1\x07\x62\xea\x91\x0e\x69\xf8\x65\x64\xb4\x09\x85\x3e\x10\xa7\x1e\xf2\xfa\x81\x43\xc0\x06\xb6\xe7\x10\xea\xeb\x21\xd3\x10\xcc\x1e\x8c\x35\x0f\xf9\x7a\x40\x2c\x87\x0a\x5d\xcd\xa1\x5b\x2c\x98\xb2\x43\x77\x85\x3b\x06\x74\x38\x54\x77\x10\xbc\x55\x29\xc8\xc0\x0a\x1c\x3a\xa6\x7d\x59\x07\x3b\xf1\x20\xd0\x39\xf4\x4e\x87\xc1\x25\x1c\xf6\x06\xa0\x87\x69\xd9\xd3\x61\x27\xf9\x43\x9a\x87\x95\x0a\x32\x59\x0b\x8b\x7b\x20\xc2\xa1\x4f\x38\x8c\x0e\xe9\xb0\x06\x2b\x77\x18\xdb\x60\x42\x06\x98\x7e\xd8\xc8\xac\xce\x32\xbc\x4f\x22\xf6\xc3\x7e\xd3\x51\xe4\x04\x81\x88\x0a\x1c\xd9\x51\x30\xf9\x82\x29\xa6\xa3\x60\x1e\x85\x3b\xf7\x00\xd6\x3a\x8a\xb3\x14\x88\xeb\x28\xce\x2a\xdc\x5a\x47\x59\xb6\x83\x92\xc3\x93\x0e\x97\x9a\x0e\xcf\x90\xb5\x9f\xe9\x00\x8c\x3a\x1c\x33\x72\x9e\x8e\x1c\x08\xcb\x0e\xf7\x99\xde\xed\x85\x28\x73\xf0\x05\x81\xc9\x81\x20\x1f\x96\x03\xd6\xeb\x70\x98\xb5\xc3\x83\x61\xf3\xe1\x63\x90\x17\x51\xdc\xc1\x63\x84\xc3\x7f\xd3\x11\x72\x52\x4a\xc1\xa9\x84\xfe\xb7\x60\x43\x8e\x50\x8c\x28\x0c\xaa\x74\xc0\x0c\xa2\x10\x23\x0a\x67\x31\x50\xd2\xc1\x38\xe9\x08\x07\x5c\x3d\x62\x41\x44\x80\x1d\xc7\x6a\xf8\xb5\x27\x1d\x2b\x1a\xd5\x0d\x20\xfd\x58\x5c\xf4\x53\x18\x44\x31\xd8\x3e\xa5\xc8\xef\x83\x84\xe0\xfe\xc4\x18\x4e\xe9\xe9\x14\x1e\x10\x9c\x12\xdb\xbf\x14\x31\xd4\x29\x51\x2c\x23\xa1\x9d\x3b\x65\xe0\x87\xda\x13\x75\xa8\x71\xa7\x2c\x36\xf8\xd3\x74\xc2\x14\x49\x41\x6a\x6b\x20\x09\x66\x22\xde\x38\xb5\x2d\x28\xc0\xa9\xe3\x1d\xd4\x85\x09\x9d\x06\xb3\x79\xc2\x5f\x9c\x76\xc2\xa2\x9f\xaf\x82\x9c\x16\x72\x1c\x78\x8d\x92\x4e\x38\x8e\xb3\xc8\x0e\x02\xd5\x3c\x8b\x04\xe9\x18\xe9\x2c\xf0\x7f\x67\xb1\xda\x07\x52\xdf\x48\xbd\x82\x62\x8a\xc5\xd9\xda\xef\x74\x22\x9c\x3e\xa1\x18\xa7\xef\x3b\x14\xeb\xc4\x4a\x9f\x58\xe2\x93\xc1\xc3\xe9\xf0\x5a\x92\x4e\x1f\x5d\x0b\x92\x61\x3d\x9d\xf0\xcf\x2d\x9d\x10\xfe\x19\xb2\x81\x60\x14\x8c\x92\xcf\xe0\x14\x02\x16\xee\x64\xac\x7c\x86\x7c\x01\x03\xce\x50\x74\x15\x0a\x49\x86\xed\x20\x7a\x80\x22\xd7\x33\x17\x20\x7c\x75\xd0\x3b\x9d\xb1\xc0\x68\x41\x79\xce\xc5\xd1\x2d\x4e\x6d\x59\x41\xbe\x4d\x89\x74\xae\x96\xce\xa7\xa6\x4b\x60\xbd\x18\x75\x5d\x52\x8e\x74\x49\xad\x8a\xe7\x4a\x75\xbb\x60\xbc\x2e\xe9\xfd\x49\x17\xa2\x49\xe4\x04\x72\x62\x5c\xa0\x5f\xe8\x30\x82\x2f\x9e\x93\x5c\x72\x7f\xd2\x25\x7f\xac\x82\x08\xff\x52\x29\xf3\x42\x12\x13\xf4\xfb\xa4\x0b\x3e\xf3\xf2\x33\x5d\xaf\x7f\xbc\xb4\x14\x07\xad\xca\x97\x9e\x2e\x6d\xe9\xd2\xf0\x74\xd9\x0e\xe5\xb9\xec\xbc\xd2\x05\x10\x70\xc1\xda\x5d\xd6\xd3\x85\xfd\x7e\xd9\x98\x58\x98\xcb\xb7\x0d\x34\x03\x7b\x5c\x58\x88\xcb\x8b\x82\x18\x50\xe9\xf5\xee\xbf\x0b\x01\xcb\xe5\x8d\x75\x1c\x75\x3a\xde\xa3\x81\xc0\xc5\x5c\x74\x85\x97\x8f\x37\x90\xa6\x5a\x5d\x3e\x15\x8f\x0b\xc5\x30\x5b\xd7\xda\xd2\x05\x3d\xbd\x56\x95\x06\x0a\xcf\x7a\xad\x0a\x06\xab\xed\xa1\x3b\xd2\x13\xc3\xc2\x2a\x5c\x2b\x76\x56\x08\xe6\x40\x0a\x6b\x6c\x14\xea\xb3\x61\x29\x81\x04\x2d\x7b\x4b\xb6\xab\x24\x1e\x2b\x23\x48\x34\xb4\xb2\xb3\x21\xc8\xc1\xcc\xad\x00\x2a\x30\xa5\x21\x33\x02\x74\xab\x46\xdf\x67\xb5\x12\x2f\x5b\xad\xb0\x1f\x56\x3b\x3c\x9c\x55\x7a\x17\xab\xef\xc9\xa5\xd5\xbe\xe0\x1c\x0c\x91\x84\xb5\xd7\xbd\x59\x63\x20\x67\xed\x1f\xfc\xb6\xb6\xeb\x2f\xa8\x11\xcd\x58\x23\x8a\xb3\x06\x24\x15\x4f\xb2\x06\xef\x81\xa4\x58\x66\xea\x51\x93\xb5\x0b\xd6\xde\xda\xa5\x50\x49\x6b\x36\x81\x79\xad\xfd\x28\x2b\xfd\x2c\x36\xad\x2f\x47\x20\x59\x6b\xcd\xb3\x92\x53\x5f\xa0\xff\x2d\x63\x9d\x81\x70\xcb\xda\x78\x1b\x22\x2c\x44\x42\xa7\x69\x0d\x11\x0f\xd8\x4e\xce\x0e\xf8\x02\xda\x67\x6d\x7a\xb2\xf6\x7d\x9f\xbf\xc6\x4e\x5e\x4f\x6f\x01\xc1\x8e\x02\x79\xdb\xf0\xc2\x01\x8c\xb1\x34\xd9\xd4\x9a\x00\x75\x9f\xf4\xf3\x1e\x55\xfd\x08\x76\x4c\xfa\xe1\xef\xef\x2f\xfd\xa8\x14\x38\xce\x1f\x95\x06\x5a\xca\x93\x7e\xf4\xd6\x92\x7e\x7c\x4b\x3f\x08\x90\x7f\x00\x2a\x7e\x7c\x05\x94\x0a\xb0\xe8\x67\x01\x0f\xfe\x2c\x2c\xea\x0f\x62\xef\x9f\xc5\x53\xea\x9f\xd5\xcc\x03\xc9\x27\xf1\x10\xff\x23\xed\x94\x70\x4f\x1f\xec\xe9\x8f\x6a\x4f\x1f\x38\xc7\x85\xf4\x49\x1f\xcb\x9f\xf4\xb1\x1d\xbf\xc6\xf7\x86\xe7\x76\xee\x5e\xd3\x07\x70\xfe\x63\x13\xbf\x8c\xbd\xf2\xc1\x94\x3f\x36\x27\x9f\x6f\x4b\x9f\xa6\x9a\x3e\xcd\x0e\x50\x38\xae\x4f\xf3\x3b\x15\xd9\xf0\xd3\x02\xea\x91\x8a\xec\x00\xa3\x45\xf6\x27\x15\xf9\x68\x2a\x08\xf7\x8a\xb4\x73\x41\xb7\x8a\xf4\xe9\x78\x0f\xbe\x4c\x56\x9d\xd6\x52\x41\xdc\x07\xda\x00\xbc\x8b\x7c\x25\x15\x01\xfb\x1b\x65\xf7\x80\x33\x29\xf2\xb0\xfe\xdf\x93\x8a\x0a\xbb\x51\x39\x40\xa2\x81\x7e\x35\x01\x03\xc3\x7e\x17\x3d\x66\x2a\x7a\xa6\x57\xc1\x8b\x9e\x70\x5c\x45\x6d\xbc\xa5\xd5\xd1\x82\x59\xed\x9c\x17\x92\x91\x8a\x7a\x87\x91\x01\x8a\x65\x39\xcf\xe0\x0a\xe2\xb0\x54\x4c\x22\x15\x40\x8b\xf9\x20\x0d\xc0\x94\x62\x99\x3b\xa4\x40\x28\x05\x6e\xe2\xf5\xf1\xc5\x30\x71\xab\x1b\x08\x06\x8e\x28\xa3\x00\x8e\x14\xfb\x0f\x0e\x9e\x38\xb7\x18\x8f\xba\x10\x73\xa6\x62\x34\x6f\xc5\x85\xa4\xa5\xe2\x1b\x4d\x65\x71\x40\x0e\x02\x85\xe2\xa7\xe5\x54\xbc\x69\x79\x90\x9c\xa9\x38\x64\xe9\x18\x26\x72\x16\xda\x2e\xb8\x66\x3a\x95\xe2\x0f\x9a\xae\xfc\x79\x52\x59\x27\x71\x77\x59\x0c\x98\xcb\x6a\x42\x9a\xaf\x54\xd6\x2f\x76\x52\x79\x02\x08\xb7\x4a\xbe\xe0\x08\xab\xec\xa9\x0a\x3a\xac\x72\x36\x9d\xa9\x8a\x21\xc7\x4a\x62\x6c\x56\xe5\xc7\x23\x55\xac\x70\x95\x5a\x05\xd9\xc8\x6d\xe8\x05\xe1\x33\x76\x45\x95\x76\x3a\x28\x31\x77\x15\x7e\x39\xa9\x02\x80\x5c\x25\xb6\x37\xc9\x17\xe8\x49\x9e\xf1\x76\x1d\x1f\x76\x18\x61\x2f\xb7\xf1\x01\xc1\xe0\x28\x93\xca\x23\x43\x6c\xfc\x30\x32\x9c\x7c\x0b\xfb\x45\xf2\xd6\xf8\xb5\xba\x6a\xaa\xf0\xfb\x55\x65\xf7\x1b\x49\x03\xa1\x06\x54\xf8\xbe\xaa\x40\xe7\x98\xa2\xee\xe0\xa3\xbb\x49\xaa\x5a\x10\x09\x55\x2d\xa8\x40\x69\x55\xad\xd8\xd2\x00\x19\x9c\x87\xb6\x95\xaa\x46\x46\x16\xf4\xb8\xd2\x40\x55\x9e\x07\x56\xe0\xa4\x8a\x58\x82\x05\x93\x7c\xe7\xe5\x7b\xaa\xb6\xc3\xfc\x56\xdb\x1b\x95\xa4\x5a\xf9\x80\x50\x2f\xaa\x21\x76\xac\xd8\x91\xd5\xda\x3b\x76\x43\xbc\x5b\xad\x21\x42\xa8\x16\x92\xd9\x9a\x5e\xa5\xda\xc0\x92\x33\x06\xaf\x08\xb9\xb1\x0c\x98\xbe\xfd\x2a\x38\xfc\x72\x13\x54\xdf\x00\xe5\xaa\xef\x5a\x40\xe1\x02\xaa\x57\xfc\x60\x25\xab\x37\x43\x34\x58\xdf\xf8\xba\x7a\x7b\xa5\xeb\x0d\xf2\x74\x8c\x8a\x67\x62\xd5\xc9\x2b\x1a\x82\xdf\xea\xe3\xbf\x65\xd3\x53\x7d\xcf\xc6\xff\x45\x88\xd5\x5f\x4e\xab\xf1\x38\xa8\xf2\xfb\x40\x85\x16\x56\xff\x9a\xa6\xba\xb0\x62\xeb\x38\x50\xb8\x30\xa8\x55\xa6\xf5\xf2\xa4\xba\x06\x27\xb6\x86\x62\xd2\x6b\x5c\x3c\x7b\xaf\x6b\x40\x20\x30\x6b\x75\xf1\x13\x66\x7d\x86\x96\x03\x09\xd5\xbd\x3e\xf3\x4a\x4d\xb0\x79\x1a\x60\x62\x93\xfe\xb1\x96\xda\xfb\xd5\xab\xc9\x98\x4f\x6a\xc2\xc1\xb5\x37\xba\x68\x2a\x91\x9a\xe6\x4f\x6a\x08\x29\x9a\x9e\x32\xd9\x5c\x4f\x9e\x48\xb6\x7f\x41\x75\xd3\x7e\xe9\x9d\x9a\x06\x0b\x07\x4a\xf8\xe3\x37\xb3\xa6\x6b\x42\x2a\x8d\x01\x47\xd3\x7b\xa4\xa6\xbf\x33\x35\x98\xe7\x77\x65\x9b\x43\xb5\x9b\x23\xa2\x6b\x5e\x0d\x86\xb3\xb9\xef\xcc\x0c\xec\x95\xe6\x81\xd1\x3b\x2b\x4c\x79\xab\x4f\x92\x0b\x52\x6e\x88\xf2\xf0\x0a\xd3\x03\x33\xdb\x56\x2e\x1c\xfe\xbb\x7f\x1b\x8f\x1c\xdb\x9a\xc9\xe5\x93\x7c\xd3\x27\xf9\x46\xbf\xe8\x5b\xb1\x53\x93\x6f\x23\x63\xce\xbe\x0d\x4e\xc3\x37\xae\x8b\x6f\x5f\x1e\xdf\x79\xce\x2b\x92\x67\x6c\x09\xcf\xd3\xc1\xd3\x77\x8f\xe4\xc7\x81\x9f\xf2\x09\x43\xf0\x03\x0e\x00\x61\x87\x7f\xe4\x49\xc0\x41\x4e\x8b\xe5\xe5\xa9\xdd\x72\x72\x18\x38\x07\xec\xf5\x86\x1f\x04\xee\x8d\xe7\x70\xde\xca\x93\xbc\xa3\x7d\x47\x20\xee\xdd\xde\xe2\x4e\x08\xe1\x9d\xab\xe3\xef\xb7\x4b\x0f\x40\x46\x8f\x4c\x28\xf8\x9e\x2a\x79\xec\xd6\x60\x68\x3d\x4e\x8c\x34\x78\x80\xed\x61\x27\xe3\x36\x8f\x7e\x21\x7b\x4c\x9e\x14\xbc\x0a\xe9\x6b\x12\x5d\xf8\x9a\xef\x1b\xa0\x80\xaf\x49\xaf\xef\x08\x18\xfd\x8b\x11\x61\xf5\x80\x98\xfd\x06\x74\xf0\xdf\xe7\x44\x2e\x95\x2b\xf9\x1f\xe6\x42\xb8\xd3\x85\xbb\xb6\x63\x3b\xf3\xb0\xae\x4b\x01\xba\xee\x52\x6a\x42\x10\x2e\xa0\x5a\x40\x2d\x83\x72\x14\x5d\x3a\x69\x20\x9e\xee\xc2\xb3\xd2\x2e\xf1\x01\x09\xe7\xf3\x7c\x52\x87\x51\xeb\xb4\x66\x1d\x46\xac\xcb\xb4\xb7\x26\x4f\xac\x3b\x8d\x59\x4b\x9d\x5f\x41\x3a\xfc\x5b\x97\x87\x7b\xb7\x2b\x07\xa1\x02\x1d\xe0\x07\xe5\xae\x32\x84\x25\xc5\xb2\xb4\x04\xb1\x77\x6d\x82\xa8\xbe\x6b\xcb\x56\x52\x57\x87\xe9\xed\xca\x53\xef\xae\x71\x40\x63\xba\x06\x96\xb0\x6b\xc0\xe9\x75\x9d\xa9\x5f\x9c\xfe\xe5\xd3\x53\xbf\x78\x7a\xd2\xaf\x67\x18\x3c\x51\x37\x69\x9e\xba\x65\xce\xd6\x5e\x6f\xdb\x4d\x31\x1a\x3b\xf1\x53\x70\x01\xba\xec\x56\x30\x53\xf8\xbe\x6e\xde\x14\x7d\x5a\x47\xbd\x31\x31\x3b\xe3\xbc\xed\xef\x4f\x52\x7f\x65\x5a\x04\x3b\xad\x97\xf7\xe4\xae\x13\x59\xf1\x58\xb1\x17\xe2\xc8\x5e\x78\x34\xd6\xe1\xd3\x40\x4f\x10\x28\x4f\x77\xad\x20\x33\x75\x07\x9a\xef\x5e\x20\x12\x00\xf6\xee\xf0\xd2\xa9\x7b\xdb\x41\x9e\xd4\x1d\x9d\x7b\x5f\x6f\x95\xa0\x12\xf2\x00\xf7\xdf\xc3\xb0\x8d\xed\x06\xf8\x4c\x81\x10\xfe\xb9\xd8\x0e\xad\x81\x3c\xfd\x86\x7a\xbe\xa7\x61\x3d\x24\x73\xb7\xf6\x10\xec\xf8\x1e\xca\x1b\x16\x3d\xf4\x60\xb1\x62\xfd\x91\xf2\x2a\x48\x0f\x9d\x60\x11\xfa\x7d\x5f\xdf\xa6\xd0\xce\x1e\x56\xa1\xed\x3d\xec\x2d\xf1\x30\x56\x35\xae\x4c\xd8\x97\x02\x09\xfb\x03\x85\x91\xa9\x48\x79\xd2\xd4\xc3\xf7\x45\x4e\x7e\x60\x35\xc3\x79\x4c\xdc\xc3\x69\x16\x7a\x78\x75\x36\x76\x3f\x40\xfb\x3b\x91\x40\x24\x89\x41\xfa\xfc\x57\x6d\xed\xa0\x3c\xb5\xed\x6b\x43\x7c\xdd\xd7\xbe\xc3\x28\xf5\x85\x45\x5d\xa5\xa7\x17\xf2\xf7\x55\x69\x72\x3b\x61\x44\x5f\x1d\x2a\xb6\x10\xd4\xf5\x15\xef\x17\xb4\xbe\xde\x19\xac\xe0\x8e\xef\x34\x5b\x7d\x0d\x54\x9f\xa9\xaf\xbf\x3f\x48\xfa\x09\xa9\xb6\xa7\xff\x96\xf0\x12\xcd\x7f\x4b\xda\x5c\x15\x69\x60\x37\xfe\xb7\x74\x70\x6d\xfe\x5b\x40\xb0\x70\x3f\x20\x7f\xe9\xbf\x85\x29\x85\x6c\xb0\x1c\x21\x39\xc3\x67\x31\xf6\xe5\x77\x97\x90\x5d\x02\xd4\x3c\x05\x80\x0b\x03\xe2\x77\x91\x42\x80\xbc\x03\xd8\x34\x04\xc3\x0f\x69\x80\xc1\xaf\x2d\x0a\xe9\xb6\xa7\xc0\xb2\xf1\x3b\x42\xbc\x67\x09\x21\xb0\x1c\x21\x77\x0a\xf9\xf3\x48\xef\x2d\x14\x7e\x69\x44\x9c\x83\xce\x15\x48\x38\xf4\xfd\x12\x1c\xca\xef\xb1\xa1\x59\x61\x31\x43\x33\xd4\x3f\x34\x7b\xb0\x90\x5f\x46\x42\xb9\x6e\xa1\x07\x9d\x50\x28\x83\x9f\xd0\x03\x7b\x3e\xf4\x34\xb2\x3d\x43\x51\x76\x52\x69\x43\x7f\xde\xaa\x45\x7e\x41\xb9\x37\x42\x0b\xc2\x77\xde\x5d\x08\x25\x46\x0b\xfd\x07\x60\x42\x89\x2c\x42\xe9\x91\x43\xdb\xce\xcc\xa6\x77\xa2\x65\x0a\xa5\x95\x86\xa6\x1a\x0a\x3a\xd0\x51\xe8\xbb\x2b\x43\x79\x7b\x27\xf4\xbd\x70\x14\x3a\xf2\x62\xa2\x8c\x52\x43\x79\x55\x24\x74\xf8\x0a\x56\x1f\xdd\x1b\x07\x34\x56\x41\xc1\x7c\x9b\xcd\x78\xb9\xce\x15\xe8\x6a\xb5\x77\x66\xdf\x57\x7c\x5f\xe3\x60\x78\x36\x15\xd7\x33\xaf\x9a\xc2\x36\xfc\x36\x54\xc3\x26\xa1\x91\xe7\x46\x79\x3f\xea\x87\x1d\xe8\x9f\x2e\x17\x2e\x61\x4f\x3c\x9e\x0f\x73\xbc\xf3\x7e\x0d\xbf\xf1\x87\x11\x3f\x04\x4f\x0b\x83\x5f\x78\x02\x38\x3b\xf8\xb5\x32\x7c\x73\xd2\xc5\x17\x46\x6d\xe1\x95\x07\x39\xdc\x2c\xe1\xfe\x31\x3e\xd7\x14\xd0\xe2\x70\x86\xc7\xc1\x53\xea\xf7\x02\x4e\xc0\xdb\xa4\x20\xe0\x8e\xb5\x51\xe6\x08\x84\x63\x9d\x29\x00\x77\x62\x35\xfc\x6e\x79\x52\x2c\xc0\x87\x21\x3b\x7e\xf0\x2d\x43\x76\x46\xdf\x43\x0e\xbc\x18\x0a\x0b\x8b\x0b\xc2\x94\x21\xe5\xa5\x13\x04\xfd\x0c\xe0\x9d\xf1\x1e\x34\x0f\x44\xa1\x43\xa6\x8d\xe3\x41\xea\xe3\xb2\x34\x04\x2a\x35\x64\x11\x85\x0e\x38\x8e\x21\x4f\x1a\x19\x01\xf5\x80\x77\x18\x19\xca\x3d\xf2\x0b\x97\x47\xd6\x86\xb7\x4b\x2b\x13\x58\xc8\x91\x8d\xe7\xac\x23\xdb\x18\x1e\x23\x8d\xec\xc1\x0f\xe7\x23\xfb\x9a\x69\xe4\x90\x0e\x8a\x58\x73\xe4\xb0\xce\xbc\xb5\xa5\xa1\x82\x1f\x80\xfd\x78\xb7\xc5\xc0\xca\x0f\xcd\xb0\xc1\x43\x33\x74\x19\xb1\x38\x99\x69\x7e\x6d\xc4\x00\x26\x1b\xaa\x9f\x34\xf4\xa4\x8f\x1b\xfc\xa2\x81\xa4\xa4\x01\x0d\x96\x48\x43\x19\xf3\x0e\x86\x5d\xb0\xa7\xef\x18\x35\x4c\x07\x12\x7e\x2a\x1b\x3a\xc6\xcb\x9b\x01\xd6\xd0\xb9\x7a\x1a\xb0\xb7\x69\x5c\x8c\x05\xc6\x25\xc7\x04\xe5\x21\xce\xb8\x28\x8c\x0b\x03\xb8\xd8\xdb\xa5\x61\xc7\x91\xc6\xc5\xd3\xe3\x71\x19\x6b\x03\xd3\x8c\xcb\x3a\x08\xb4\x68\x5c\x08\xcb\xc6\xe5\xc8\x76\x47\x15\x47\x21\xb6\xcb\xb8\x7c\xf1\xb3\xcc\xb8\xb0\xe7\xc6\x15\x56\x51\x06\x8d\x18\xd7\x3a\xa0\xba\xe3\x7a\x12\x9c\x0d\xb4\x76\xc0\xb4\x11\xa3\x0c\x53\x2c\x1a\xd5\x9a\xdf\x0a\x87\x15\x8a\x03\xf1\xc2\x30\xd8\xad\x61\x85\xfd\x5b\x35\xd8\x83\x61\xaf\x2a\xf0\xeb\xf6\x78\xb9\x05\x26\x6b\x44\x33\x03\xfa\x0f\xb5\xb1\xdf\x34\xe0\x3b\xc6\x87\xaf\x3c\x1b\x48\xe3\x63\xf8\x61\xd6\x30\xe6\xe3\x63\x18\xfd\x07\xb6\x7e\x20\xb8\x1f\x45\x6a\x1a\x45\xb5\x83\xd2\x72\x0c\x7a\xd4\xc1\x93\xcd\xf1\x46\xbc\xa3\x18\x6a\x39\x60\xda\x80\xdb\x1f\x14\x2c\xcf\xb1\x47\x85\x15\x1c\x55\xc0\xb8\x22\x22\x19\xd5\x3f\xa4\x3e\xaf\x34\x1a\x8c\xf5\x68\x88\x61\x46\x83\x4e\x35\xca\x1e\xb0\x77\x38\xde\x3d\x67\xf4\xea\xfc\x92\x3d\x28\x73\xdf\x25\x0d\xc7\xaa\xd0\xd3\x0f\x2f\xbb\xb1\x4e\xb1\x1d\xf4\xbd\x30\x32\x78\x5e\x33\xbc\x2a\x00\xcd\x40\xc8\x3c\x9c\xf9\x08\xd5\x06\xd7\xc9\x17\x78\x62\x13\x0f\x87\x9a\xbc\x56\x6c\xf8\xc2\xd0\x3a\x0c\xe0\xa0\xff\x1e\x00\x67\xe8\xbf\xcb\xdd\xd2\xe8\x2a\x1f\xd0\x77\x4c\x9d\xca\xdb\xa9\x3b\xfc\x24\x3c\xfa\xa5\x6c\x44\x49\x75\x5e\x44\x18\xdd\x3e\x7c\x41\x73\x43\xc8\x38\x7a\x21\x05\xbc\xa6\xd5\x84\x6a\x77\x8e\x90\x36\x77\x74\x48\xb2\x07\xf6\x6e\xe7\xe5\xa6\xd1\x69\xe3\x46\x7f\xd2\x80\x7f\x54\x24\xbc\xef\x84\xb0\x8c\x37\xd5\xc6\x1b\x4f\x8c\x29\xbb\xad\x8a\x14\xd2\x9c\xb4\x04\x53\x0c\x3b\x79\xc2\xef\x8d\x49\xd3\x31\xb9\x2c\xb4\x68\x63\xa2\xa3\xc9\x99\x4d\x25\x2b\x05\x03\x2c\xfd\xd4\x50\x4f\xc0\x65\x28\xa4\xba\x4c\x8e\x64\x72\x3d\xa6\x57\x81\x32\x4d\x0a\x7a\xd2\x80\xf0\x18\x75\x4c\xaa\xff\x84\x1f\x3d\xf1\x1a\x8a\xdd\x3f\x83\xb2\x98\xc1\x35\x99\xb1\x78\xba\x3e\xe6\xe2\x0d\xd8\x31\x17\xc7\xfc\x9e\x83\x8e\xf9\x80\xae\x37\xc0\x19\x6b\x03\x5c\x1d\x6b\x83\x31\x1d\xeb\xbd\x3c\x3b\x10\x5f\x8e\xc5\x93\xdd\xb1\x18\xc0\x8c\x75\x0a\xe9\x89\x10\x8e\x07\x48\x63\xf1\x18\x7a\x2c\x54\x6a\x0d\xcd\xdb\xc0\x70\x56\x67\x76\x47\x40\x3a\x56\x0f\xda\x41\x20\xdb\xb1\x82\xdf\xc7\xc6\x42\xa0\x3f\x56\x00\x8c\xf1\xe1\x35\xfc\x63\xc5\x57\xd1\xe6\xbd\x45\x39\xd6\x60\x9c\x35\xee\x7f\x96\xe5\xa6\xa4\x6f\x21\x89\x9a\xc6\x0d\xac\x3e\x6e\x0a\xe1\xa6\x59\xb9\xb1\x73\x6e\xca\xf2\x26\x24\x1e\x37\xf0\xc1\x78\xea\x06\x29\x3e\xb5\x4f\xaf\x69\x3c\x01\xed\x7c\xb8\x24\xef\x0a\x4f\xe1\x0d\xa2\x29\x67\xe2\xbd\x81\x29\xb4\x13\x53\xca\x27\x4d\x69\x20\x1d\xc5\xfc\x14\x34\x65\x20\x63\x4c\xe4\xcc\xe9\x9e\xa6\xfc\x5a\x9a\xbc\xbd\x38\x55\x6a\x9a\xd0\x5e\x04\x7b\x53\x1b\x02\x89\xa9\xad\xd9\x40\x82\xe7\x40\x85\x81\xa7\xdf\x99\xe6\x45\xf6\x97\xe0\x11\xb2\x9a\x17\xda\x5d\x8a\x15\x9f\xd4\xfc\x79\x29\x1e\x31\xad\x79\x81\xcd\xe5\xbc\xd1\x35\xaf\x50\x94\xf2\x6b\xfb\xbc\x10\xab\xcf\x6b\xd5\x0d\x94\xc6\x65\xbe\x77\x5c\x26\x8c\xcb\xb4\x93\x39\x05\xef\x44\x32\xd3\xd0\x9b\xb5\x27\x4d\xeb\x09\xc8\x62\x4f\xf3\x3d\x7c\x9d\x06\x63\x3f\xe9\xd4\xa7\x6f\x80\x83\x69\xfa\x2e\x0f\xe8\x5e\xd0\xd8\x51\x7e\x2a\xc1\xdc\x74\x2b\xe8\x87\xd7\xfe\xa0\xbe\x13\xd5\xeb\x7b\x09\x91\x6a\x3c\xbd\x9d\x8b\x09\x4d\x1c\x95\x7a\xd2\x64\x4d\xef\xf8\x59\x06\xed\xec\x15\xde\x6e\x7a\x34\xd9\xc1\x26\x26\x83\xff\xe9\x63\xa4\xe9\x53\xd0\x70\x85\x71\x64\x84\x38\x93\xa1\xc3\x44\x00\x3a\xfd\x49\x93\x80\x75\x32\x5a\x9c\x21\x08\xbd\x91\x9e\x6f\x62\x0d\xb4\x0d\x68\xf5\x84\xd7\x9d\xbc\x39\x34\x81\x47\x4b\xe2\xbd\xd0\x17\x5c\x4d\xca\x16\xf8\x2e\x4d\x1e\x8d\x4d\x5e\x3d\x99\xbc\x0a\x39\xc3\x4e\x8a\x33\xac\x82\x80\x8d\xf7\x0b\x6d\xdf\x9b\x14\x33\x16\xab\x2d\x3e\x16\x14\xac\x8a\x78\x70\x06\xb0\xd1\x0c\x98\xc4\x89\x15\x5e\x60\xba\xde\x80\xe9\xdf\x26\x9d\xab\x09\x08\x42\xe1\xb9\xe2\x83\xd5\x07\xd0\x9b\x2b\xb8\x2c\xb7\xc2\x14\xcf\x5b\xdb\x7c\xd2\xbc\x61\x16\xe7\x8d\x89\xdd\x94\xca\xed\x69\x3e\xd0\xd6\xa7\x33\xcc\x5c\x67\x79\xd2\xaa\x5b\x68\x29\x92\xd6\x7b\xd5\x60\xb5\xf7\x36\xf0\x6a\x99\x6f\xef\xc5\x94\x57\x6d\x56\xdb\x3d\xad\xc6\x2b\xea\xab\xf1\x13\xe9\x6a\xef\x27\xa6\xd5\x8c\x98\x7a\x35\x5e\xcd\x5e\xcd\x26\xc8\x57\x11\x8c\xac\xf6\x69\x58\x85\xd5\x78\xc6\xba\xda\xb4\x92\x56\x5b\xbc\xa7\xb8\xda\x57\xf1\xda\x79\x9a\xb9\xfa\xc9\x05\x5a\x9d\x9f\x83\x56\xf7\x96\x16\x43\xe9\xd5\x61\x45\x56\x6c\xd2\x12\x0d\xc5\x0b\xbc\x80\xe0\x79\xe5\x7c\x0d\x3d\x56\x41\xc2\x0b\x12\xff\x98\xcf\xf7\x3f\x03\x5f\xc9\xd8\x6e\x5f\xc9\x6b\xd5\xf4\x15\xe8\xdc\x57\xe0\xc7\xbe\xef\x3d\xf8\xaf\x40\x74\x5f\x69\xf8\xd9\xb8\xd2\x57\xba\x47\xfa\xca\x7b\x15\xeb\x0b\x85\xff\xf2\x83\xfa\x57\x2f\x83\x68\xbe\x10\x36\x5e\xdb\x8e\x8a\xbc\x14\x89\xdc\x06\xd6\x1a\x1b\x88\x1d\x0f\x12\x02\xa5\x2f\x82\xdb\xaf\x8e\xa1\x25\x7d\x75\x6a\xa0\x2f\xa3\xcc\xbf\xb6\xf1\x0b\xe2\xd7\xf2\xdb\x9b\x65\xda\x75\x04\x88\x9e\x88\xda\xbf\x56\x0a\xa6\xfb\xb5\x36\xdf\xd4\x8b\x81\x41\x10\x77\x7f\x2d\xd8\x6e\x08\x88\x81\xd5\x78\xf3\x27\xe9\x17\x33\xe5\x29\xf7\x97\x17\x25\x79\xf9\xfb\xeb\x25\x4b\x73\xa4\xab\x22\x6f\x82\x3c\x60\x7f\xff\x23\xde\xd2\x2d\x36\xd3\x0d\x7b\x07\x7b\x0b\xd2\x16\x32\x1a\x48\x1c\xd0\x15\x5a\xdd\x5b\x02\xc1\x74\xba\xb1\x6d\x6e\x19\x1d\x64\xa2\x10\xf8\xe8\x06\x3e\x86\x33\xb9\xdf\xef\x8a\xb7\x0a\x96\x96\x96\xfa\x46\x6c\x55\x90\xd0\x68\xdc\xba\xa5\x5b\xdf\x70\xf8\x56\xfd\x60\xa7\xdd\x6a\x01\x5a\xf8\xcd\xeb\x86\x91\xbc\x75\xa6\x9b\x5f\xaf\x6e\xd8\xc8\xfb\xd2\x97\x82\x13\x2c\xe5\x4d\x13\x79\x03\x4a\xde\x97\x31\x02\xbf\x61\xef\x6e\xdb\xd1\xbf\x1d\x78\x2c\x3b\x48\x49\xd8\x25\xb7\x35\xc0\xd6\x1b\x08\x94\xae\xe2\xb6\xf6\x01\x69\x6c\xca\x4b\x31\x37\xc2\xac\xdb\x06\xc2\xd8\x1b\xd6\xe7\x86\xae\xdc\xff\xee\x28\xdc\x5e\x8e\x74\x23\xae\x49\xb7\x73\xc7\xdc\xee\x3b\x48\x49\xf4\x37\x3c\xdc\xbc\x3d\x0a\x1f\xe3\x01\xc5\x60\x60\x6f\xee\xd0\xfc\x01\xe5\x25\xde\x9b\x86\xec\xe6\xcd\x8d\x9b\x0e\xfc\x81\x49\x7b\x20\xaf\x47\xe9\xf7\x1e\x5f\xf8\xa1\x88\x40\xea\x4f\xb7\x90\xf4\xa7\xe1\x89\x47\x6b\x7f\xee\xe9\xff\x00\x00\x00\xff\xff\x96\xd2\xdb\xc1\x3c\x33\x00\x00") - -func keysWordsWordlistEnglishTxtBytes() ([]byte, error) { - return bindataRead( - _keysWordsWordlistEnglishTxt, - "keys/words/wordlist/english.txt", - ) -} - -func keysWordsWordlistEnglishTxt() (*asset, error) { - bytes, err := keysWordsWordlistEnglishTxtBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "keys/words/wordlist/english.txt", size: 13116, mode: os.FileMode(420), modTime: time.Unix(1523115814, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _keysWordsWordlistJapaneseTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\x5c\xff\x72\xe2\xb8\xd2\xfd\x9f\xa7\x5e\xbc\x5c\x2f\x01\x3c\x0e\x71\x1c\xc7\x61\x58\x87\x8a\x2f\x43\x60\x80\x0c\x59\xb8\x93\x8f\x2c\x3c\x8c\x5f\xe4\x2b\xf5\xe9\x3e\xea\x99\xaa\x54\xea\x1c\x59\xd6\xcf\x56\x77\xab\x25\xd3\xf5\x93\xae\x3f\xe8\xfa\x45\xd7\xcf\xbb\x7e\xd5\x25\x45\xcf\x92\xca\xae\xdf\x92\x3c\x03\x8d\xba\xfe\xdf\x5d\x72\x03\x32\xee\xfa\x8b\x2e\xf9\x93\xef\x64\x5d\x32\x06\x9a\x76\xfd\x49\xd7\x6f\x8c\x58\x72\x11\x92\x93\x09\x79\xd9\xf5\x07\x44\x07\xa0\x4a\xfe\xaf\x40\x1e\xbb\x24\xef\xfa\x29\xc8\x53\xa8\xd1\x5e\x7d\xea\xfa\x19\xd0\xbc\xeb\x9f\x80\x9a\xae\x3f\x64\x86\x26\xfc\x25\x7d\xc7\x93\x51\xd7\xbf\x74\xfd\x21\xb9\x3e\x69\xd9\x8a\x56\xfa\xa4\xd5\xbd\xc8\x70\xfc\xa7\xeb\xe7\x7c\x78\xe9\x92\x91\x11\x57\xf4\xb2\xeb\xaf\x89\xf6\x92\x4d\x9f\x1c\x88\x4e\x1c\xb5\x13\xd3\x8e\x7e\x2c\x2e\x6c\xc5\xa5\xeb\xbf\x1a\x4a\x06\xd2\xa4\x9a\x5c\xeb\xbf\x76\x49\xd2\xf5\x77\x42\x42\x4b\x46\x5d\x1f\xe5\x84\x17\x58\x7f\x92\x76\xc9\x1f\x40\x37\x32\x8b\xb7\x5d\xff\x42\x5e\x11\xd5\x5d\xff\x91\xc4\x8f\x5a\x72\x23\x65\x44\x92\x5b\x5b\x42\x8d\x93\xae\xbf\xb2\xe1\x0a\x4f\x66\xcc\x99\x87\xa1\x30\x52\x58\xcf\x12\x99\x7f\x47\x0a\xa2\xaf\x26\x44\x81\x2c\x7d\x9e\xb5\x27\x3a\x00\x03\x88\x24\xda\x32\x08\x52\x29\x6f\x0f\x58\x3c\x50\x0e\x94\x89\xd8\x0e\x48\xd6\x2c\x24\xe3\x28\x0e\x28\xbd\x03\x59\x08\x8f\x44\x27\x96\x3d\xed\xfa\x6f\x98\x69\x21\x96\x5c\x60\x08\x74\x0d\x11\xb5\x3d\x5b\x44\x17\x11\xea\x81\x71\x7b\xaf\x82\x04\x0f\x44\xca\xff\xc3\x42\x1e\xbb\xe4\x2f\x4f\x72\x36\xeb\xa9\xeb\x5f\x0d\x25\x13\xa0\x19\x0b\x9e\x05\xe1\xef\xbf\x93\x8c\xfd\x13\xad\xe8\x2b\x2b\x9f\x77\xfd\xb4\x4b\x32\x56\x34\x97\x01\x8b\xcd\x7c\xf6\x48\x3b\xd5\x48\xc5\x37\x24\x57\x43\x41\x16\x12\x90\x85\x8c\x75\x4a\xf2\x48\xf4\x4a\xf4\x46\x74\x32\x94\x8c\xfc\x10\xb4\x10\xe6\x41\x5c\x83\xd6\xec\x17\xdf\xe3\x17\x74\x83\xa4\xf1\xd9\x16\x44\x4b\xff\xc2\xbf\x7c\x61\xd9\xf5\x1f\x0c\xd9\x7b\xaf\x7c\xba\x82\x70\x0e\x28\x7f\x40\xda\xac\x6d\x97\xfc\x41\x21\xda\xb1\xb2\x1d\xa7\x6a\xcf\xf9\x7f\x73\x69\x56\xcd\x3b\x27\xe4\xc0\xb4\x23\x87\xf9\x27\xd3\xce\x6c\xce\xd5\xd2\x82\xbc\xa6\x50\x8f\x20\x8d\x89\x42\x92\x58\x8b\x12\x91\x7e\xad\x36\x10\xac\x92\x64\x28\xfa\xb3\x20\x41\x7d\xa2\x19\x88\x6a\x96\x3d\x12\x6d\xb1\x30\x12\x85\x32\xe1\x1a\x0b\xda\x8b\xeb\x27\x89\x55\x66\xa2\x87\x8b\xae\xff\x8f\x0d\x43\x50\x08\x03\xa2\x94\x28\xb6\x27\x37\xb9\x08\x02\x9f\xb2\xa8\xa2\xeb\xdf\xd9\xca\xef\x33\xa9\x64\xb9\x85\x08\x48\x6c\x5b\x21\x3d\x0b\x24\x95\xf5\x90\x19\x92\x02\x53\x91\xce\x07\x20\xed\x46\x2a\x4b\xe5\x44\xf4\xc1\xac\x59\x97\xe4\x40\xb9\xe9\xcf\x35\xf9\x04\xe3\x9e\x8a\x5a\x68\xa4\x7d\x39\xdf\x9c\x8a\x0c\x4f\x49\x56\xee\x49\x18\xb1\x96\x44\x93\xef\xa9\xe5\x41\xb4\xde\x02\xc3\x93\x4a\x8f\xbf\x00\x55\x22\x88\xa9\x91\x30\xd8\x13\xac\xc5\x54\xa6\x6f\x40\xf4\x85\xe8\x96\xb3\x2c\xdc\xf4\x7b\x2a\xab\x49\x1b\xb3\xa0\x16\x27\x9f\x70\x00\x16\x1c\xc9\x05\x17\x6a\x2a\x0b\x6a\x0c\xa9\x4b\xa5\xc7\x39\x55\x48\xaa\x2b\xd2\x8d\x7c\x4b\xf4\xca\x6e\xad\xd9\xca\x35\x74\x05\xd0\x13\x47\x60\xcd\x97\xb6\x44\x3b\xd6\x7f\xea\xfa\x77\x44\xf7\x30\xed\xa9\xcc\xc5\xc4\x72\xc7\xbe\xca\xd2\x01\x12\x1b\x69\x64\x68\x95\x85\x31\x9a\x88\xd4\xd4\xe4\xba\x04\x40\xd6\xd6\x37\x51\x78\x56\x77\x20\x99\x49\x43\x32\xa6\x57\x93\xca\x4a\xa9\x1c\x49\x52\x1b\x46\xd7\xbe\x0c\x9a\x26\x95\xb1\xcf\x88\x4a\xa0\x82\xf6\x05\x64\x61\x43\x07\x3b\xe9\x88\xea\xae\xa1\xc8\xe9\x10\x4f\x40\x26\x44\x19\x97\x0a\xf8\x3d\x91\x6a\x55\x90\x93\x7b\xdb\x96\x13\x48\x0e\x34\xc2\xa4\x0f\x65\xbc\x22\xd2\xa7\x99\x4c\xbc\x16\x17\xdd\x82\xa1\x88\xeb\x9f\xcc\x56\x77\xfd\x25\x50\x2b\xae\x85\x56\xb9\xeb\xfa\xb7\x40\x67\x9d\x4c\x19\x15\xe1\x96\x87\x69\x61\x4e\x1f\x89\x76\x40\x37\x56\x79\x40\x27\x20\xb5\x50\x50\x4b\x1c\x9d\x40\xc6\xcc\x5d\x40\x18\x87\xaa\x75\xac\x8a\xc2\xfc\xc0\x94\xfc\x2b\x56\x0d\xc8\xdc\x7a\xa4\xf3\xf3\x97\xcf\xb9\x42\xce\x91\x8c\xeb\x98\x4b\x7e\x64\x5e\x42\x4d\xa2\x82\x32\x32\x0b\x98\x83\xa4\x6c\xee\xc8\x14\xc1\x85\xe4\x91\x68\xc6\x7a\x52\x8e\x3e\xc8\xd1\x17\xf5\xe1\x9e\xd8\xcc\x8e\xb8\x48\x47\x74\x94\x46\x34\xe3\x40\xaf\x9c\x73\xe1\x09\xf3\x84\x42\xe6\x20\x63\x0c\x34\xc9\x13\xd0\x04\x2e\xa8\xa4\x05\x15\xa9\x19\xbe\x50\x8d\x8d\xe8\x7a\x8d\x44\x5c\x62\x0f\x73\xef\x0d\x09\x57\xaf\x73\x4d\xce\xd7\x6c\x45\x8d\xfc\xb0\x16\xbe\x92\x82\x19\x4a\xdf\xe3\x92\xeb\x5a\x88\xe9\x8b\x11\x66\x04\xeb\x1a\x24\xbe\xf3\x08\x49\x01\x2a\x39\x3d\x22\xde\xf6\xc2\x5c\xc4\x2f\x27\x89\x8d\x6d\x68\x7b\x40\x34\xcf\x33\x9c\x7d\x90\x85\x97\x81\x17\x18\xe5\x91\xac\x14\x1d\xbf\x6f\x10\x27\x90\x95\xd4\xad\x2b\x00\x7c\xed\x25\xea\x95\xaf\xbd\x8a\xc2\x19\x73\x84\xde\x7c\xfb\x2f\xb0\xf5\x42\x92\xbe\xd4\xb1\xb2\xe1\x4b\xb0\x0d\xfc\x46\x12\x93\x29\x6e\x81\x84\x0d\x21\xc8\xc0\x44\x32\x19\x88\xe6\x7b\xef\x99\xc0\x7c\x5a\xf5\xb2\xec\xb1\xb7\x1c\x49\xc3\x34\xb9\xa0\x3a\x01\x99\xb2\x06\x2c\xc6\x3f\x49\x66\xd6\x78\x29\xc7\x93\x68\xa8\x46\xa6\x1f\xb5\x98\x31\x76\x70\x40\xaa\x1f\x27\xd0\x8f\x44\xea\xde\x4f\xbc\x87\x3f\xf6\xbb\xe2\xb1\x2e\x5a\x69\x0b\x48\xed\x1d\xab\xb1\x77\xb8\x41\xfe\x86\xf1\x23\x6f\x7d\xb1\x4b\x9f\x73\xe5\x9f\xe8\x02\x9e\xa8\x73\x28\x8d\x1c\x7b\xff\x70\xec\xf5\xf4\xc4\xfb\x74\x63\x2a\xed\x31\xc5\x77\xcc\xa5\x3c\xfe\x2d\x79\xc2\x96\x4f\xb0\x39\x1c\xd3\xb5\x18\xcb\x62\xbc\x27\x5a\x31\xeb\x03\x5e\x9f\xa0\x7b\x48\x6b\x58\x7b\x03\xf3\x39\xf1\x8a\x71\x22\x02\x9d\x71\x7a\xc0\x0b\x4f\x4a\x8e\xfe\x8b\xf7\xef\xc6\x22\xd6\x0f\x62\x1f\xb5\x7d\x3b\xbe\xb6\x67\x93\x4e\x58\x45\x63\x3f\x40\x67\xb6\xfe\xc2\xb4\x8b\x48\x22\x46\x3d\x2c\xfb\x09\x37\x92\x63\x11\x58\xf4\x41\x06\x16\xd2\x3b\x76\x03\x9b\x8c\x89\x32\x2b\x31\xb4\x2b\x37\x24\x1b\xa5\x09\x4c\x0c\xd2\x0a\x27\x81\xce\xb0\x8f\xbd\x54\x8f\xcd\xa4\xc4\x27\x0d\xdb\x54\xd8\x68\x06\xa4\x1b\x8b\x0c\x01\x1a\xa2\x16\x28\x78\xe1\x3d\xd1\xb2\x03\xbc\x9e\x49\x2f\x06\x86\x2c\x6d\xc8\x52\x54\xdf\x03\xe5\x44\x0b\x43\xf6\xc6\x98\xa5\x8c\x99\xef\x97\x2e\x64\xf2\xb7\x04\xca\xa5\xa1\x23\x23\x61\xfc\xee\x40\xa6\xba\x7e\xad\xb4\x82\xf5\x17\xbe\x59\x05\x2b\x29\x99\xb5\xf4\x69\x17\x43\xa1\xec\x2f\xe8\xf3\xa3\x97\xe7\x2f\xdc\x6a\xe3\x49\xe3\x17\x38\x92\x36\x7e\xa3\xf8\xc5\x36\xe4\xad\xef\x52\xcd\xe6\xc5\x26\xeb\xc6\x3a\xa3\xf9\xcd\x38\x75\x99\xac\x87\xdc\x90\x0d\x5e\xe3\xbb\x16\x97\x44\x26\x95\x0d\xd9\xa4\x17\xec\x89\xf9\xa4\x65\x45\x6d\xd7\xdf\x02\x2d\xd9\x8c\x57\x16\xf2\xca\x2a\xd7\x7c\xba\x86\x82\x03\xd2\x66\x7c\x17\x6f\xb9\x02\xd9\xb2\x75\x3b\x16\xb4\x93\x31\x6b\x40\xf6\x2c\xf5\x9d\x46\x25\xe3\xde\x35\xa3\x86\xca\xe8\x39\x66\xb2\xb2\xb4\xac\x33\xd3\x2e\xec\xfa\xd5\xc6\x2b\xf9\x43\xe3\x7a\xb1\x60\xb3\xc0\x08\xce\x3c\x8b\x25\xaa\xc8\x17\x3d\x1f\xb6\xc9\xe8\x50\x66\x62\x70\x30\xdf\xa2\x59\x64\x56\xf5\xc9\xd0\x1a\x23\x03\xee\xa3\x0d\x19\x97\x74\x46\x7b\x9d\x49\x06\xb4\xd9\x36\xbb\x40\xda\xe6\x8c\x15\x65\xcc\x97\xb3\xdd\x5f\x10\xf1\xc2\x02\xcc\xcc\xc7\xd4\x98\x12\x78\xf0\x6a\x8c\x38\xfd\x72\xcb\xb5\x9c\x23\xcc\x03\x94\x72\x9f\x0c\x92\x11\xdd\xfa\x64\x5d\x40\xb7\xe6\x0f\x0e\xf8\x64\xee\x9f\x34\xd0\x4c\xb9\x77\x0e\x41\x3e\x81\x62\x5d\x71\xbb\x90\x63\x1b\x8e\x42\x0a\xa6\x95\xac\xa5\x64\xb3\x4a\x46\xc9\x84\xc8\x90\xe4\xe6\xfa\x5f\x49\x62\xc1\xb5\x88\x5b\x66\x24\x8c\xbd\x8e\x87\xec\x1d\x44\x5f\xe4\xb4\xf4\xb7\xb6\x80\x97\x7c\xe7\xd9\xd7\xd3\x04\x29\x35\x67\x30\x17\x47\xaa\x60\xbd\x0b\xdf\xd0\x96\x32\x7e\x2b\x2b\xae\xc6\x8a\x93\x27\x61\x8a\x6f\x7b\x66\xea\x52\x9a\xe7\x9c\x6b\x2c\x97\xbd\xa9\xa6\x6d\xf1\x1f\x64\xc7\x9e\x1d\x89\xae\x7e\x73\x0d\xde\x30\x44\x1a\x45\x27\x87\x10\x63\x80\x7a\xa6\x30\x6b\xa2\x0f\x66\x1b\x43\xf1\xe5\xae\xab\x66\x87\x72\xd8\x47\x4c\xcd\xad\xca\x9f\x8e\x5d\x8c\x97\xe4\xe4\x8d\xcf\x19\xd4\xf6\x54\xc4\x70\x0d\x34\xa0\x9e\x9f\x7a\xbd\x09\x12\x91\x7a\x45\x77\x2e\x9e\xd9\xf2\xa1\xd6\x70\x67\xe1\xb2\x54\xb2\xf0\xe5\xb0\xb2\x32\x12\x45\xf0\x62\x6b\x23\xc9\x88\x6b\xfe\x0e\x26\x87\x48\x05\x13\xe4\xd9\x93\x85\x27\x2b\xb6\x30\xa8\x34\x43\xa6\x34\xee\x28\xd6\x77\x76\x16\x12\xb7\x1e\x77\xc1\xe9\x90\x2e\x4c\x29\x40\x92\x66\x7d\xa8\xd8\x81\x2a\x68\x56\xd9\xf0\x4c\xbd\x98\xdf\x31\xb2\x86\x68\xd1\x1b\x90\x9c\x9e\x04\xd9\xfb\x1f\xf9\x0d\x3b\xdd\xd2\x9e\x4f\x79\x46\x31\x55\x43\x61\xd5\xbd\x30\x46\x84\x27\xaa\x58\xa6\x16\x29\x8d\xd9\x96\xbe\x80\x0b\xc7\xa2\xf5\xfa\x07\x7c\xe2\x72\x9a\x82\xbb\xa3\xdc\x4b\x34\x2b\xac\xf0\xba\xe7\x43\x5b\x53\x31\x2f\x77\x44\x35\xd1\x15\xe8\x3b\x87\x6d\xcb\x4e\x6d\xd9\xf4\x3d\x25\xe4\xc0\xb4\x13\x7d\x8d\x3b\x31\x27\x5a\xbb\x1e\x01\x4c\x65\x11\x8d\xad\xf6\x60\x47\x2a\x43\x9a\xc1\x04\x66\x4a\x1d\x3f\x95\x45\x32\x35\x21\x73\xeb\x64\xca\x63\x8a\xa9\x86\x08\xb4\x91\x81\x8c\x88\x20\x75\x01\x65\x4c\xbb\xb3\x16\x3b\x9f\x6e\x6a\x61\xca\x9c\x24\xc6\x10\xc0\x6b\x93\x0c\xe7\xf0\x4d\x75\xe7\xe2\x5e\x5b\xfa\x56\xad\x7c\xb6\xb5\x7f\xb2\xb1\x79\x0a\xe4\xe4\x1b\x7f\x21\xba\xba\x86\x06\xa3\xca\xb7\x2d\xfa\x02\x12\x7a\x5b\x88\xec\xe5\x78\x5b\xac\x59\xff\x3b\xd1\x3b\x24\xf9\x9e\x1e\x65\xe1\xc3\x14\x85\x86\x59\x1d\x51\xf5\x73\x6f\x51\x55\x1d\x87\x7b\x0b\x8f\xc6\x32\x74\xf8\x0a\x0b\x75\xc4\x27\x8f\x44\x1a\xe3\xbc\xf7\x76\xae\x30\x3b\x97\x93\x34\xfe\x89\xee\x4a\x0b\x0b\x54\xc6\x4a\x96\x3e\xdb\xab\x7f\xb2\xf6\x4f\xf6\xbe\xd2\xb3\x6f\xff\xc5\xf5\x34\x48\x1c\x5b\x90\x8c\x30\x0d\xd1\x9d\x2d\xb8\xf5\xba\xa7\x6c\xdf\x8b\x9f\xda\x5a\x9a\x95\xa5\xbb\xad\xc2\x9b\xd9\x82\xf6\x88\x64\xed\x9f\xec\x59\xf9\x2d\x27\x2e\x8e\xee\x94\x6d\x28\x44\x09\x93\xc8\x62\x28\x10\xfb\x00\xaa\xd8\xf0\x9a\x95\xc5\x81\x56\xb5\x12\x0f\xed\x20\xbf\xcf\x30\x1e\x85\x1f\xf9\xc6\x77\xbd\x61\xa9\xd1\xf1\x2d\x10\x43\x06\x6a\x79\x6e\x06\xf2\xc6\xe2\x5b\xc4\xf1\x0a\x3f\x5d\x4b\x3e\x5d\xc9\x96\xe8\x86\xa4\x22\x7a\x33\x64\x42\xbd\x96\x61\x5e\x83\x6c\xf1\xbf\x67\x23\x72\xe1\xa8\xed\xa0\xb6\x04\x25\x43\xcc\xcd\x9e\xf5\x1d\xa0\x6a\x41\x8e\xec\xc8\x91\x19\x3e\x69\x95\xef\xa5\xd4\x78\xfc\x2b\x07\x19\x6e\xea\x2f\x74\x3b\xf0\xa4\x65\xe3\x2e\x36\x6e\x41\xb3\x7d\x81\xa9\x2d\x18\xef\x2c\xe8\x0b\x17\x54\x73\x82\xb4\x09\x66\xd6\x80\xd0\xab\xe0\x55\xa5\x44\xef\x40\x43\x1b\x4f\xf3\x91\x0b\x31\xb5\x5a\xf5\x24\x7a\x6b\x56\x70\x26\x33\x36\x05\xc9\xa5\xf2\x25\xc9\x84\x6f\x16\xdc\x78\x16\x3e\xca\x5a\x50\x77\x16\xbf\x29\xc5\xc2\x94\x62\xcc\x46\x89\x82\xea\x73\xa5\xad\x3d\x79\xef\xfa\x1b\x92\x7f\xfd\x93\x0b\x1b\x5a\x20\x64\x09\x34\x71\x95\xd8\x96\xfd\x41\xc3\xe6\xd2\xb6\xd2\xdc\x9e\x01\x89\xda\x41\x64\xbb\xf3\xa4\x60\x1e\x75\xda\x4a\x1f\x50\x7f\x30\x07\x28\x56\x12\x03\x53\xa5\x77\x64\x1f\x7e\x3b\x68\x2b\xa1\x84\x80\x34\xda\x04\x32\x81\x79\x45\x72\xcc\x70\x85\x40\x94\x3c\xfc\x2b\x65\x2f\x12\x8b\xcb\x59\x42\x4e\x3b\x5b\xc2\xb5\x04\xd2\xbd\x76\xc9\x75\x58\xfa\x4b\x17\x0f\x5c\xfa\x25\x83\x12\xa5\xf9\x23\xda\xd7\x96\x9a\xff\x81\x2b\x1b\xc9\x13\x96\xfd\x62\x1b\x8b\x9c\xd9\x2a\x16\xf5\xe8\xdf\x9e\xb3\xe9\x2d\xbd\xa6\xd2\x1c\x98\x41\x97\x24\xe0\x4b\x4e\xd4\xca\x27\xaf\xf8\xf6\x8a\x31\xeb\x92\x0a\xa2\xa4\xeb\x52\xd2\x65\xc7\xd6\x45\x9b\x19\xf7\xba\xa5\xc4\xcd\x75\x3c\xce\xcc\x7a\x46\x2c\x0f\x07\xfc\x3a\x21\x57\xff\xd2\x55\xdc\xd1\x89\x90\xb0\x8a\xa7\x3d\x1f\x60\x2e\x65\x69\x0e\xfd\xd9\x4d\xc9\x35\x5a\x72\x3d\x96\x8c\x28\x22\xc2\xf1\xdc\x43\xcc\x4d\x46\x07\x03\x92\xe4\x8c\x1c\x97\x8c\x33\x97\x7e\x0d\x96\x74\x5e\x80\xe2\xb6\xb9\xf4\x5e\x4b\x69\x5e\x0b\x66\xd3\x36\x0b\x7c\x52\xfb\x6c\x33\xeb\xa7\xf8\x2f\x44\x0b\xa2\x0b\xd1\xd5\x90\x39\x1a\x15\x37\xba\x15\x0f\xd2\x2a\xbb\x07\xf4\x82\x65\x5f\xf9\x2d\x93\x84\xe2\xa5\xc1\x15\x3b\x55\xc1\xb2\xf7\x34\x36\x6f\xc5\x8d\x30\xd0\x15\x17\x70\xc5\x1d\xcc\x23\x2d\xac\xb8\xe9\xe2\xc5\x54\xec\xd6\x23\x6f\x3d\x54\x22\x6d\x29\x0b\x6a\x10\x58\x02\x5a\x12\x5d\x81\xa2\x35\xab\xec\x2a\x83\x56\x11\x8f\x47\x2b\x9a\x0c\x41\xa6\xa8\x2b\x0a\x6f\x45\x3d\x00\xd4\xa2\x41\x6a\xe4\x1e\x29\x22\x38\xfd\xfd\x02\xb1\x12\x62\xea\xbf\xa2\x5a\xac\xc4\xb4\x5d\x0c\x59\x9a\x1e\xac\x01\x9d\x80\xf6\xac\xfd\xcd\xb7\x55\xaf\x2f\x08\x32\xdf\xb9\xa2\x09\xac\x44\x7b\xc4\x3e\x1f\x39\xba\x27\x66\xf8\xc9\x97\xce\xcc\x77\xe6\xd3\x0b\xd3\xd4\xcc\x55\xf4\x4e\x2b\x2c\x15\x24\x3f\xc2\xaf\x87\x0c\x56\x74\x5a\x2b\x2e\xa2\xca\x0d\x65\x10\xe9\x81\x27\xa9\x27\x23\x1b\xc9\x40\x26\xd4\x13\xd5\x6f\x3b\x6e\x3d\xa1\x74\xcd\x0e\x7c\xea\x4b\x8a\xe8\x81\xcd\xf9\x93\x57\xe7\x40\x66\x9e\xcc\x7d\x51\x8d\x7f\xc7\x8b\x8e\xee\x04\x33\xdf\xce\x8b\x3d\x89\x42\x25\x27\x4c\x28\xe3\x91\xea\xe2\xd1\x42\x5e\xb1\x17\xff\xf1\x2e\x21\x9e\xc7\x16\xfe\xc7\xef\x0f\xc1\xaf\x86\xc2\x7c\xbf\xd9\x3b\x1a\x68\xd6\xd7\xfe\xb2\x3b\x12\x03\xf2\x9c\xc6\x0d\xfc\xc5\x0f\xd6\x5f\x4e\x6c\x83\x0b\x91\x98\x58\x85\x3a\x66\x9c\xc1\x18\xd8\xa8\xa8\xa7\x2a\xaf\x97\x1e\x2d\x68\xf6\x27\x9f\xcc\x10\x68\x20\x5f\xb0\x11\x05\x07\xab\xa6\x6e\x01\xaa\x88\x82\xd1\x7c\xc2\x9d\xb2\x9e\x9e\xdb\x98\x06\x01\x19\x13\xa9\x15\x79\xf2\x07\xe3\x3c\xe8\x51\x3f\xaa\xb6\xfb\x24\x39\xc9\x23\xba\x5a\xeb\x26\xc5\x5e\x8b\x67\x71\x35\x22\xa2\x40\x7a\x27\xa6\xf6\x3e\x7d\xcd\x55\x50\x8b\xb2\xd2\xb4\x02\xfd\x78\xe2\x21\x49\x2d\xa4\x62\x86\x1a\xe1\x87\xda\x5f\xf4\xa8\xbd\x2e\x7a\xb2\x53\x95\x48\x56\xc8\xa3\x1a\xa8\x66\x64\xaa\xe6\xb5\x0b\x04\xe9\xb4\xbe\x3d\xcc\x50\x2d\xb2\x71\xc3\xca\x9f\xbc\x5e\x78\x92\x6d\xe8\x77\x28\xaa\x5a\x86\x4e\xbb\x7d\x64\xda\x07\xb4\x69\xcd\xf9\x7f\xe2\xba\xab\xc5\x8b\xd6\xfa\x2e\xd6\x39\x0b\x05\xd7\x3c\x81\xac\x65\xfd\xa2\xd5\xb8\xbf\x24\xce\x4c\x1d\x2c\xa4\x6c\x67\x6a\x59\x2e\x72\x99\xc5\x5e\xc8\x5c\x9f\xcd\x5c\xd6\xfe\x16\x62\xad\xae\xa4\xbc\x30\xf3\xfe\xfb\xcc\x3c\xc3\x96\x44\x9d\xc1\x28\x90\x33\x7f\x1c\x37\xe3\xc1\xca\xcc\xbc\xb8\x31\x5f\xc8\xb8\x6f\x9f\x21\x16\x4e\x94\x12\xe1\x84\x34\x65\xb6\x29\x51\xc1\x72\x6b\x56\xac\xda\x05\x68\x0a\xf4\x42\xfb\x37\x33\x0d\xa3\xc6\xff\xab\xf0\xf8\x24\x96\xfd\x42\x17\x70\xa6\x07\x72\xb2\xcc\x21\xb0\x33\x31\x66\x7f\xf3\xcd\x96\x61\x37\x90\x6f\xbe\x98\x1f\xfe\xc9\x3b\xd1\xc9\x25\x9b\x5a\x07\x19\xb1\x5e\xbd\x6f\x37\x13\xd1\xd3\x57\xf7\x50\x4e\x33\x89\xf2\x66\x40\x9f\xd8\xc4\xcd\x28\x28\x33\xda\x95\x19\x97\xc0\xcc\xdf\x96\x9b\x49\x35\xc7\x1e\x66\x1c\xb1\x0e\x24\x17\x56\x82\x06\x81\x22\x19\x13\x65\x50\xb2\x20\xf1\x3d\x15\x04\x94\x78\xcf\xe4\xd2\x17\x12\x34\x2c\x49\xed\x9f\xcc\x3c\xf9\x9b\xa8\xf1\x35\x44\x73\x31\xf3\xb1\xa1\x99\x8f\x0d\x81\x68\xb4\x0d\x64\x6b\x63\x1d\xc8\x0f\xbc\x83\x56\x9e\x88\xfe\x75\x6f\xab\x1c\x22\x4a\xe4\x8e\x2b\x90\x94\xb8\xd2\x6c\x9b\x09\x92\xfa\x32\x54\xfe\xbf\xc2\xed\x23\x1a\x51\xf8\x66\x7e\x2f\x06\x12\x9a\x3c\xe7\x6c\xcc\x4d\xff\xde\x61\x06\xc1\xb7\x3d\xbd\xbc\xaa\xc7\xa0\xf1\x8c\x62\xce\xc3\x11\xa0\x7b\x22\x35\x7c\x20\xcf\x9e\xac\x3d\x79\x37\x24\xdd\x26\x19\x01\xc5\x2b\x46\x73\xc6\xba\xe6\xbc\xc9\x31\xe7\x8d\xa1\x39\x57\xe6\xdc\x42\x23\x9a\xf5\x81\x59\x2b\x98\xa0\x39\xa7\x7d\x4e\x23\x31\x97\xbf\xdb\x1e\x63\x2a\xec\x7c\xcb\x52\x5b\xdf\x80\x17\x6a\x14\x3c\xf9\xe2\x07\xe4\x05\x71\x5c\x92\xc2\x3f\x99\xf9\x32\x56\x40\x2b\xde\xfa\x03\xf9\x2f\x26\x6f\x2e\xab\x71\xc8\xb6\xac\x71\x70\x32\x17\xe7\xef\x13\xe8\x93\xd3\xf6\xc9\xa9\xbc\xb0\xf2\x8b\xbd\x1b\x3c\xba\xdc\x50\x58\x86\x43\x90\x3e\x33\x24\xf8\x0f\x22\x97\x56\xfb\x5f\x7b\x76\xa1\x46\xef\x81\xce\x79\xdc\x31\xf7\xf1\x85\xb9\x3f\x65\x07\x79\xf0\xa4\xb2\xf6\xc8\x2a\x63\x43\x7e\x59\x5b\x7f\x23\xaa\x40\x74\xb2\x61\x72\x31\xd4\x86\x1b\x18\x1c\x46\x0d\x98\x3c\xa0\xb2\x6e\x7c\x48\x01\x44\x4d\xc1\x33\xae\x9d\xa0\xfa\x86\x37\x4f\x80\x6e\x91\xe7\x97\x53\xea\x86\x91\x06\x20\xed\xd3\x73\xe7\x2e\x8c\x63\x35\x3f\xdb\x4d\x94\x58\xa0\x9e\x4d\x83\xcc\x7d\x0b\x1a\xdf\x85\x38\x00\x3c\x5f\x8b\x75\xbc\x32\x50\x88\x87\x6b\xff\xe6\xd6\x57\xb0\xf3\x65\xe8\x86\x01\x65\x1c\x7e\xab\xe0\xe8\xc9\x4f\xdf\xd1\x33\xd1\x45\x03\x81\xb2\x5c\x90\x74\x95\x79\xb8\x35\x2e\xca\x0a\xa8\xef\xca\x48\xfc\x98\x9a\x32\x02\xb9\x21\x1a\x31\x0c\x01\x3e\x26\xca\x59\x54\x0a\x01\x8d\x91\xcc\x46\xa6\xb1\x36\x14\xd3\x2c\xfa\xd5\x50\x1a\x81\xb6\x40\x19\x64\xaa\xb1\x73\x51\x2d\xbf\x60\x03\x0a\xdf\xe8\x92\x25\x54\x3c\x68\x7a\xd6\x6d\x81\x98\xb0\xc6\x7b\x88\x8d\x39\x84\x39\xf9\x1c\x9f\xda\xf4\xf4\x43\x18\xfb\xae\xa5\xa1\x49\x69\xa4\xc0\x8a\xf5\xe8\x86\xb6\xc1\x15\x7d\x8c\xf8\xb3\x79\x0f\x03\x92\xe8\x3d\x80\x17\x44\x15\x4f\xfd\x9e\xed\xf2\xaf\x16\xbd\x64\xab\x56\x7e\x18\xd7\x52\x4f\x03\xb2\xe1\x88\x7c\xe7\x20\xe0\x16\x82\xb6\x6a\x4f\x29\x3b\x31\xeb\x07\xcb\xfa\x64\xf7\x2e\xd0\xfc\x0d\x55\xce\xb3\x28\x1a\xe4\x13\x57\xc3\xca\x0f\xa4\xee\xf9\x0f\x5e\x1a\xee\x51\x1a\x5c\x9c\xb7\x2e\x24\x6c\xb5\x1d\xd0\x35\x7a\xef\x57\x76\xb5\x30\x46\x96\x1a\xc5\x3c\xa1\x7c\x24\x63\xa8\xd8\xc6\x89\x49\x02\x0b\xa6\xc9\xd1\x2b\x6d\x64\x1e\xff\x60\xce\x67\xf3\x51\xb4\x61\x05\x5b\x55\x70\x5f\xdb\xd0\x47\x69\x18\x62\x6d\x54\x19\xba\x0c\xf7\x44\xa5\x4f\xa6\x0a\x79\x67\x75\x33\x5f\xc9\xdc\x44\xc6\x9d\x17\x3f\x33\xdc\xd3\x78\x67\xa4\xf1\xce\x08\xf2\xac\x99\xbc\x31\x41\x86\x5b\xe2\x3a\x44\xb5\x91\xc8\x67\x03\x2e\xdb\xa7\x7f\x72\x71\xef\x98\xdb\xf8\x6c\x8e\x44\x4b\x92\x11\x85\x66\x2f\xa8\xac\x17\xdc\xf3\x2d\x28\x07\x0b\x3b\xbf\xd6\x0c\x43\x66\x18\x33\x6d\x0c\xad\xb1\xf0\xa7\x57\x0b\xee\xd5\x17\x76\xce\xfd\x64\xc4\x92\x75\x71\x2f\x7c\xf9\x15\xab\xad\xbc\xb0\x2c\x38\xe4\x0b\x6a\xe9\x05\x07\x7b\xc1\x88\xeb\x42\xbf\xb1\x49\x34\x39\x1e\xfa\x2e\xb8\x81\x5b\x30\x70\xb4\xe0\x72\x12\x24\xbe\xcc\x82\xa3\xbd\xf0\x4a\x79\x81\xa0\x0d\xdd\x82\x05\xf7\x62\x0b\x19\xf7\x06\x48\x6f\xee\x00\xbd\x62\xa8\x17\xb6\xae\x5e\x7b\xfc\x22\xd0\x8e\x5b\x3e\x7a\x8c\x78\x5b\x57\x92\xd4\xab\xde\x85\xc9\x5e\x45\x82\x08\x35\x87\xd1\xbe\x55\x03\xba\xf6\x34\xca\x66\x77\x13\x17\xbf\x0e\x63\x58\x69\xda\x8e\xdc\xe6\xdf\x89\xed\x42\x9d\x58\xa9\xbb\xe5\x66\xbf\x35\x83\xb8\x00\x49\x99\x9c\xfa\x9b\x00\xad\x1e\x06\x4a\xcb\x5a\xdc\xd5\xef\xf9\xef\x06\x05\xd9\xc2\x6d\x79\x2d\xa4\xe5\x65\xe5\x16\x27\xdf\x86\x2c\xed\x9e\xaf\x47\x4b\xd3\x06\xf7\xcb\xda\xa9\xe1\x43\x41\x62\xf3\x5a\x09\x60\xf7\x99\x75\xcd\xb8\x7f\xcb\x73\xf7\x56\x56\xd9\x7f\x59\xdf\x8e\x19\x4e\xd0\x62\xf8\xa6\x31\x7e\xda\xd0\x52\x6b\xb6\x32\xc1\x59\xcf\x36\x68\x8d\x65\xb0\xef\x8c\x80\x90\xd5\x8e\x91\x5a\x19\xfd\x4f\xa2\xab\x35\x5f\x4f\x8a\x76\x24\xa1\x84\x25\xa3\x32\x40\x4b\xa2\x2b\x50\xfc\xb2\x6f\xc9\x89\x5a\x72\xe1\x2e\xd5\x43\x92\x9a\x97\x76\x51\x37\x27\xd1\x2b\x29\x4b\x1e\x9d\x2c\xfd\xc1\xcc\xd2\x7b\x40\x4b\x4a\xef\xd2\x3c\x9a\x98\x1c\x97\xc8\xd2\xbb\x2a\x20\x9f\x7c\xa2\xb1\xe8\x25\xef\xa3\x83\x64\x54\x86\x4b\x91\x86\xa0\x61\xbf\xe9\x29\x61\x5f\xcb\xf9\xe5\xa0\x06\xfc\x0e\xa8\xe6\x48\xcd\xf9\x74\xc1\x4d\xc7\xd2\x7b\x6d\x4b\x7f\xcc\xb2\x34\xe9\xc9\x50\x5d\xd8\x88\x33\xf9\xd3\xbd\x20\x6a\xe4\x9b\x68\x89\x31\x3c\x9d\x25\x55\x06\xd0\x2d\xeb\xda\xc9\x58\xdc\xf4\xec\x33\x57\x4d\x3e\xe1\xf2\x11\xc8\x11\xa1\xa1\x25\x8e\x47\x58\xce\x99\x63\x76\x61\x2d\x17\x19\x9c\x27\xce\xcd\x15\x01\x7a\x23\xc1\xfe\x62\x14\xcc\xe4\x2e\x45\xcb\xbf\x03\xe5\x88\x6f\x00\x35\x28\xe4\x9b\x37\x94\x4b\x7f\x00\xb2\xf4\x9b\x84\x25\x2d\xe4\x92\xbe\xe4\xd2\xdb\x4a\x90\x7b\x1b\x4a\xb7\x8b\x07\xa9\x88\xf4\xe8\xe0\x1b\x6d\xe1\xd2\x6c\x61\x2c\x9e\xd3\xef\x2e\x6d\x80\xfc\xcf\x46\xd3\xec\x1c\x4f\x20\x96\x66\xe0\xd8\x13\x0d\x04\x69\x17\xbe\xd9\x66\x5a\x95\xe8\x37\x1a\xbb\x57\x1a\x3b\x1c\x86\x4d\x90\x16\x6f\x61\xac\x7e\xbb\x85\x81\x87\xb7\x7c\x52\x19\x92\x83\xe7\x9e\x9e\x9e\x59\x89\xfa\x9d\xf1\x8a\xb7\x84\x57\x74\x87\x57\x74\x87\x57\x6c\xe7\x8a\xdf\x1a\xac\xec\x1a\xf1\x88\x44\xc5\x63\x85\xeb\x8e\x44\xf1\x4c\x18\x7c\xc9\x76\xe7\x38\xe9\x05\xd2\x23\xb9\x15\x55\xc0\x8a\xfa\x74\x05\x67\x1a\xa8\x64\x8b\x11\x91\x8e\xc3\x30\x67\x2d\x0d\xd3\x16\xbe\xf2\x5f\xae\xa9\x83\xe7\xcc\xd9\x32\x5c\x08\xb2\xf1\x39\x5f\x7d\x5b\x56\xb2\x74\x86\xe4\x6b\xb6\x77\xfd\x6b\xb2\x8d\xcd\x8e\x17\x9b\xe3\x55\xab\x57\x59\x68\xba\x37\x5f\xd1\x36\xaf\xa8\xb0\xa3\x31\x58\xe9\xc5\x59\x11\xc8\x15\xd5\xf4\xab\x0f\x59\xaf\x64\x55\xb1\x72\x15\xad\x16\xd9\x0a\x86\x6b\xd7\xfe\x02\xe0\xda\x7f\x0c\xb1\xf6\x47\xde\x20\x35\x91\xba\x10\x6b\xbf\xe5\x5c\x53\x50\xd6\x54\x60\x6b\xdc\xf9\x04\xd2\x30\xcf\x9a\x97\x71\x40\x4a\x2c\xf4\xb5\xac\x72\x68\x4e\x2d\xfb\x85\x6b\x6b\x0d\x55\x26\xeb\xf1\x0a\x8e\xea\x2a\x90\x0d\x8f\xfb\x84\x98\x29\x02\xd1\xae\xe9\x95\x98\x35\x75\xd8\x5a\x8f\x99\x45\x48\xd7\xd4\x5c\x40\x5a\xcb\xd5\xb2\x86\xb1\xbf\xb1\x12\x6c\x22\xd6\xf2\xe9\xcb\x1f\x40\x37\xd6\xd4\x80\xde\x89\x4e\x40\x13\xbe\x81\x2b\x3e\xef\x24\x7a\x7d\x7e\x23\xeb\x3a\x05\x1a\xf0\xe7\x15\x36\x3c\xa7\xdc\x70\x99\x6e\xb8\xfc\x36\x92\x6f\x09\xa4\x1b\xd0\x8d\x7d\xa6\x79\x25\xd1\x2b\x4c\x1b\xce\xc1\x86\x47\xc6\xdc\x01\x20\x55\x9d\xd7\x8d\xc5\x53\x77\x20\x0b\xef\x23\x09\x77\xa2\xb6\xe1\x4d\x00\xa0\x8c\x68\xca\x56\xc6\xd0\xd4\xc6\x7f\x00\xb2\x71\x1f\x80\xe4\xe4\xb5\xcf\x39\xf3\x05\x2e\x59\xe0\x9a\x79\xce\x2c\x4a\x43\x47\x1b\x6e\xf2\x36\x32\x3f\x18\x5d\xf3\x50\x2d\x77\xf2\xcb\xc7\x46\x1b\x9d\x17\xcb\x5c\x58\x45\xb6\xeb\xda\xd0\xa6\x6c\x7c\x30\x78\x63\x51\xa7\xf8\xe4\xc9\x5a\x96\xc4\x7b\x7f\x1b\xef\xa1\x6e\x68\x4c\x36\x7e\x63\xb5\xd1\x1d\x94\x0e\x84\xd8\x0f\xa2\x8b\x6b\x99\x08\xdc\xc6\xef\x90\x36\x3e\x22\xfb\x1d\x47\xe9\xd0\xed\xdf\xa9\x9f\xd5\xd2\xf3\x56\xc4\x77\x46\xa2\xbe\x8b\xd6\x53\xaf\xef\x3b\x0f\x98\xbe\x63\x45\x60\x8e\xbf\xe3\x47\x28\x80\x6e\xac\x44\x8d\xab\x69\xbc\x60\xcb\xe3\xb8\x2d\x97\xd5\x96\x71\x97\x2d\x2f\xff\x6e\xa5\xe6\x59\xcf\xae\x55\xeb\xb0\x6c\x79\x53\x05\xf7\xb6\xbe\x1a\x92\xd6\x6c\xe9\x35\x6d\xed\xc0\xac\x06\x99\x33\x4c\xb0\x65\xf0\x77\xcb\x0b\xb5\x5b\x93\xb0\x98\xac\xdf\x31\x6d\x19\xc4\x80\x77\x86\xa4\x13\x37\xc3\x5b\x2a\x8a\x2d\x5d\xaa\xad\x88\xdb\x48\xbc\xa3\x33\xc6\x63\xcb\xaf\x55\xb7\xfa\x91\xb8\x28\xa5\xad\xe8\x8e\x6b\x4f\x7f\x4b\x40\xdb\x12\x10\xbb\x9b\xe8\xcf\xa0\x6c\xa9\x3b\xb6\xf2\xfa\x03\x10\x9c\x9b\x11\xc9\xc8\x0a\x4e\xe2\x85\xef\xad\x85\xc8\x23\xb9\x25\x8a\xe5\xc4\xf7\xfc\x6c\xc9\xc5\x14\xa2\x7f\x88\xf4\x76\xe9\xd6\x6f\xc8\xb7\xce\x1f\x49\xc9\x55\xcb\xef\xb8\x39\xde\x49\x33\xff\x0b\xdb\xb6\xe3\x4d\xa6\x9d\x7d\x9e\x72\x05\x29\x64\xc4\x47\x24\xb5\x21\x99\xc6\x1d\xcf\x8e\x77\x8c\xe1\x0a\x12\x41\xd8\x59\x10\x28\x05\x59\xf0\xa2\xce\x8e\xa7\x5d\x3b\x5a\xd5\x1d\x6e\x38\x00\x7d\xb0\xd4\x4f\xa2\xf8\x3b\x2b\x3b\x5e\xa5\xdb\xd9\xaf\x01\x7c\x27\xd9\xc2\x28\xed\xfc\x3d\xf5\x9d\x7d\xca\x90\x81\x68\x88\x68\x47\x4d\xf1\x46\x57\x6d\xcf\x43\x8f\x37\xbd\x05\x23\x59\xdf\xb8\xeb\x79\xe3\xfd\x97\xbd\x8f\x0b\x83\xdc\x13\x55\x3e\xb9\x66\xd9\xd1\x22\xef\xbd\x45\x06\x59\xb0\xf8\x37\xf7\x82\xc5\x53\xf6\x74\x12\xf6\x74\xef\xf6\xb4\x2f\xf1\xd2\xc8\x9e\xd7\xc4\xf6\x74\xe2\x40\x62\x53\xf5\xc0\x69\x8f\xcb\x51\x86\xec\x69\x85\x8e\xbc\xd1\xa9\x90\x34\x2b\x52\x67\xfc\x87\x9e\xaa\xd8\x4b\x73\xa2\x86\x28\x06\x29\xf6\xfe\x42\xda\xde\x9f\x84\xee\xb9\x39\xda\x9b\x9b\x37\x22\xc9\xf9\xf6\x8b\x6f\x7e\xb4\x51\x7b\x6f\xa3\xf6\x5e\x83\xec\x4d\x69\xc4\x02\xa2\x47\xb9\x57\x1b\xe5\x72\xfe\xc3\x15\xb3\xf7\x3f\x4f\xb2\xe7\x1d\x7a\xa0\x77\x20\x31\xec\x22\xe5\x7b\x9c\x48\x63\xe9\xee\xa5\xc3\x13\xeb\x4f\x50\x22\x63\x2b\xc7\xf6\x10\x7b\x91\xde\x01\x11\xde\x33\xc5\xb2\xc7\x69\x4a\xd7\xff\xd3\x1a\x67\x3f\xd8\xb1\xa7\xad\x03\x1a\x7a\xc2\x91\x55\x57\x21\x27\x89\xa7\x72\x6f\xd0\x3a\x36\xe1\x89\xba\x6f\x7b\x6f\x5d\xf7\x7e\x2f\x05\xa2\x8a\xfa\x07\x6d\x21\x50\xcb\x0c\x4b\xdf\x90\x15\x3b\x14\x43\x89\x20\x3f\x88\x4e\xbe\xb1\xff\xe7\xc9\x27\x0f\x0e\xf7\xde\x6a\xee\x3b\x77\x63\x0d\x44\x35\xe9\x81\xf6\xeb\xc0\xd3\x9e\x03\x17\xca\x81\x63\x71\xe0\xf2\x38\x70\x79\x1c\xa8\x9c\x0f\xdc\xf7\x1c\x78\x4a\x77\x30\xe7\x37\x23\xd1\x82\x4a\x66\x2d\x65\xad\x9c\x58\xb0\xca\xe1\xbb\xfb\x6c\x31\xd6\xa0\x6b\xe9\x20\xeb\x66\x6c\x48\x64\xe8\x20\x8b\xe6\x0f\xd6\xf5\xcc\x12\x1b\x36\xb5\x85\x9b\x70\x30\xe9\xaf\x48\x2a\x66\x40\xad\x07\x56\xf9\x02\xc9\x3d\xf8\x2d\xd2\x3f\xf6\x03\x3d\x23\x92\x05\xab\x6b\xe9\x9b\x1c\x38\xaf\x07\x99\xd4\x7b\x88\xcd\xc1\xbc\xee\x96\xef\xac\x59\xdd\x96\x8d\xdd\x33\xed\x9d\xc3\x16\x83\x37\x07\xee\x99\x0e\xf6\x6b\x2d\x23\x12\x7d\xef\x6a\xb3\x60\x32\x00\xf4\x68\xdd\x0d\x2b\x67\x4a\x84\x5e\x5a\xdb\xdf\x2d\x8e\x89\xe1\xd4\x1f\x13\x59\x93\xa0\x41\x76\xbd\xe1\xe0\xad\xe5\x81\xdf\x73\x09\x72\x1b\x99\x03\x8d\xe8\x41\x96\x68\x44\x29\x51\x66\x28\x89\x95\x17\x4e\x06\xf5\x44\xb4\x25\x29\xac\xbf\xee\x46\xc2\xc1\xbb\xa3\xff\x70\xd5\x21\xf9\x87\x49\x98\x8b\xc7\x1f\x19\x4a\x3f\xea\xa1\xa7\xbc\x70\xf4\xdf\x74\x1c\xfd\xed\xa7\xff\xd9\xd7\x87\x19\x0b\x48\xb9\x81\x03\x39\x02\xe9\x3a\x3a\x52\xc1\x1c\x69\x70\x8e\xf4\x66\x8e\xb2\x7a\x1e\xd0\xaf\xa3\xfe\x52\x97\x05\xa2\x8e\x54\xd5\x47\xae\x9c\xa3\x2c\x9b\x2f\x40\x8f\x18\xde\x23\xae\x17\x01\xcd\x98\x6f\x06\x37\xe9\x48\x5f\xef\xa4\x47\x54\x42\x8e\x34\x36\x47\x1f\x7f\x3b\xf2\x84\xfe\xc8\x5f\xb0\x3a\x9a\xcd\x69\x49\x32\xa2\x82\x65\xbf\xf2\xbd\x15\xbb\xbe\x62\x15\x3b\x3e\xdd\xb3\x85\x07\x5f\xed\x4f\x66\xbd\x10\x5d\x0d\x99\x01\x38\xf2\x7c\xf4\x48\x91\x3d\x8a\x38\x16\x86\xb4\xea\x84\x63\x0d\x1f\x53\x9a\x7c\xd2\x53\x2e\x6d\xb2\x79\x92\xc7\xce\x9d\xaa\x9f\xec\xe0\x28\xe3\x13\x15\x28\x3c\x51\xe3\x86\x53\x06\x15\x9e\x9f\x3e\xca\xfb\xd3\x76\xb6\x03\x92\x8c\xe8\xce\xe7\x29\x7c\x51\x25\x91\xda\x93\x9f\xfe\xdc\x1b\x64\x4e\xa4\xc7\x9f\x3f\x3b\xf7\xab\x0b\x3f\xfd\x39\xf6\xcf\xce\x7e\x34\xe1\xa7\xf8\xa5\x13\x20\xdd\x68\x7c\xe8\x06\x5c\xe4\xec\x43\x37\xc5\xba\xf2\x91\xd3\xf6\x3f\x3f\xbd\x27\xfe\xf1\x9b\x59\xfc\xb0\x10\x63\xc5\x9c\xa5\xf5\xdb\xed\x05\x3f\x3a\xfb\x22\xeb\xcc\x21\x3b\xd3\x17\x84\xe1\xd2\xcd\xc9\xd9\x3e\xa0\xca\x49\x74\xf4\xcf\xfe\xa3\xa5\xb3\x7e\xa7\x64\x45\xc5\xef\x94\xce\x5c\x79\x67\xce\xc8\x99\x1d\x38\xfb\xd6\x7f\x72\x19\x9e\xb9\xe6\xce\xd4\x32\x67\x7a\x4d\x67\xce\xd4\x99\xee\xfb\x99\x87\xce\x67\x4a\xce\x99\x7a\xe8\xdc\xb9\xaf\x26\xcf\x5c\x94\x67\x5c\xff\x21\xd2\x3e\xea\x75\xec\x33\x4d\xd6\xbf\xf8\x59\x39\xdf\xa8\x5f\x3e\x37\x00\x2f\x89\x1a\xb6\x73\xc5\xfd\xce\x99\xf1\x9b\x33\x9d\x9f\x33\x9d\x76\xa0\x29\x11\x7b\xe0\xae\x43\x21\x6c\xb4\x81\x46\x8c\xdf\xfb\x00\xa9\x27\x7b\xe1\x71\xcd\x85\xb1\xc2\x0b\xbe\x56\x02\xd2\xe3\x8b\x8b\x18\xd8\x7e\x4f\xbf\x15\xb2\xf2\xbf\xf2\x0d\xb5\x89\x17\x44\x00\x81\xd6\xf0\xb4\x2f\xb2\x4b\x9f\x02\x6d\xf9\xae\x4a\xc2\x85\x91\xc1\x8b\x98\x8e\x3b\xa0\x21\x9f\x66\xfc\xac\xe0\xc2\x1f\x7e\x8c\x86\x33\xfe\xe0\xd9\x05\xba\x81\x28\xb3\x96\xbb\x4b\x36\x17\x8b\x7e\x87\x17\xae\xbc\x87\x71\xa5\xe1\xb8\x52\xfa\xae\xd4\x33\x57\x04\xa0\x0c\xc9\x54\x5d\x29\x5c\x57\x5a\xb2\xab\xfd\xe2\xc3\x00\xa4\xf6\x28\x96\x3a\x23\x7a\x61\x3b\x5a\x3a\x66\x57\x7f\x22\x77\xa5\x23\x72\xf5\x91\xd5\xab\x74\x61\x45\x84\x06\x96\xcc\x29\x5b\x75\xcb\xa9\x7a\xfb\xea\x77\xba\x57\xc6\xa3\xae\xdc\xdf\xc7\xa3\x8e\x2b\x2f\xdb\x5f\x7d\x70\xff\xca\xaf\x94\xae\x8c\x37\x5d\xdd\xe0\x4a\xfc\x40\x92\x03\xc2\x85\x23\xa0\x50\x93\x6e\x07\x06\x3d\xb7\x31\x50\x34\x24\xaa\x7a\xf6\x9d\x19\xbe\x94\x8c\x77\xf0\x03\xba\x63\x41\xa5\xed\x8d\x71\x2f\x3f\xfe\x7a\xaa\xf2\x37\xa0\x47\xfb\xcd\x46\xbd\xbe\xaf\x0d\xaa\x59\x79\x2d\x66\x47\xd1\xc9\x50\x10\xdf\x80\x66\xac\x62\xc6\x52\xb8\x8d\x0a\x84\x3f\x6e\x14\xc8\xce\x92\xc3\x30\x5e\x81\x86\x4c\xbb\xb1\x2f\xb6\x71\xdb\x4c\x55\x4b\x20\xd0\x60\x7a\x72\x9d\x78\x92\x7a\x32\xf4\x04\x4e\x95\xdd\x22\xb1\x19\x52\x0e\x39\x50\x52\x11\x41\x0b\x2b\x41\xf0\x04\x44\x5d\x3b\x25\x39\x8b\xba\x75\xbf\x60\x17\xf8\x83\xc8\x8e\xdc\x7d\x96\xd5\x10\xd0\x93\xbb\x78\x1d\xf8\x33\xcb\xbd\x58\x9a\xba\xa8\x7a\x87\x13\x97\x56\x95\xc0\x46\x2b\x81\xf7\xa1\x3f\x2c\xa9\xdf\xe3\xa0\xee\x84\x1f\xc5\xda\xa2\x0b\x49\x43\x3e\x44\x2c\x4b\x11\xce\xbc\x40\x62\xf4\x57\x7f\x12\x2a\xe3\xdb\xaf\xf6\xb6\xee\x3d\x13\xfc\xb0\x6b\x4e\x84\x13\xb0\x64\x60\x97\x1c\x92\x01\x45\x31\x8e\xf1\xc0\xb6\x41\x4a\x6a\x8f\xe8\x63\x46\x47\x3a\x19\x50\xaa\xe2\x8c\xf0\xfc\x37\x19\xd8\x6f\x05\x24\x03\xbb\x85\xa3\xe8\x87\x28\xbb\x64\x60\x3f\xdb\x9b\x0c\x4c\x19\x24\xb8\x64\x56\xb8\x66\xe8\x31\x78\x82\x0b\x64\x37\x5c\x77\xa9\xed\x0b\x14\xbd\x3b\x67\x20\x67\xea\x87\x21\xdd\x7c\x24\xa9\x59\xd4\x24\x75\xb7\xab\x12\xba\xd4\x09\x4d\x7c\x82\xef\x9d\xc7\x40\x0c\xe2\x05\xf2\x0d\x8d\x4d\xdd\x01\x55\x82\x26\x20\x83\x6a\x9c\x84\xbf\x49\xa8\x73\x37\x20\x8a\x69\x3c\x0c\x53\xfe\x48\x54\x13\xf1\x06\x4d\xbc\xb9\x19\x7f\x78\x34\x19\x9a\xe3\x90\xd8\x4f\x03\x5a\x45\xb9\xed\x2c\x02\x99\x32\xf9\xde\x37\xab\xe4\xab\x95\x6f\xc9\xdc\xa3\x1c\xe8\x85\xed\x5e\xb2\xac\x57\x9c\x9f\x31\x0f\xfc\xbd\x64\x68\x76\x3b\xa0\xd4\xca\x4a\x32\x0b\x58\x29\xd1\x59\x46\xe4\x2f\x05\xca\x2d\xec\xa2\xe4\x9e\x08\xd6\x5b\xc9\x73\x4f\x57\x6b\xc2\xcf\x69\xf4\x0b\x18\x45\xaa\xc7\x6f\x28\x90\x37\xec\xc1\x8d\x85\xe2\xe4\xaa\x2c\x2a\x1b\x51\xb2\x46\xee\xf7\x90\x94\xcc\x98\x3b\xb7\x1f\x88\x51\xa2\xc9\x53\xa6\xc1\x37\x0b\x68\xc6\xe2\xe6\x4c\x9b\xb3\xd4\x25\xdf\xd8\x1a\xb2\x81\x1a\xd9\xc1\xc9\xc4\x72\x9b\xee\x1d\xf1\xc7\x76\x48\xc6\x7c\xfb\x2f\xfd\x39\x16\xb1\x35\xe0\x6c\x4c\x32\x62\x51\x13\xeb\xaf\x29\x10\x1c\xca\x84\x61\x1e\xbb\xdb\x1f\xc9\xd8\xeb\x5f\x90\x47\x22\x55\x76\x63\xfb\x60\xa5\x10\x82\x0b\x44\xfa\x3b\x5d\xc9\xa4\x8b\x5f\x66\x28\xf9\x42\xa4\x83\x03\x82\x1f\x71\x8b\xd9\xb0\x81\x55\xf2\x49\x92\x41\x35\x4e\xf4\x47\x49\xb4\x00\xbd\x9e\x10\xc9\xd4\x93\xc2\xaa\x8f\xbb\x01\x25\x51\xdc\x27\xde\xee\x4f\x34\x42\x25\x24\xe3\x62\xcd\xec\xfa\xbb\x22\x7c\x53\xab\x64\xce\xdc\xb9\xf8\x6c\x2a\xe7\x2d\xd0\xa3\xcc\xd8\x4d\x4f\x25\xde\x54\x4e\x46\x61\xcd\x28\x0d\x99\x6d\x28\x13\xfe\x36\x52\x82\x5f\x37\xfa\x42\xf4\x83\xe8\xc4\xac\xd8\xcf\xe0\xc7\x7f\x45\x6f\xe0\x27\x87\xfa\x44\x88\xb2\x2b\xd1\xc5\x9f\x9b\xa3\x9d\xc8\x0f\xb3\xc8\x4f\x6a\x83\xd4\xee\x57\x88\x55\xeb\xa6\xbd\xf8\x31\xfa\xff\x07\x00\x00\xff\xff\xaa\x0a\xcc\xb8\xdf\x5e\x00\x00") - -func keysWordsWordlistJapaneseTxtBytes() ([]byte, error) { - return bindataRead( - _keysWordsWordlistJapaneseTxt, - "keys/words/wordlist/japanese.txt", - ) -} - -func keysWordsWordlistJapaneseTxt() (*asset, error) { - bytes, err := keysWordsWordlistJapaneseTxtBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "keys/words/wordlist/japanese.txt", size: 24287, mode: os.FileMode(420), modTime: time.Unix(1523115814, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _keysWordsWordlistSpanishTxt = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x5b\xbb\x76\xfc\x2e\xaf\xed\x79\x4b\x8c\x65\x8f\xe6\x00\xe2\x27\xc0\x2b\x99\xb7\x49\x99\x62\x8a\xff\x4a\x97\xd6\x2f\x76\xd6\xde\xe4\x2b\x46\x98\x3b\xe8\x2e\x60\xee\xaf\x2d\x26\x0b\x71\xdb\xad\x48\x0d\x71\x93\x67\x0c\x71\x53\xf1\x81\x52\x3b\xe3\xce\xb4\x12\xae\x42\x8f\x2f\x26\xea\x21\x6e\x53\x32\x32\xb3\x5b\x88\x29\x6e\xd1\x91\xec\x52\x34\x86\x98\x92\xb0\x38\xe9\xfd\x53\x43\x4c\xa2\x43\x90\xe4\x13\x95\x52\x31\x5a\x92\x36\xa2\x87\xfb\x2b\x29\x66\x4a\x39\x3a\xc7\xa8\xf7\x77\x88\xc9\x4e\x41\xc6\x38\xcc\xd0\x8b\x09\x81\xeb\x0b\xc9\x64\xe3\xb9\x2b\x13\x71\x8e\x31\x3b\x4a\x77\x65\xd3\xbd\xe8\x40\xed\x6e\x9c\x28\xee\xe6\xd8\xcc\x3e\x63\x8d\x48\x32\x1a\xdd\xdf\x2e\x16\xe2\x21\x89\x6d\x0e\xfd\x5b\xf2\xa1\x75\xe5\xbd\x70\x91\xa7\xe6\x10\x4f\x65\xa3\xd3\xea\xfd\x8e\x48\x3b\x86\x38\x6d\x95\xba\x9c\x2b\x55\x14\x4e\x34\x98\xbb\xa1\xef\xd4\xcc\x1c\x30\xfc\xb0\xd3\x00\xdd\x2d\x44\x75\x09\x51\x7b\x46\xbf\xa7\xec\x2e\x2f\xa4\x58\xe5\x73\x76\xa0\x2c\xc7\xe4\xf7\x57\xc5\x47\xd9\x9c\x05\x5e\x62\x88\x79\x8b\xe1\xfe\xca\xdb\x2c\x21\xe6\x14\xf3\x8e\xaa\x5d\x50\x23\x27\xdb\xc9\x13\x83\x66\xf1\xc1\x42\xc2\x43\x33\xb0\x4a\x2a\xe4\xd3\x76\xee\x34\x2b\x29\x9d\x75\x91\x25\xeb\x85\xf5\x67\xce\x52\xc8\x14\xb9\xdc\x6f\xd2\x37\x8f\x05\xe5\x85\xd2\x45\x15\x62\x31\x8f\xe9\x28\x9a\x05\x6b\xcf\x2f\x34\x2b\x71\xcb\x82\xa4\x0e\x26\xcd\x80\x84\x12\x1d\xfb\x2f\xb1\x13\xad\x65\xfb\x4b\x14\xc3\x14\x6e\xbd\x28\x5b\x68\x1f\x71\x0f\xb1\x18\xc6\x6a\x11\xe8\x2a\x2d\x63\x6d\x35\x3d\x08\x35\x56\xa6\x18\xb7\xee\x98\xb3\xee\xf7\x77\x0d\xb1\x92\x0b\xef\xaf\x7a\x4e\xf0\x68\xd5\x9c\x41\x87\xaa\x05\xb9\xfb\xdd\x43\xac\x8b\x68\x75\x08\x98\xa1\x0e\x3d\x27\xea\x86\x3d\x91\xcc\x98\x01\x49\x97\x3a\x6b\xc2\xac\xf7\x7f\x91\xcc\x76\xff\x27\x4f\x66\x2d\xc4\x16\x49\xf2\x16\x3d\x62\xfd\x4d\x06\xf7\xd1\xd0\xbe\x65\x4d\xac\x34\xa0\xb7\x99\x03\x0d\xcd\x3e\x91\x71\xa9\x3b\x28\xd1\xdc\x88\xd8\x36\xa5\x83\x42\x6d\x62\x9b\x4e\x82\x38\x66\x0c\x14\x8a\xfb\xcb\x37\x1d\x6e\xfc\xb0\x1c\xa2\x6f\x93\xac\xe7\xe9\x41\x22\x38\x24\xd9\x39\xa4\xef\x9a\x81\x10\xdf\x27\xdb\x0b\x10\xe1\x14\x31\x57\xe9\x21\x7a\xf9\x63\x5f\xaf\xf7\x37\xf2\x06\x52\x7b\x23\x20\x47\xb8\xcb\x09\xbc\xb9\xdb\x0b\x70\x82\x5f\xb8\x7c\x1f\xca\x75\x76\xfe\x30\x66\x5f\x0c\xd0\x93\x54\x88\x6a\x97\x73\x52\x8c\xbb\x30\xd7\x41\xbd\xfe\xc7\x5a\x5d\x33\x61\xa7\x58\x76\x10\xaf\x5b\xd9\xb8\xaf\xde\x04\x5b\xef\x63\xad\xbe\x8f\x95\x9b\xec\x37\x0b\x3b\x4c\x8e\x32\xe2\x93\xf0\xdf\x14\x24\x1e\xe2\x58\xc3\x0f\xc1\x40\x43\x81\x8b\x41\x8e\xbf\xbf\x86\x81\xe4\xc3\x23\x50\x33\xb8\x9f\x71\xff\xd6\x10\xe7\x1e\x5f\x80\xa0\xd4\x3c\x25\xc4\x89\x69\x67\x59\x43\xcd\x2e\xe4\xda\x39\xb0\xfe\x0b\xdc\x70\xc5\x9a\x04\x09\x16\x76\xe1\x4b\x72\xa6\x26\xb9\x64\xc1\x3e\x7c\xbe\x42\xbc\x96\x02\xb9\x14\xf8\xf8\xc4\xbc\x9f\x73\x8f\x80\xd8\xf0\x2b\x1e\x4b\xa0\x29\x23\x2f\xc3\x2c\xaf\xfb\x97\x9c\xf2\x9a\x07\x44\xf7\x35\x73\xd8\xe2\x16\x01\xcc\xc3\x16\xd3\x43\xc2\x16\x1f\x20\xda\x16\x35\x23\x03\xe1\xde\x62\x8e\xf5\x85\xb2\x9c\x30\xe5\x46\x35\xb0\xc5\xb2\xdd\xbf\x61\x8b\x35\x19\xe0\x8e\x06\x60\xd6\x2d\x3a\xc7\x74\x96\x7b\xd5\x17\x12\xb7\xb0\xdd\x5f\x3d\x61\xfb\x5b\xec\x63\x0d\xd4\x21\xce\x5b\x1c\x31\xb3\x78\x88\xaf\xc9\x41\xb8\x2d\x8e\x39\x38\xe8\x2f\xd6\x89\x7d\x6c\xb2\xdd\xdf\x80\x8a\xd9\x04\xd2\xb6\x49\x67\x45\xe7\xe7\xd0\x18\x36\x85\xd8\x6e\x2a\x35\x6c\x5a\x4f\x0b\x5b\x5e\x6b\xcc\x06\x52\x6e\x79\xf6\x18\x36\xc3\x6f\xd3\xca\xc4\xc2\x66\x09\x5f\x69\x15\xec\x04\x72\x22\x59\x25\x99\x00\xac\xb3\x59\x66\xff\x82\x4d\x5a\xdd\xe3\x8e\x04\xe2\x48\x1b\xb6\x59\xed\xf7\x97\x86\xcd\x1c\x48\x32\x07\x97\x6e\xd6\x39\x35\xa8\xb0\xd9\xb8\xdf\x35\x6c\xf7\xcf\x25\x9c\xe7\x15\x73\xd8\x3c\x5e\x16\x96\xdd\xdb\x5c\xd2\x23\x22\xb9\x24\x6c\x4e\x9d\xb2\xb9\x72\x0b\xae\x98\xdb\xb9\x58\xca\xd3\xe6\x06\x76\xd9\x9c\x43\x3b\x34\xff\xe6\xb3\xb3\x2d\x78\x7a\x9b\x49\x08\x41\xcd\x09\xb5\xb7\x4d\xf9\x0c\xdb\x3c\x16\xc5\xe6\x41\x42\xdc\xbf\x40\xd9\xd4\xe1\x68\x96\xd9\xd1\x37\x8e\x36\x3d\x13\x62\xeb\xb3\x83\x7f\xb6\x39\x22\x16\x30\x5f\xe8\x0b\x93\x8c\x25\xa6\xb8\x41\x5d\xa7\x48\xa4\x26\x18\xf1\x90\x62\x8a\xa8\xd9\xef\xaf\x4b\x1c\x1f\xc2\x3a\x7e\x1f\xf7\x77\x48\xf1\x7e\xef\x28\xd1\x02\x66\x4d\xf1\x89\xcc\x73\x8d\x9b\xf1\x83\x22\x47\x0a\xd5\x08\xfb\x43\xa8\xc0\x7a\x8a\x39\x0b\x60\x41\x9f\x6c\x6c\x76\xa1\x9e\x05\x65\x63\x8f\x22\x6b\x71\x45\x2b\x93\x66\x21\xdd\x5f\x35\x71\x09\x75\x57\x4c\x52\x25\xa3\x47\x3d\xa1\x15\x53\xac\x9a\x98\x1d\xc8\x40\x37\x02\xae\x25\xd9\x86\x9c\xf5\x90\x62\x8b\x2f\x40\x1d\x6b\xe1\x0d\x04\x48\x91\x1e\x40\x8a\x6d\x82\x84\x29\x12\x07\xbe\xb1\xf3\xfd\xe5\x49\x30\x9d\x43\x65\xa4\xe8\x27\xa1\x42\x66\x52\xf4\x8a\xee\xde\xfe\xea\xb8\x10\xe7\x77\x27\x48\x28\xe8\xc2\xf2\xde\x58\x34\xb8\xe5\x61\x9e\xd0\x15\xa4\x4b\x50\x37\x98\x62\xb2\xd3\xcb\x42\x92\xcd\x20\x5b\x49\xa0\xb4\x93\xec\x18\x40\x32\x70\x7e\x7f\x67\x81\xa9\x4f\x92\xe1\xfd\x20\x3f\xd9\x72\xe9\xa6\x24\x55\x41\x4f\xa9\x83\x7d\x1c\x48\xa1\xfb\x93\xc4\x49\x69\x59\xe5\x60\xf0\x24\x4e\x63\x9d\xee\xef\xde\x64\x0f\x49\xd8\xe9\x11\x49\xc5\x47\xcc\x92\x98\x2d\xed\xfe\x45\x4a\x5b\x9a\x1e\xb1\x11\x3a\x33\xca\x26\x0a\x77\x64\x59\x9b\xf4\xa0\xc0\xa6\x87\x61\xe4\xc7\xa4\xaa\x4d\x8f\xd9\x30\xa1\xa6\x4c\xac\xaa\x9c\x06\x98\x09\x59\x00\x1f\x32\xe9\x01\xdc\xeb\xb9\x50\xa9\x60\x09\x8a\x50\x52\x20\x5a\x2b\x86\xd2\xe6\xb0\x4c\x49\x9d\x15\x3e\xc9\x07\xda\xd9\x82\x0d\x26\x19\x2d\xd3\x39\x48\x39\x56\x00\x8c\x97\x63\x17\xc0\x0b\x50\xa9\xc3\x53\xe6\x24\xf9\x7e\x2f\xfe\x31\xe2\xd6\xfe\x5c\xd3\x64\xe9\x41\x0e\x5c\x2a\x26\x19\x66\xbc\x7f\x76\xb8\x20\x09\x86\x3b\xd9\xc1\xf6\x70\x47\x93\x3d\x04\x23\xda\x13\x9a\x22\xc1\x55\x48\xd0\x40\xc9\x32\xd9\xca\xb2\x9c\xca\x32\x78\x05\xc9\xf2\x1a\x32\xe7\x95\x2b\xac\x9a\x85\x85\x05\x5a\x15\x29\xc7\x2d\x4a\xca\xff\x94\x35\x65\x69\x40\x92\xd5\x1d\x2d\xaa\x70\x9e\x7a\xb2\xc8\x28\x21\x56\xfb\x5f\x29\xf9\xda\x40\x2f\x6b\x0a\xe8\x71\x89\xbf\x39\xf4\x37\x52\xa8\xdd\x64\xbe\xff\x15\x1b\xe7\x77\xe7\x38\x7d\xc1\x02\xd1\x31\x98\x76\xba\x9b\x62\x4c\x07\x2a\x5d\x22\x61\x5a\x99\xfb\x8d\x15\xba\x14\x36\x7d\x03\x2a\xe2\x87\xe4\xda\xd8\x5d\xbb\xf6\x90\x1c\x76\x37\xf9\xfd\xb3\x90\xee\xe0\x18\x56\x4f\x76\x9f\xaf\x90\x66\x24\xd3\xcf\x48\xbe\x98\x91\x9c\x39\x37\x02\x44\x18\x09\xb2\x0a\x3c\xcc\xa5\x2a\xe6\x62\x7f\xb8\xfa\x2c\xe4\x6a\xa7\x5c\x80\x0a\xef\x2f\x4d\x08\x0e\xb2\xb9\x11\xb2\x39\xdd\xe6\x34\xe1\x3a\xa2\x09\x36\x3f\x2b\xd7\x32\x8d\xb0\x2d\x2d\xf0\xdb\x28\x65\xf4\x5e\xd2\x74\xa5\xec\x4d\x5f\x90\x93\x0c\xed\x61\x87\x12\xdb\x69\x76\x31\xe5\x1e\x21\x78\x3b\xbc\x8e\x1c\x76\xd9\xc4\xc3\x7e\x7f\x6f\xc8\xdc\xdf\x29\xee\x31\xec\x92\xd4\xc3\x2e\x68\x26\x87\xd4\x8e\xa2\x43\x2b\x0b\x61\xc5\x77\xc9\x07\xd8\x69\x47\x70\xc4\x56\x19\x46\x6b\x97\x62\x8e\xb6\x70\xab\x76\xa9\x23\x62\x82\xe5\x45\xee\x02\x53\x84\x62\x77\xec\x61\x97\xbe\xbc\x8b\x5d\xe0\x76\xed\xd2\xe1\xe8\x23\xad\x93\x23\xf6\xa1\xab\xf6\xba\xdf\x48\x07\x55\xf4\x2e\x43\x2a\x56\x2c\xf0\x4f\x76\x10\x73\xd7\xb8\x65\x43\xb2\x83\xc2\xbb\xfe\xb9\xef\xbb\xc2\xd3\xd9\x35\x22\xb6\xd9\x75\x9b\x4f\x24\x0c\x99\xf6\x25\x66\xbb\x02\xa7\xbb\xca\x2b\xec\x7a\xdc\xef\x04\x1c\xe8\x89\x69\x35\xaf\xb1\xf2\xc4\xa6\xb5\x42\x3f\xed\xea\x82\x20\x6d\x57\xd7\x93\xc5\xd0\xa4\xbb\x76\x81\xda\xdd\xb5\x1f\x1e\x31\xd2\x85\x8e\x17\x57\x6f\x08\x27\x76\x4b\x00\xb0\x2a\xbb\x15\xba\x11\xbb\x55\xfc\xb0\x14\xa3\xe7\xbc\x9b\xc3\x5f\xdc\x0d\xc4\xdb\xad\xe3\x07\xd2\x79\x3c\x41\xea\xdd\xed\x8c\x61\xa7\x25\xd8\xb9\x73\x46\xb2\xfb\x5c\x53\xcf\x8c\x19\xee\x5f\x7c\x42\xcd\xed\xe4\x88\x7d\x52\xb7\xee\xb0\x44\xf7\xf7\x86\xc0\x43\x36\x20\x03\x3e\x81\x07\xa8\x51\x01\x47\x9b\x07\x81\x6e\x92\xfd\x2f\x90\x94\x5d\x11\x53\x1a\x3e\x06\x6b\x27\x6c\xb5\x1c\xdc\xbe\x1c\x9a\xe2\x2b\xc8\x53\xf0\x2b\x2d\x5b\x90\x2c\x07\x71\x2e\xd0\x26\x8e\x64\x29\x7e\xc9\x72\xa1\x67\xd6\xd6\x25\xdc\xdf\x59\xd9\x48\x3f\xd8\xc8\xa0\x79\x24\x33\x1e\x96\xb2\x81\xee\xb2\xe2\x5f\x29\xf6\xb7\x94\xd2\xa0\x73\xa4\x34\xee\x14\xd3\x09\x13\x97\x1e\x83\x54\x6e\xaa\x26\x06\x68\x52\xd3\x63\x1e\x82\x14\x7c\x21\x88\xa8\x58\x0c\xe2\x49\x3d\x80\x67\xa9\x87\x78\x41\x7a\xd2\xc1\x94\xaa\x67\x41\xdb\x1c\x13\x7a\x9a\x17\x24\x2e\x6c\xdb\xe3\x27\x13\xb9\xff\xc3\x2e\xea\x58\x23\x0d\x67\xee\x82\xe2\x96\x4a\xfe\xbc\xbf\x1b\x1c\x29\xf9\x37\xb5\x59\x10\xd7\x97\x05\xe9\xf0\x39\x90\xc0\x53\x91\x0e\xbd\xeb\x48\x5d\x37\xe5\x07\x77\xdc\x05\x51\x61\x90\x7e\x88\x33\x99\xe2\xec\xdd\x20\x8b\xd2\x1b\xb4\xa6\xf4\xc6\x3d\xf5\x66\x9d\xc9\xc4\xaa\xfb\xbf\x79\xbf\x03\xb4\x0a\x86\x03\x9e\x10\x8b\xa0\xf5\x98\x47\x0c\x32\x60\x14\x65\x88\x57\xac\x70\x40\xad\xc9\xa8\x98\xec\x62\x5c\x28\x57\xcc\x13\x7d\xaf\x45\xad\x8b\x67\x05\xf2\xc1\x63\x0b\xf9\x40\x6c\x1b\xe4\x83\xe7\x22\xf2\x91\xe0\x08\xc8\xc7\x6a\xf9\x41\x09\x90\x0f\x45\x70\x2b\x1f\x2b\x3c\xba\xbf\x3f\x94\x95\x8d\x76\x53\x3e\xfe\xc2\x49\xf9\x68\x06\xa1\x95\x8f\xe1\x52\x2c\x1c\xf7\xd7\xe6\x58\x0c\x3e\xa0\xc1\x8e\x98\x1e\xd8\xec\x71\x7f\x41\x06\x0f\xcc\xef\xe1\x88\xc0\xdb\x01\x3f\xee\x88\x70\x33\x0e\x3a\x87\x47\xcc\x9d\x10\x6b\x3d\xa0\xdb\x8e\x58\x34\x2b\x53\x63\x95\x47\xf0\xce\x11\xbd\xc4\xc4\x72\x37\x8c\xea\x1d\xdf\x5d\xc2\x11\x87\x9e\xf8\x9e\x9c\xe0\xe2\x64\x1f\xe1\x80\x0f\xe3\x16\x0e\x3a\xcd\x87\x64\x7d\x85\x43\x90\x77\x8c\x22\x08\xc5\x8e\xfb\xdb\xa1\x38\x0f\x71\x76\x93\x4e\x17\xfc\x50\x9e\x1c\x1c\x4a\x35\x7b\x28\x96\xa6\x50\xec\x87\xfe\x59\xed\x43\x39\xa8\xee\x18\x50\xe9\x2d\x1d\x2a\x19\x80\xcd\x68\x1b\x0e\x45\x28\x1a\x0e\x7d\x72\x80\x27\x9a\x02\x3f\x9a\x61\xc4\x0f\xec\x12\x3d\x32\xec\xce\xa1\x18\xb4\x02\x8d\x5a\x41\x0d\x68\xe8\x81\x72\x07\x4e\x72\x4c\x06\x88\xb8\xe7\xc8\x6b\x47\x50\x41\x47\x36\x96\x40\xb1\x1d\x19\x4a\xf1\xc8\xf7\x2f\x2a\x6c\xc3\x2e\xc1\xc6\x87\x9d\xb0\xc3\x87\x51\xf9\x1c\x06\x22\x1f\x96\xb3\x60\x78\xab\x3b\x20\x27\xe1\x89\xd0\x61\x3e\x88\x48\x73\x04\x56\x07\x38\xf4\x30\x34\xf5\x98\x22\x08\xe2\xeb\x2c\xea\xf0\x58\x41\x4c\x27\x0d\x3c\xce\x1d\x89\xdc\x6f\x47\x52\xd1\x10\x52\x7d\x38\x24\xea\x70\x6e\xc6\xb9\xfe\x09\xcf\xec\x98\xd4\xda\x94\x0f\x94\x81\x82\x13\x2e\xfd\x31\xeb\x1f\x8e\x27\x02\x91\x63\xfa\x5a\xf7\x24\xd9\x66\xc7\xd4\xf7\xef\xd8\xc0\x04\x73\x40\x1d\x9e\x31\xc1\x3f\x3b\xe3\x11\x7b\x38\x23\x1c\xb4\x13\x21\xfa\x19\x59\x9a\x57\xec\x78\x92\xdf\xce\x88\xf0\xec\x8c\xd0\xd6\xe7\x3a\xc7\x39\x23\x3c\x9b\x33\xc2\xce\x9d\xd1\xe3\x53\x90\xbc\x50\xd4\x97\x07\x75\x46\x0a\xe5\x19\x07\x5a\x5c\x9a\xe1\xd9\x9f\x52\xa0\xb5\x4f\x81\xaa\x3f\xa5\x86\xf3\xfe\xa6\x72\x3a\xa5\x2a\xe1\x90\x70\x8a\xc7\x95\xf3\xff\xe5\x21\x86\xa7\x74\x0c\xa5\x27\xf5\xec\xa9\xa5\xc6\x8e\x56\x0a\x5d\x74\x2a\x06\xc9\x60\x76\x0f\x67\x46\x10\x7a\x66\xc3\xee\x4f\xcb\xf8\x1d\x06\x08\xe1\x38\x2d\x37\x09\x27\xe2\xbd\xd3\xe0\x08\x9c\xe6\x60\xb1\x13\xd1\x65\x38\xc1\x1b\xa7\x0d\x41\x39\x88\x79\x3a\xe4\xf2\xf4\xfb\xeb\x80\x4f\x7d\x3a\x14\xee\xe9\x08\x24\x4e\x8f\xf0\x2e\x4e\x87\xe7\x7a\x3a\x6d\xe9\xb9\x42\xcc\xd3\xb5\xb1\x0c\xd5\x20\xe3\xe9\xd6\x0d\xa3\xdd\xbf\x68\x34\xa1\x51\x4e\x9f\x85\xb0\x59\x38\xe7\xda\xd6\x8c\x2b\xe3\x3b\xd6\x3e\x85\x6b\x9a\xa4\xc5\x64\x70\x73\x4e\xb5\x0a\xd8\xf9\x3d\xe2\x6a\xd1\xb9\xac\x49\x9c\x3f\x22\x5c\x9a\xc7\xfd\x05\x97\xe6\x11\xb7\xcc\x32\xb8\x82\x0f\xa8\x99\x40\x4d\xf3\x88\x79\x95\x17\x84\x9f\x8f\xe8\x20\xda\x23\xbe\xf0\x63\x9c\xf6\x90\x8d\xa7\x3a\x0f\xba\x67\x0f\xfa\x2e\x0f\xc9\xb0\x21\x0f\x81\x3c\x3c\xa4\xac\x1a\xf8\x7d\x0f\xf1\x82\x25\x3c\xee\x6f\x37\x41\xf6\x42\x29\x43\x89\x87\xc2\xe5\x09\x8f\xfb\x4d\x5f\xe9\xa1\xa7\x4a\x95\xf0\x80\x74\x3f\xb4\xa0\x97\x22\xfe\xd2\x18\x1e\x96\x80\xe5\x87\xc1\x17\x7f\x18\x10\x80\xc2\x27\x00\x7d\xc2\x87\xc1\x7b\x78\x58\x35\xd4\x57\xd6\x2e\x50\xa0\xd0\x1e\x3c\x2d\x7e\x18\xac\x40\x78\xd8\xa7\x85\xc7\x84\x99\x7f\x4c\x9e\x62\x3f\x26\x4f\x56\x1f\x44\xff\x63\xca\x05\x08\x2f\xfe\x01\x65\xf0\x98\x7f\x5b\xf8\x2d\xb0\x7e\x8f\x59\x34\xef\x82\x14\x99\xba\xb3\x89\x47\x44\xbc\xf8\x18\x16\x14\xbe\x7d\xd0\x5d\x62\x0e\xba\x2b\x78\x0a\xae\x76\xb6\xa0\x67\x96\xae\x11\xe9\xfd\x1b\xf4\x9c\x68\x91\xe5\x64\x32\x3b\x85\x55\x4b\x84\x0c\xac\x68\x5d\x0b\x4d\x8f\x96\xb6\xa0\xc0\x4f\xd1\xb2\xec\x86\x96\x36\xa1\xf3\xa1\xec\x10\x2a\xdf\xef\xba\x6b\x92\x00\xb7\x6c\x20\xa1\x22\xd5\x7a\xd0\x7a\x6b\x5d\xe2\xa4\x95\x3e\x8c\xd6\x42\x7f\x54\x6b\x99\x15\xb5\x15\x32\xa9\xb5\xd3\x99\xd1\xda\x07\x59\x4f\x61\xdc\x11\xc1\xdd\xef\x3a\xb4\xa0\x66\x00\x2b\x5a\xef\x5f\x60\x53\xeb\xa5\xb4\xa3\xea\x31\x28\x38\x5b\x7d\x9d\x49\x6a\xcf\x04\x08\xda\x9f\x71\x8b\xf9\x7e\x23\xc5\x16\x9f\xb1\xac\xc4\xe3\x86\x4a\xdf\x61\x2b\x9e\x64\xda\x27\x4f\xef\x9e\xf1\x55\x58\x26\x87\x84\xa7\xb8\x42\xb1\x3c\xb5\x42\xdd\x3f\xcd\x2b\x78\xf5\x69\x6e\x1b\x92\x4b\x6a\x78\xda\x67\x0c\xcf\x29\x88\xf8\x9f\x53\x2e\xe9\x48\x5e\xe1\x39\x4f\x7a\x72\xcf\x79\x1a\xc0\xe4\x08\x93\x28\x78\x4e\x44\xab\xcf\x59\x4f\xcc\x38\xeb\x2a\x02\xbe\x9f\xf7\x6f\x53\x84\x4c\x4f\x7a\x8c\x4f\x9e\xd0\x3e\xe7\x25\x55\x73\x78\xce\x17\xf8\xf0\xff\xe0\x51\xfc\x9f\x41\x33\xe6\xb8\xa9\x05\xe8\x19\x42\x47\xc9\x8e\xcf\x1d\x51\x53\xc8\xf1\x64\x60\x94\xef\xaf\xd3\x11\xc1\xe6\x78\xc2\x30\xe4\x08\xae\xce\x11\x71\x63\xbe\xbf\x0a\x64\x0d\x69\x8b\x1c\x81\x2d\x2a\x44\x33\xc7\x7a\x32\xa2\x5b\x87\x84\xf9\xfe\x6a\xfa\x0a\x99\xde\x5d\x8e\x88\x68\xf2\xfd\xd5\xc7\x1a\x7a\x30\x37\xe4\x03\xdf\xea\x21\xc7\xe9\x92\x43\x8e\xf0\x38\x73\x7c\x59\xc8\x60\xcc\x2c\x7f\x06\x18\x36\x50\x00\xe1\x5b\x64\xc1\x5a\xe4\xfc\xab\x39\x57\xc8\x95\xe5\x09\x11\xc8\x52\xcf\x19\x91\x60\x33\x70\xfe\x00\xd9\xd0\x1a\xa3\x27\x70\xf7\x2a\x18\x9c\x62\x60\x23\x72\x61\x84\x4f\x81\x0d\xca\xba\x41\xd6\x76\x7c\xb8\x85\xac\x09\x93\xde\xef\x1d\xd3\x2a\x82\x92\x80\x58\x1f\x8b\x84\xe0\x66\x3d\x85\xcd\xb0\xb3\xfb\x5d\xe0\x26\x67\x25\xf3\x64\x2d\x0d\xe8\xd6\x9a\x50\x06\xe3\x9b\xef\x77\x15\x74\xaa\x50\xd5\x48\x59\x0f\x3f\x8f\xdd\xff\x4d\x45\x2b\xe8\xc8\xcc\xb3\x6f\xb8\xdd\xce\x84\x23\xc1\x7b\xc8\x20\x16\x60\x21\xe4\x4e\x79\x06\x91\x33\xaf\x84\x72\x96\xba\x12\xa2\x33\x9b\xaf\xe4\xc2\x06\xf2\xbc\x34\x06\xda\x99\xfc\xe7\xa8\x67\x4b\xcc\xc0\x7d\xc9\xf7\xcf\x09\xf7\x2e\xdb\x89\x99\xa0\xba\x40\x46\x84\xd7\xd9\xe0\x01\x50\x56\x32\xa3\x99\x3c\x11\x6b\xe6\xc9\x39\xe1\x8d\x64\x72\xcc\xac\xd2\x43\x9e\x0d\x9f\x3c\x57\xcf\x13\x2b\x9c\xaf\x50\x62\x82\xa5\x29\x11\x1a\xb9\xc4\x1d\x1b\x2b\x71\x77\x01\x84\x6d\x2f\x51\xd8\xa3\xc4\x43\x51\x75\x2e\x88\x82\xfb\x8d\xfe\x19\xc1\x4e\x59\xf7\x4b\x85\xa7\xc5\x25\x66\x54\x97\xfb\x0b\x70\xe3\xf7\x1c\xa1\xf0\xac\xb7\x44\xe0\xbc\xc4\xca\xd0\xb7\xd0\xf4\x97\x58\x95\xbe\x77\x81\x47\xc3\x52\x36\xe9\x84\x1c\xf7\xfe\x0f\x8c\x5d\xe0\x81\x97\xfb\xeb\xdf\x54\xe6\xd0\xd4\x39\xa8\x0b\xf3\x87\x66\x24\xd0\x84\x25\xf2\xca\xa3\xdc\x5f\x5e\x8c\xa5\x94\xaa\x12\x7d\x48\x47\xf2\x42\xbf\xce\xf1\x3a\xcf\x03\x4b\xec\x7a\xa1\x70\x70\xe0\x41\x3f\xb5\xc4\xa1\xd8\x26\x2f\x1d\xcb\xfd\xf5\x01\x6d\x56\xe2\xa7\xa1\xc9\xcb\x3c\xc5\x50\xe8\x0e\x16\xd9\xd7\xee\x65\x57\x4c\xfb\xbd\x4f\xe6\x9e\xba\x4a\x9f\xe8\x21\xe0\x03\x24\x5c\x0a\x02\x7c\x4c\x81\x40\x09\xb0\xc3\xf5\x29\xf4\x53\x8a\xd4\xfb\x37\x14\xf1\x04\x95\x50\xe0\xbd\x9c\x53\x30\x2c\x3d\x80\x82\x2d\x48\x5f\xa3\x00\x41\x08\x4b\x50\x3b\x8c\xcd\x49\x31\x79\x25\xcc\xac\xb0\x3f\x05\x3a\xbd\xa8\xf0\xae\x85\xd6\xad\x00\x55\x9a\xe3\xc9\x82\x4c\x83\x51\x34\xaf\x95\x71\x93\xc4\xf1\x0a\xd6\xa1\x55\xff\xca\xc0\x39\x45\xad\x49\x28\xf4\x96\x8a\x02\x87\xda\x17\xb6\xb4\x73\xd8\xce\xb6\x90\xd8\xc2\xe5\x5a\x7a\xc0\x2d\xfa\x5f\x1c\x5a\x6c\x47\x66\x87\x41\x2f\x06\xce\x33\xd2\xdd\x60\x22\x8b\x65\xe1\x37\x04\xb1\xd8\x0a\x7d\x8b\x15\x0c\x8f\x20\x3f\x31\x15\x8e\x00\xf6\x2f\xb6\x1a\xc0\xa1\x29\x46\x0f\xab\x18\x6f\xc2\x8a\xd1\x0f\x06\x96\x99\x71\x7e\x77\xd6\x43\xd3\x14\xeb\x1c\xac\x33\x04\x2d\xc6\xeb\xcc\x42\xa1\x2c\xf7\xcf\x85\x9d\x18\xb8\x64\x52\x38\xe6\x8e\x46\x53\x10\x99\x14\x1e\x48\x96\x49\x8b\x59\x26\x44\x04\xd9\x13\x72\x33\x9f\xe8\x4f\xe2\xaf\x83\xd1\x32\x33\x21\x19\x7f\xde\xff\x09\x26\x9d\x8e\x05\x50\xc2\xee\xdf\x9e\x26\x30\x31\xbb\x10\x9e\xab\x50\xd9\xae\x67\x0b\xf5\xfe\x42\xe4\x57\xe3\x42\x1f\xec\x18\x72\x70\x0b\x6b\x5c\x61\x40\x8d\x60\xd0\x1a\x79\xe8\x5b\x63\x8f\x39\xd4\x38\x16\xc4\xb6\x6a\x1c\x9c\xb2\xde\x5f\xb3\x0b\xda\x5f\xac\xbc\x30\xc4\xc5\x63\xfb\x2a\xb0\x44\xf5\xfe\xe6\xa9\x4e\xa5\xe2\xaa\x72\x1a\x4b\x05\x7c\x52\xa9\xb7\x2b\xfc\x31\x64\x06\xc0\x1c\xac\xb8\xd8\xf8\x82\xfe\xa8\xbc\xe6\xa9\x90\xbe\xaa\xb2\x65\x94\xb0\xad\xde\xff\xc9\x8b\x09\xa6\x79\x8f\xd5\xe2\x92\x1c\xaa\x6d\x59\x5e\x31\x54\x83\x55\xa9\xf7\x0f\x99\xaf\x52\x3c\x2a\x83\xa3\xca\x73\xaf\x0a\x8f\xba\xda\xd0\xc4\x8a\x0b\xce\x47\xb5\x0b\xc4\xa8\xc6\x45\xcd\x4d\x42\x9d\x29\x86\x7a\xff\xa6\x2c\x28\xd9\xe9\x45\xf3\x20\xac\xd2\x07\xac\xb0\xf4\x80\xaf\x50\x27\xd1\xfb\x5b\xc0\xe5\x75\x0e\x4c\x68\xb1\x6b\x0f\xc6\x9b\x2b\xdb\xb4\x37\x24\x4f\xec\xc0\xe0\xa3\xda\x0a\x6b\x6d\xeb\xe2\xd8\xb5\x6d\xeb\x10\xcd\x36\x2c\x00\x01\x9f\x31\x4e\xb3\x74\x7f\x43\x91\x61\x4b\x50\x62\x06\xac\x10\x99\x96\x5c\x82\xa5\x11\x2f\x7c\x8f\xb9\x31\xcb\xd3\x4a\x4b\x3c\x44\x87\xe6\x07\xd3\x1a\x6d\x9b\x41\xa3\xd8\xae\xa0\x9b\xf1\x64\xc2\xd6\x39\xa2\x1d\x74\x41\x6d\x9d\x2f\xd9\xb1\xce\x68\x69\x27\x8c\xc7\xb4\x86\x68\xd0\x9e\x16\x2c\xc7\x60\x59\x20\x1c\x96\x0f\xa0\xcd\x32\xd8\x82\x57\x10\x3c\x98\xe6\x89\x9a\xe5\x0b\x44\xb1\xb2\x65\x3d\x2d\x18\x8c\xaf\xc1\x79\xb0\x86\x00\xd8\xda\x62\xc0\xfb\xa7\x01\x8f\xd6\xf8\x44\xc2\x96\x5f\xb9\xde\x58\xdc\x3f\x8d\x27\x23\xc6\x0b\x6d\x0b\xe6\x7f\x4c\xcb\x93\x39\x47\x92\xc3\xfd\xe3\x1b\xa2\x44\xaa\x4f\xc8\x2a\xaa\xe5\x19\x51\x71\x12\x67\x7e\xc2\x19\x34\x3f\x27\x68\x67\xbe\x8e\x18\xcd\xf5\x64\x5b\xea\x54\xc3\x36\xfd\xdf\x3a\x07\x36\xde\x51\x5b\x8f\x3c\xc5\xb4\x9e\x20\x5a\xd6\xe5\x85\xd1\x40\x0d\x8a\xa8\x0d\xaa\x09\x03\xcf\xda\xb5\x66\xbc\xc0\x02\xf7\xcf\x07\x37\xfe\x71\xbf\x4f\xe8\x0c\xfb\x5c\x13\xbe\xe0\x93\x37\x9e\xe0\x34\x9a\xc5\x16\x05\x73\x37\xc4\xe0\x35\x86\x06\x53\xd8\xe2\xfd\xee\x28\x7a\x46\x47\x2e\xf3\x8a\xad\xc5\x9c\x98\x83\x0e\x68\xf7\x57\xc6\x04\x8d\x97\x62\x2d\x66\x5b\x09\x88\xdd\x62\xc5\x2f\x66\xb4\xaa\xca\x4e\x95\x2e\x46\x8b\xf7\x7f\x3c\x9a\x6c\xb1\xdd\x5f\x80\x92\x01\xb9\xfd\x16\xff\xd1\x2d\x6d\x7c\x20\xd0\xa2\x33\x08\x6f\xd1\x65\x07\x54\x96\x19\xc6\xf4\x16\x39\x35\x70\xc5\xbc\xc7\x83\x79\xf6\xee\xec\x0d\xd5\xd3\xe2\xf2\xc3\x1a\xd8\xb7\x21\xe6\x0e\x2d\x2e\xa0\x28\xa0\x74\x34\x5e\x61\x35\x9e\x84\x34\x70\x70\x8b\x9f\x6c\x2f\x91\x57\xc7\x4d\x68\xb2\x1a\x58\x31\x22\x79\x20\xb3\x63\x77\x82\xa8\xa7\x51\xaf\x34\xd1\x2a\xa1\x49\xe6\x77\xde\x79\x7c\xd8\x24\x0b\xba\x64\x05\x07\x37\xc9\x59\x9e\x4c\x09\x20\xd4\x0d\xe6\xb3\x81\xf7\xd1\x6d\xdd\xfd\x35\x59\xd0\x50\xd4\x60\x34\x9a\xfc\x5b\x47\xb9\x6d\x2d\xc1\x61\x9f\x9b\xd0\x26\xb4\x75\x45\xd6\x84\xbe\x02\x22\xa3\xc4\x76\x99\x65\x45\xb9\x13\xe7\xf4\xde\x8d\xb3\x75\x02\xcc\x7e\x7f\x77\x58\xc1\x06\x8e\x83\x1f\xdb\xee\xef\x11\xb9\xba\xe1\xf7\x0f\xb4\x4d\x93\x17\x7e\x93\xb5\x3c\xae\x6b\x9a\x1e\x5c\xa0\x0a\x7e\x3b\x56\xa4\xf4\x2d\x9b\x72\x25\xfa\x84\xd7\xd8\x94\xa8\xd0\x6c\x60\x35\x2d\x4a\x9d\xb1\xb6\xa3\x15\x4e\x76\xd3\xca\xe6\x6b\x68\x08\x75\xd3\x86\x4f\x27\x8d\x94\x38\xd1\xce\x5b\xac\xc6\x7d\xd0\x5b\x6d\xba\xc8\xa2\x2f\xec\x20\xc7\x05\x2b\xc0\xe0\xe7\x27\x21\x86\xce\x02\x63\xdd\x32\x04\xa0\xd1\xc1\x6c\x79\x62\x6d\x99\xa6\xa3\xf1\xe2\xac\xc1\x35\x6d\x46\x5c\x52\x31\x35\x13\xb4\x31\xe9\x90\xbc\x66\x64\x77\xcb\x52\x01\x35\xad\x42\x48\x71\xb3\x0c\x76\xb1\x02\x2d\xd4\x8c\xa7\x37\x8d\xb3\x58\xc1\x46\xa8\x45\x9a\xf9\xd2\x17\x6d\xd9\xe8\x06\x91\x46\x65\x17\xd6\x76\x85\xfd\x6d\x06\x2d\xd8\x6c\xac\xd3\xde\x46\x81\x6e\x30\xd6\x8d\x17\x00\xcd\x25\xd9\x0b\xc9\x39\x89\x47\x97\xa2\x2c\x86\xda\x6c\x0e\xd5\xde\x5c\x2e\x96\x91\xa4\x7e\xbf\x6b\x82\x41\x6d\xae\x7f\x52\xe0\x0a\xf5\xde\xdc\xd0\x83\xaf\x74\x9a\x5b\x5a\x5d\x6d\x9f\xd4\x09\x6e\xa4\xa1\xdb\xc1\x87\x2e\xcd\xed\x74\x92\xd3\x0d\xcb\x74\x2b\x64\x1f\xa7\x8f\xd2\xdc\x1a\x67\x84\xb6\xe1\xa4\x53\x36\x70\xd1\xef\x96\xc9\x86\x33\x3d\x60\x5a\xda\x84\xa6\x6c\x70\x35\x90\xa1\x8e\xff\x53\xa7\x6d\xe6\x13\x99\x0c\x49\x9a\x99\x31\x4d\x9b\xb9\xb1\x06\x2b\x23\xbd\xf8\x4c\xa6\x81\x09\x33\x13\x64\x80\xe1\x09\x2e\x0b\x6d\xfa\xfd\x1d\xfe\x4d\x81\x17\xf1\x6f\x42\x0b\xfe\x9b\x52\x56\xc6\x85\x49\xb7\xf0\x6f\xd2\x6a\xc3\x31\x2f\xd0\xe8\x70\xba\x93\x20\x81\x9e\xf7\xfb\x8b\x77\x20\x1e\x37\x8d\x80\xf8\x5c\x94\xf3\xb8\x6b\x8a\x39\x38\x23\x04\xa2\xc3\x23\x28\xec\xeb\xbc\xcf\x11\x97\x06\xe7\xe1\x83\x23\x28\xdd\x99\x1b\x80\x9d\x35\x9d\x8d\x59\xf0\x09\xf0\x42\x96\x97\x9a\x2e\xff\x7b\x52\xe8\xf2\xf7\xda\xc0\x65\xbd\x6e\x71\xe1\x2b\x0e\x17\xbe\x62\x80\x29\x1c\x31\xf0\xc5\xc6\x0b\x95\xeb\x02\xd7\x25\xb9\x30\x3b\x08\x79\xbd\x07\x8d\xe9\xb2\xf3\x28\xd6\x65\x67\x0c\xe5\x72\x50\xfb\xb8\xac\xc3\x59\x97\xf5\x6a\xc7\xe5\x98\xa7\xa2\xfc\x84\xe4\x3b\x6f\x68\x5c\xce\x8c\x26\x27\x19\xcb\xe5\x71\x7f\xa3\x25\x84\x77\x1d\xc8\xd2\xb8\xb9\x64\xee\x49\xb2\x5c\x4c\x14\x6e\x88\x43\xcd\xb1\x61\xb6\x67\x70\xd2\xc1\x65\x45\x11\x3c\xdf\x77\xa9\x08\x77\x5d\x78\x68\xe4\xd4\x0b\x2e\x8d\x67\x03\x2e\x4d\x06\x4b\x9b\x71\xe6\x36\x34\x07\x97\x8e\x5f\x8a\x44\x47\x87\x42\x70\xe9\x4d\xd8\xa1\x2f\x38\x8b\x60\x89\x43\x1d\xd9\xc1\xa3\x2e\x47\xe4\xcd\xea\x59\x39\xe8\x75\x7f\x63\xa4\x8b\x8a\xc4\xe5\x33\x40\x77\x7a\xa0\xce\x74\xde\xef\xc3\x30\xef\x11\x09\x29\xa7\x47\x0c\x7e\xbf\x4f\x92\x54\x4f\x2c\x5b\x2b\x9f\x26\xb9\x2e\x6d\xcd\xd3\x68\xd7\x7f\x13\x72\xc3\x47\x33\xae\x03\xbb\x84\xea\xe1\x45\x8f\xf3\x9a\x0f\x92\x06\x00\xff\xc7\x6d\x5f\x10\x94\xb3\xf5\xba\xcd\x0d\xd4\xb4\xe7\xea\x01\x42\x19\x7d\x38\xb7\xd2\x58\x53\xf1\xc3\x3a\xe9\xc4\xb8\x35\x82\xd5\x04\xb3\xd2\xf7\x77\x63\x70\xeb\x7c\x0a\xe8\x73\xbb\xdf\x80\x58\x36\xbc\x45\x87\x88\x04\x9f\x24\x31\x4f\x01\x9c\x81\xa7\x2f\xbf\xde\xe1\x38\xf8\x44\x84\xeb\xb3\xb0\x53\xe3\x2b\x48\x9e\xb2\xfb\x1c\x68\xdb\x21\x27\xbb\x85\xce\x73\xd4\xce\x23\x9f\xce\xdb\x8d\x1e\x61\x1e\x7a\x3c\xe3\x0b\xd0\x57\xab\x1c\x01\xd6\x27\x16\xdb\x23\x44\xbd\xc7\x25\xea\x3d\xe6\xbf\xa4\xb3\xdd\x60\x83\xb9\x03\x5e\x1c\xad\x6c\xa8\xf8\x3b\xc1\xef\xb1\xd2\x1d\xea\xb1\x0a\x6b\x2b\x22\x94\x1e\x2b\x05\x87\xc7\xbc\x9d\x87\x15\x3d\x36\x00\xf8\x07\x3d\xfa\xce\x85\x47\x1f\x60\xe3\x1e\xfb\x60\x27\x3e\xa7\xe9\xbc\xe4\xe9\xf1\xc3\xf8\x3c\xa9\xff\xef\x38\xa8\x4b\x32\x00\xb0\x12\xd2\x11\x43\x97\x3d\x74\x39\x27\x96\x2f\xda\x43\xe7\x25\x7e\x97\x7c\xa1\xae\x20\x9e\xef\x52\x48\xcc\x4e\x26\xea\x52\xa1\x43\x79\x3f\x98\x99\x30\xb7\xfc\x9b\x2e\x4d\xd1\xe4\x1f\xcf\xaf\x3b\x70\x29\xae\x02\xb8\x30\xb3\x0e\x89\xbb\x74\x0a\x48\xff\x3b\x52\xea\xc2\xcc\xf8\x2b\xbc\x88\x52\xf9\x20\xc0\x4a\x15\xf6\xb8\xaf\xeb\xa2\xae\x70\xa7\xba\x9e\x58\x26\x2f\xae\xfb\xfd\xce\x11\x08\xd5\x0c\xf5\xdf\x35\x0b\x5f\x82\xf6\xb5\xea\xfb\x5d\x36\x63\xe3\xc2\x42\x87\x77\xd2\xb5\x0f\x18\xc4\xce\xe3\xa1\xae\x7c\xa6\xdc\x69\x3a\x3b\xbd\xff\x4e\xab\xd9\x2d\xe3\x17\x5b\x44\xb2\x93\xf8\x96\x79\x73\xdc\xef\x1f\xfa\x8a\xdd\x78\x29\xd7\x2d\xcf\x3f\x24\x1b\x0f\xc9\xbb\x55\x48\x42\xb7\xba\x5a\x55\x38\xc2\xdd\x2a\xa5\xa9\x1b\x47\x6c\x99\x3d\xd7\x6b\x81\xce\xab\x89\x6e\xbe\xee\x79\x3b\x0a\x91\xef\x8b\xc0\xf7\xcf\x20\x27\x4c\x04\x83\x7d\x6e\x40\xe3\xa4\x9d\xeb\x34\x44\x7d\xca\x89\x69\xe9\x89\xf6\xe5\x59\xf5\x15\xfa\xf6\x79\x38\x9b\x33\x3c\xea\x33\x2f\x26\xe1\x3d\x52\x9f\x70\xbf\x98\x92\x85\xe7\x32\xf0\x7d\x36\xaa\xb5\x3e\xf1\xed\x89\x5f\x7f\x63\xfa\xc9\x86\x9d\x63\x41\x93\x8d\xc8\x27\xea\x23\x6e\xd0\x18\x48\x73\x04\xbc\x7f\xc3\x58\x15\xd0\xe3\x7c\x0f\x3a\x22\xb6\x3c\xe8\x74\x8f\xb8\x4e\x1b\xd7\xeb\xc5\xb1\x84\x66\xc4\x42\x3b\x31\x62\x81\x84\x0f\x5a\xa1\x11\xeb\x1a\xb8\xa1\x5d\x03\x03\x8c\x08\x4e\x1b\xb1\xad\x4e\xff\xa6\xae\x41\x7c\x47\x9d\x0b\xbf\xa1\xe8\x46\xf4\x27\xd8\x6b\x44\xb7\x01\xe8\x18\xcf\x59\x32\x66\x7c\xa2\xf9\x64\xd9\x0b\x45\xb4\x5f\x43\xf8\xca\x65\xd0\x2d\x1e\x92\x30\xf2\xfd\x9d\xf8\x46\x66\xc8\x13\x6c\x30\xe4\x29\x0e\xa8\xcc\xa0\x85\xe4\xfb\xfb\x40\x24\x42\xce\x1a\x02\x65\x33\xd6\x63\x81\x21\x35\xbe\x00\x77\x76\xaa\x0b\x6a\x07\xec\xa8\x36\x5e\xbe\x21\x9c\xe0\xb6\x04\x18\x1f\xf7\xb7\xf3\xd9\xdd\x10\xaf\xd0\x58\x03\x2e\x2f\x7a\x76\xf6\xec\xc6\x35\xf6\x81\x20\x70\x08\x63\x91\x41\x81\x19\xf2\x0a\x43\xa1\xc4\x86\x6e\x93\x27\x6a\x43\xa5\x34\xe4\x29\xc4\x43\x79\xcd\x34\x14\xfc\x33\x14\xfa\x66\xe8\x93\x03\xf0\x02\x64\x28\xcf\x86\x07\x9c\x0a\xec\x0f\x7e\xd0\xe0\xa3\xaf\x01\xcb\x30\xee\x77\x83\x75\x19\xca\x21\xd9\xed\x6f\x16\xb2\xd6\xb8\xdf\x43\x56\xff\x01\xf5\x3b\x14\xb8\xb5\x45\x67\xdb\x18\xe9\x0f\x83\x62\x1d\x96\xb8\x43\xc3\x2c\x76\xa2\x3a\xf3\xb3\xb0\x92\x55\xe4\x11\x6b\x2c\x68\x12\x06\x5f\xb5\x8d\xfb\xc7\xe3\x47\x18\xc6\x30\x7f\x98\x17\x2a\x0f\x98\x48\x61\x9e\xa0\x09\x07\x73\xac\x85\xcf\x4c\x86\xf9\x98\x9c\xa6\xe3\x87\x3d\xf0\x6d\xd5\x80\xb3\x87\x9c\xc7\x8d\x7c\xea\xeb\x3e\x7e\xbd\x48\x1e\xff\xbb\x0b\x1c\x8e\x48\x72\xf0\xf6\x73\x78\x2c\xfc\x86\xbf\xb5\x4c\xf2\xf0\x08\xcf\x6e\x38\x5f\xdb\x0e\xbf\xbf\x37\xcb\x61\xc0\xbf\x45\xa9\x2c\x0c\xba\x54\x00\x6e\x08\x4e\xc0\x70\xdd\x26\x20\x87\x46\xb4\x30\x9c\xcf\xf8\x86\xeb\xac\x07\x0a\xed\x10\x26\x85\x95\xb4\x98\x83\xc6\x72\xf0\xe1\xea\x70\x38\xd5\xc3\x27\xcb\xf9\x4c\x75\xf8\x04\xf3\xcf\x6d\x5d\xeb\x8e\xb9\x59\x18\x93\x6f\x14\xc6\x84\xf9\x19\x34\x86\xe3\xfe\xad\x92\x99\x90\xb9\xa7\xf3\xf9\xe9\x98\xce\xd3\xc1\x31\xe1\x71\x0c\x3e\xaf\x9e\x1b\x23\xa5\xfb\x37\x33\x66\x9c\xd0\x72\x39\xcc\x65\xa5\xe8\x8a\xcc\xaa\x17\xe2\xb1\x30\x2b\x7e\x50\x8b\x0c\xb1\xa6\xd3\x09\x9d\xbe\x49\x98\xbe\xae\x7c\x27\x62\x2b\xfe\x0d\x64\xf6\xc9\xe7\x4a\xeb\xce\x69\x0e\xe3\xab\x8f\x79\xc5\x70\x21\x0c\xba\x62\x02\xcb\x5d\x91\x6f\xc2\x2e\x3e\xe4\xbf\x40\x85\x2b\x2a\x0b\xd6\xd1\xed\x15\xb3\x84\xeb\x2f\x7e\xbf\xf8\x6e\xea\xe2\xa3\x56\x94\x5d\x93\x2d\x4a\x83\x1f\x75\x45\x47\xc6\x95\x03\x91\x6d\x2f\x84\xc6\x97\x90\x15\xaf\x75\x59\x72\xc9\xe3\x7e\xf3\xc0\xef\x02\xd9\x24\x5c\xf2\x94\x57\xe0\x21\xd6\x25\x34\xfa\x97\x64\x43\x09\x56\x21\x7c\x11\x7b\x51\xb8\x2e\xa9\xc2\x81\x2a\xd7\x2a\x40\xcd\x45\xee\xbc\xa4\xce\x1e\x2e\xb6\xe4\xad\xf2\x25\xbe\x11\xee\x98\xc0\x85\xbd\xfd\x49\xc8\x25\xf9\x40\x63\x20\xe4\x52\x30\xdd\xa5\x1b\xb4\xf5\xc5\xa3\xa4\xeb\x7e\x27\x5e\x0c\x5d\x8a\x8e\xf7\x1b\x06\xe7\xd2\x1d\xd8\xbc\x14\x7e\x31\xef\xef\xa4\x87\x8b\x5e\xde\xa5\x19\x3f\xec\x40\x6b\x84\xd0\xf3\xc5\xd6\xa5\xf7\x7f\x90\x93\x4b\x2d\xdf\xef\x1a\x2e\x05\x61\x2f\x75\x20\x59\x7d\xcc\x3d\x5c\xda\x89\xca\x77\x67\xb0\xbe\x5c\xcd\x4b\x47\xe4\x09\xe0\xa5\x93\xdd\xaf\xf8\x02\x24\x6e\x14\x76\xfe\xd2\xcb\xc2\x65\x99\xf7\xa7\x97\x65\xba\xb3\x97\x65\x62\xc0\x1c\xcd\xe9\xd3\x5d\x08\xa7\x2f\x20\x93\xd6\xeb\x9a\x7c\x98\xf9\xc9\x0b\xec\x4f\xf8\xc7\x9f\x94\xa0\x4f\xe8\xd5\x4f\xde\x48\x7e\x42\x71\x7d\x42\x6b\x7c\x42\x6b\x7c\xda\x39\x3d\xbc\xe2\x01\x02\xbf\x78\xd4\xfa\x8a\x0d\x22\xf9\xe2\x1b\x85\x97\x55\x00\xe8\xfe\xd7\x2c\x00\xb0\xb5\xff\x1f\x00\x00\xff\xff\x11\x91\x1a\xde\x5b\x35\x00\x00") - -func keysWordsWordlistSpanishTxtBytes() ([]byte, error) { - return bindataRead( - _keysWordsWordlistSpanishTxt, - "keys/words/wordlist/spanish.txt", - ) -} - -func keysWordsWordlistSpanishTxt() (*asset, error) { - bytes, err := keysWordsWordlistSpanishTxtBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "keys/words/wordlist/spanish.txt", size: 13659, mode: os.FileMode(420), modTime: time.Unix(1523115814, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "keys/words/wordlist/chinese_simplified.txt": keysWordsWordlistChinese_simplifiedTxt, - "keys/words/wordlist/english.txt": keysWordsWordlistEnglishTxt, - "keys/words/wordlist/japanese.txt": keysWordsWordlistJapaneseTxt, - "keys/words/wordlist/spanish.txt": keysWordsWordlistSpanishTxt, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} -var _bintree = &bintree{nil, map[string]*bintree{ - "keys": &bintree{nil, map[string]*bintree{ - "words": &bintree{nil, map[string]*bintree{ - "wordlist": &bintree{nil, map[string]*bintree{ - "chinese_simplified.txt": &bintree{keysWordsWordlistChinese_simplifiedTxt, map[string]*bintree{}}, - "english.txt": &bintree{keysWordsWordlistEnglishTxt, map[string]*bintree{}}, - "japanese.txt": &bintree{keysWordsWordlistJapaneseTxt, map[string]*bintree{}}, - "spanish.txt": &bintree{keysWordsWordlistSpanishTxt, map[string]*bintree{}}, - }}, - }}, - }}, -}} - -// RestoreAsset restores an asset under the given directory -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil -} - -// RestoreAssets restores an asset under the given directory recursively -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) -} - From a589e0eabd113cb6f788e8f24b75870c11816937 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 20 Jun 2018 14:09:24 -0700 Subject: [PATCH 271/273] delete keys package - it will be moved to cosmos-sdk --- keys/bcrypt/base64.go | 35 ---- keys/bcrypt/bcrypt.go | 292 -------------------------- keys/bip39/wordcodec.go | 62 ------ keys/bip39/wordcodec_test.go | 15 -- keys/hd/fundraiser_test.go | 83 -------- keys/hd/hdpath.go | 168 --------------- keys/hd/hdpath_test.go | 73 ------- keys/hd/test.json | 1 - keys/keybase.go | 362 --------------------------------- keys/keybase_test.go | 383 ----------------------------------- keys/keys.go | 12 -- keys/keys.toml | 2 - keys/mintkey.go | 115 ----------- keys/types.go | 142 ------------- keys/wire.go | 16 -- 15 files changed, 1761 deletions(-) delete mode 100644 keys/bcrypt/base64.go delete mode 100644 keys/bcrypt/bcrypt.go delete mode 100644 keys/bip39/wordcodec.go delete mode 100644 keys/bip39/wordcodec_test.go delete mode 100644 keys/hd/fundraiser_test.go delete mode 100644 keys/hd/hdpath.go delete mode 100644 keys/hd/hdpath_test.go delete mode 100644 keys/hd/test.json delete mode 100644 keys/keybase.go delete mode 100644 keys/keybase_test.go delete mode 100644 keys/keys.go delete mode 100644 keys/keys.toml delete mode 100644 keys/mintkey.go delete mode 100644 keys/types.go delete mode 100644 keys/wire.go diff --git a/keys/bcrypt/base64.go b/keys/bcrypt/base64.go deleted file mode 100644 index fc3116090..000000000 --- a/keys/bcrypt/base64.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bcrypt - -import "encoding/base64" - -const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - -var bcEncoding = base64.NewEncoding(alphabet) - -func base64Encode(src []byte) []byte { - n := bcEncoding.EncodedLen(len(src)) - dst := make([]byte, n) - bcEncoding.Encode(dst, src) - for dst[n-1] == '=' { - n-- - } - return dst[:n] -} - -func base64Decode(src []byte) ([]byte, error) { - numOfEquals := 4 - (len(src) % 4) - for i := 0; i < numOfEquals; i++ { - src = append(src, '=') - } - - dst := make([]byte, bcEncoding.DecodedLen(len(src))) - n, err := bcEncoding.Decode(dst, src) - if err != nil { - return nil, err - } - return dst[:n], nil -} diff --git a/keys/bcrypt/bcrypt.go b/keys/bcrypt/bcrypt.go deleted file mode 100644 index ce2b9f4bc..000000000 --- a/keys/bcrypt/bcrypt.go +++ /dev/null @@ -1,292 +0,0 @@ -package bcrypt - -// MODIFIED BY TENDERMINT TO EXPOSE NONCE -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing -// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf - -// The code is a port of Provos and Mazières's C implementation. -import ( - "crypto/subtle" - "errors" - "fmt" - "strconv" - - "golang.org/x/crypto/blowfish" -) - -const ( - MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword - MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword - DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword -) - -// The error returned from CompareHashAndPassword when a password and hash do -// not match. -var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") - -// The error returned from CompareHashAndPassword when a hash is too short to -// be a bcrypt hash. -var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") - -// The error returned from CompareHashAndPassword when a hash was created with -// a bcrypt algorithm newer than this implementation. -type HashVersionTooNewError byte - -func (hv HashVersionTooNewError) Error() string { - return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) -} - -// The error returned from CompareHashAndPassword when a hash starts with something other than '$' -type InvalidHashPrefixError byte - -func (ih InvalidHashPrefixError) Error() string { - return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) -} - -type InvalidCostError int - -func (ic InvalidCostError) Error() string { - return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) // nolint: unconvert -} - -const ( - majorVersion = '2' - minorVersion = 'a' - maxSaltSize = 16 - maxCryptedHashSize = 23 - encodedSaltSize = 22 - encodedHashSize = 31 - minHashSize = 59 -) - -// magicCipherData is an IV for the 64 Blowfish encryption calls in -// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. -var magicCipherData = []byte{ - 0x4f, 0x72, 0x70, 0x68, - 0x65, 0x61, 0x6e, 0x42, - 0x65, 0x68, 0x6f, 0x6c, - 0x64, 0x65, 0x72, 0x53, - 0x63, 0x72, 0x79, 0x44, - 0x6f, 0x75, 0x62, 0x74, -} - -type hashed struct { - hash []byte - salt []byte - cost int // allowed range is MinCost to MaxCost - major byte - minor byte -} - -// GenerateFromPassword returns the bcrypt hash of the password at the given -// cost. If the cost given is less than MinCost, the cost will be set to -// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, -// to compare the returned hashed password with its cleartext version. -func GenerateFromPassword(salt []byte, password []byte, cost int) ([]byte, error) { - if len(salt) != maxSaltSize { - return nil, fmt.Errorf("salt len must be %v", maxSaltSize) - } - p, err := newFromPassword(salt, password, cost) - if err != nil { - return nil, err - } - return p.Hash(), nil -} - -// CompareHashAndPassword compares a bcrypt hashed password with its possible -// plaintext equivalent. Returns nil on success, or an error on failure. -func CompareHashAndPassword(hashedPassword, password []byte) error { - p, err := newFromHash(hashedPassword) - if err != nil { - return err - } - - otherHash, err := bcrypt(password, p.cost, p.salt) - if err != nil { - return err - } - - otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} - if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { - return nil - } - - return ErrMismatchedHashAndPassword -} - -// Cost returns the hashing cost used to create the given hashed -// password. When, in the future, the hashing cost of a password system needs -// to be increased in order to adjust for greater computational power, this -// function allows one to establish which passwords need to be updated. -func Cost(hashedPassword []byte) (int, error) { - p, err := newFromHash(hashedPassword) - if err != nil { - return 0, err - } - return p.cost, nil -} - -func newFromPassword(salt []byte, password []byte, cost int) (*hashed, error) { - if cost < MinCost { - cost = DefaultCost - } - p := new(hashed) - p.major = majorVersion - p.minor = minorVersion - - err := checkCost(cost) - if err != nil { - return nil, err - } - p.cost = cost - - p.salt = base64Encode(salt) - hash, err := bcrypt(password, p.cost, p.salt) - if err != nil { - return nil, err - } - p.hash = hash - return p, err -} - -func newFromHash(hashedSecret []byte) (*hashed, error) { - if len(hashedSecret) < minHashSize { - return nil, ErrHashTooShort - } - p := new(hashed) - n, err := p.decodeVersion(hashedSecret) - if err != nil { - return nil, err - } - hashedSecret = hashedSecret[n:] - n, err = p.decodeCost(hashedSecret) - if err != nil { - return nil, err - } - hashedSecret = hashedSecret[n:] - - // The "+2" is here because we'll have to append at most 2 '=' to the salt - // when base64 decoding it in expensiveBlowfishSetup(). - p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) - copy(p.salt, hashedSecret[:encodedSaltSize]) - - hashedSecret = hashedSecret[encodedSaltSize:] - p.hash = make([]byte, len(hashedSecret)) - copy(p.hash, hashedSecret) - - return p, nil -} - -func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { - cipherData := make([]byte, len(magicCipherData)) - copy(cipherData, magicCipherData) - - c, err := expensiveBlowfishSetup(password, uint32(cost), salt) - if err != nil { - return nil, err - } - - for i := 0; i < 24; i += 8 { - for j := 0; j < 64; j++ { - c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) - } - } - - // Bug compatibility with C bcrypt implementations. We only encode 23 of - // the 24 bytes encrypted. - hsh := base64Encode(cipherData[:maxCryptedHashSize]) - return hsh, nil -} - -func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { - - csalt, err := base64Decode(salt) - if err != nil { - return nil, err - } - - // Bug compatibility with C bcrypt implementations. They use the trailing - // NULL in the key string during expansion. - ckey := append(key, 0) - - c, err := blowfish.NewSaltedCipher(ckey, csalt) - if err != nil { - return nil, err - } - - var i, rounds uint64 - rounds = 1 << cost - for i = 0; i < rounds; i++ { - blowfish.ExpandKey(ckey, c) - blowfish.ExpandKey(csalt, c) - } - - return c, nil -} - -func (p *hashed) Hash() []byte { - arr := make([]byte, 60) - arr[0] = '$' - arr[1] = p.major - n := 2 - if p.minor != 0 { - arr[2] = p.minor - n = 3 - } - arr[n] = '$' - n += 1 - copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) - n += 2 - arr[n] = '$' - n += 1 - copy(arr[n:], p.salt) - n += encodedSaltSize - copy(arr[n:], p.hash) - n += encodedHashSize - return arr[:n] -} - -func (p *hashed) decodeVersion(sbytes []byte) (int, error) { - if sbytes[0] != '$' { - return -1, InvalidHashPrefixError(sbytes[0]) - } - if sbytes[1] > majorVersion { - return -1, HashVersionTooNewError(sbytes[1]) - } - p.major = sbytes[1] - n := 3 - if sbytes[2] != '$' { - p.minor = sbytes[2] - n++ - } - return n, nil -} - -// sbytes should begin where decodeVersion left off. -func (p *hashed) decodeCost(sbytes []byte) (int, error) { - cost, err := strconv.Atoi(string(sbytes[0:2])) - if err != nil { - return -1, err - } - err = checkCost(cost) - if err != nil { - return -1, err - } - p.cost = cost - return 3, nil -} - -func (p *hashed) String() string { - return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) -} - -func checkCost(cost int) error { - if cost < MinCost || cost > MaxCost { - return InvalidCostError(cost) - } - return nil -} diff --git a/keys/bip39/wordcodec.go b/keys/bip39/wordcodec.go deleted file mode 100644 index b0c23e629..000000000 --- a/keys/bip39/wordcodec.go +++ /dev/null @@ -1,62 +0,0 @@ -package bip39 - -import ( - "strings" - - "github.com/bartekn/go-bip39" -) - -// ValidSentenceLen defines the mnemonic sentence lengths supported by this BIP 39 library. -type ValidSentenceLen uint8 - -const ( - // FundRaiser is the sentence length used during the cosmos fundraiser (12 words). - FundRaiser ValidSentenceLen = 12 - // FreshKey is the sentence length used for newly created keys (24 words). - FreshKey ValidSentenceLen = 24 -) - -// NewMnemonic will return a string consisting of the mnemonic words for -// the given sentence length. -func NewMnemonic(len ValidSentenceLen) (words []string, err error) { - // len = (ENT + checksum) / 11 - var ENT int - switch len { - case FundRaiser: - ENT = 128 - case FreshKey: - ENT = 256 - } - var entropy []byte - entropy, err = bip39.NewEntropy(ENT) - if err != nil { - return - } - var mnemonic string - mnemonic, err = bip39.NewMnemonic(entropy) - if err != nil { - return - } - words = strings.Split(mnemonic, " ") - return -} - -// MnemonicToSeed creates a BIP 39 seed from the passed mnemonic (with an empty BIP 39 password). -// This method does not validate the mnemonics checksum. -func MnemonicToSeed(mne string) (seed []byte) { - // we do not checksum here... - seed = bip39.NewSeed(mne, "") - return -} - -// MnemonicToSeedWithErrChecking returns the same seed as MnemonicToSeed. -// It creates a BIP 39 seed from the passed mnemonic (with an empty BIP 39 password). -// -// Different from MnemonicToSeed it validates the checksum. -// For details on the checksum see the BIP 39 spec. -func MnemonicToSeedWithErrChecking(mne string) (seed []byte, err error) { - seed, err = bip39.NewSeedWithErrorChecking(mne, "") - return -} - - diff --git a/keys/bip39/wordcodec_test.go b/keys/bip39/wordcodec_test.go deleted file mode 100644 index dbc5c0d02..000000000 --- a/keys/bip39/wordcodec_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package bip39 - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestWordCodec_NewMnemonic(t *testing.T) { - _, err := NewMnemonic(FundRaiser) - assert.NoError(t, err, "unexpected error generating fundraiser mnemonic") - - _, err = NewMnemonic(FreshKey) - assert.NoError(t, err, "unexpected error generating new 24-word mnemonic") -} diff --git a/keys/hd/fundraiser_test.go b/keys/hd/fundraiser_test.go deleted file mode 100644 index 63607b0a5..000000000 --- a/keys/hd/fundraiser_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package hd - -import ( - "encoding/hex" - "encoding/json" - "fmt" - "io/ioutil" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/tyler-smith/go-bip39" - - "github.com/tendermint/go-crypto" -) - -type addrData struct { - Mnemonic string - Master string - Seed string - Priv string - Pub string - Addr string -} - - -func initFundraiserTestVectors(t *testing.T) []addrData { - // NOTE: atom fundraiser address - // var hdPath string = "m/44'/118'/0'/0/0" - var hdToAddrTable []addrData - - b, err := ioutil.ReadFile("test.json") - if err != nil { - t.Fatalf("could not read fundraiser test vector file (test.json): %s", err) - } - - err = json.Unmarshal(b, &hdToAddrTable) - if err != nil { - t.Fatalf("could not decode test vectors (test.json): %s", err) - } - return hdToAddrTable -} - -func TestFundraiserCompatibility(t *testing.T) { - hdToAddrTable := initFundraiserTestVectors(t) - - for i, d := range hdToAddrTable { - privB, _ := hex.DecodeString(d.Priv) - pubB, _ := hex.DecodeString(d.Pub) - addrB, _ := hex.DecodeString(d.Addr) - seedB, _ := hex.DecodeString(d.Seed) - masterB, _ := hex.DecodeString(d.Master) - - seed := bip39.NewSeed(d.Mnemonic, "") - - t.Log("================================") - t.Logf("ROUND: %d MNEMONIC: %s", i, d.Mnemonic) - - master, ch := ComputeMastersFromSeed(seed) - priv, err := DerivePrivateKeyForPath(master, ch, "44'/118'/0'/0/0") - assert.NoError(t, err) - pub := crypto.PrivKeySecp256k1(priv).PubKey() - - t.Log("\tNODEJS GOLANG\n") - t.Logf("SEED \t%X %X\n", seedB, seed) - t.Logf("MSTR \t%X %X\n", masterB, master) - t.Logf("PRIV \t%X %X\n", privB, priv) - t.Logf("PUB \t%X %X\n", pubB, pub) - - assert.Equal(t, seedB, seed) - assert.Equal(t, master[:], masterB, fmt.Sprintf("Expected masters to match for %d", i)) - assert.Equal(t, priv[:], privB, "Expected priv keys to match") - var pubBFixed [33]byte - copy(pubBFixed[:], pubB) - assert.Equal(t, pub, crypto.PubKeySecp256k1(pubBFixed), fmt.Sprintf("Expected pub keys to match for %d", i)) - - addr := pub.Address() - t.Logf("ADDR \t%X %X\n", addrB, addr) - assert.Equal(t, addr, crypto.Address(addrB), fmt.Sprintf("Expected addresses to match %d", i)) - - } -} - - diff --git a/keys/hd/hdpath.go b/keys/hd/hdpath.go deleted file mode 100644 index 00d0572cc..000000000 --- a/keys/hd/hdpath.go +++ /dev/null @@ -1,168 +0,0 @@ -// Package hd provides basic functionality Hierarchical Deterministic Wallets. -// -// The user must understand the overall concept of the BIP 32 and the BIP 44 specs: -// https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki -// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki -// -// In combination with the bip39 package in go-crypto this package provides the functionality for deriving keys using a -// BIP 44 HD path, or, more general, by passing a BIP 32 path. -// -// In particular, this package (together with bip39) provides all necessary functionality to derive keys from -// mnemonics generated during the cosmos fundraiser. -package hd - -import ( - "crypto/hmac" - "crypto/sha512" - "encoding/binary" - "errors" - "fmt" - "math/big" - "strconv" - "strings" - - "github.com/btcsuite/btcd/btcec" - "github.com/tendermint/go-crypto" -) - -// BIP44Prefix is the parts of the BIP32 HD path that are fixed by what we used during the fundraiser. -const ( - BIP44Prefix = "44'/118'/" - FullFundraiserPath = BIP44Prefix + "0'/0/0" -) - -// BIP44Params wraps BIP 44 params (5 level BIP 32 path). -// To receive a canonical string representation ala -// m / purpose' / coin_type' / account' / change / address_index -// call String() on a BIP44Params instance. -type BIP44Params struct { - purpose uint32 - coinType uint32 - account uint32 - change bool - addressIdx uint32 -} - -// NewParams creates a BIP 44 parameter object from the params: -// m / purpose' / coin_type' / account' / change / address_index -func NewParams(purpose, coinType, account uint32, change bool, addressIdx uint32) *BIP44Params { - return &BIP44Params{ - purpose: purpose, - coinType: coinType, - account: account, - change: change, - addressIdx: addressIdx, - } -} - -// NewFundraiserParams creates a BIP 44 parameter object from the params: -// m / 44' / 118' / account' / 0 / address_index -// The fixed parameters (purpose', coin_type', and change) are determined by what was used in the fundraiser. -func NewFundraiserParams(account uint32, addressIdx uint32) *BIP44Params { - return NewParams(44, 118, account, false, addressIdx) -} - -func (p BIP44Params) String() string { - var changeStr string - if p.change { - changeStr = "1" - } else { - changeStr = "0" - } - // m / purpose' / coin_type' / account' / change / address_index - return fmt.Sprintf("%d'/%d'/%d'/%s/%d", - p.purpose, - p.coinType, - p.account, - changeStr, - p.addressIdx) -} - -// ComputeMastersFromSeed returns the master public key, master secret, and chain code in hex. -func ComputeMastersFromSeed(seed []byte) (secret [32]byte, chainCode [32]byte) { - masterSecret := []byte("Bitcoin seed") - secret, chainCode = i64(masterSecret, seed) - - return -} - -// DerivePrivateKeyForPath derives the private key by following the BIP 32/44 path from privKeyBytes, -// using the given chainCode. -func DerivePrivateKeyForPath(privKeyBytes [32]byte, chainCode [32]byte, path string) ([32]byte, error) { - data := privKeyBytes - parts := strings.Split(path, "/") - for _, part := range parts { - // do we have an apostrophe? - harden := part[len(part)-1:] == "'" - // harden == private derivation, else public derivation: - if harden { - part = part[:len(part)-1] - } - idx, err := strconv.Atoi(part) - if err != nil { - return [32]byte{}, fmt.Errorf("invalid BIP 32 path: %s", err) - } - if idx < 0 { - return [32]byte{}, errors.New("invalid BIP 32 path: index negative ot too large") - } - data, chainCode = derivePrivateKey(data, chainCode, uint32(idx), harden) - } - var derivedKey [32]byte - n := copy(derivedKey[:], data[:]) - if n != 32 || len(data) != 32 { - return [32]byte{}, fmt.Errorf("expected a (secp256k1) key of length 32, got length: %v", len(data)) - } - - return derivedKey, nil -} - -// derivePrivateKey derives the private key with index and chainCode. -// If harden is true, the derivation is 'hardened'. -// It returns the new private key and new chain code. -// For more information on hardened keys see: -// - https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki -func derivePrivateKey(privKeyBytes [32]byte, chainCode [32]byte, index uint32, harden bool) ([32]byte, [32]byte) { - var data []byte - if harden { - index = index | 0x80000000 - data = append([]byte{byte(0)}, privKeyBytes[:]...) - } else { - // this can't return an error: - pubkey := crypto.PrivKeySecp256k1(privKeyBytes).PubKey() - - public := pubkey.(crypto.PubKeySecp256k1) - data = public[:] - } - data = append(data, uint32ToBytes(index)...) - data2, chainCode2 := i64(chainCode[:], data) - x := addScalars(privKeyBytes[:], data2[:]) - return x, chainCode2 -} - -// modular big endian addition -func addScalars(a []byte, b []byte) [32]byte { - aInt := new(big.Int).SetBytes(a) - bInt := new(big.Int).SetBytes(b) - sInt := new(big.Int).Add(aInt, bInt) - x := sInt.Mod(sInt, btcec.S256().N).Bytes() - x2 := [32]byte{} - copy(x2[32-len(x):], x) - return x2 -} - -func uint32ToBytes(i uint32) []byte { - b := [4]byte{} - binary.BigEndian.PutUint32(b[:], i) - return b[:] -} - -// i64 returns the two halfs of the SHA512 HMAC of key and data. -func i64(key []byte, data []byte) (IL [32]byte, IR [32]byte) { - mac := hmac.New(sha512.New, key) - // sha512 does not err - _, _ = mac.Write(data) - I := mac.Sum(nil) - copy(IL[:], I[:32]) - copy(IR[:], I[32:]) - return -} diff --git a/keys/hd/hdpath_test.go b/keys/hd/hdpath_test.go deleted file mode 100644 index b014ae804..000000000 --- a/keys/hd/hdpath_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package hd - -import ( - "encoding/hex" - "fmt" - "github.com/tendermint/go-crypto/keys/bip39" -) - -func ExampleStringifyPathParams() { - path := NewParams(44, 0, 0, false, 0) - fmt.Println(path.String()) - // Output: 44'/0'/0'/0/0 -} - -func ExampleSomeBIP32TestVecs() { - - seed := bip39.MnemonicToSeed("barrel original fuel morning among eternal " + - "filter ball stove pluck matrix mechanic") - master, ch := ComputeMastersFromSeed(seed) - fmt.Println("keys from fundraiser test-vector (cosmos, bitcoin, ether)") - fmt.Println() - // cosmos - priv, _ := DerivePrivateKeyForPath(master, ch, FullFundraiserPath) - fmt.Println(hex.EncodeToString(priv[:])) - // bitcoin - priv, _ = DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/0") - fmt.Println(hex.EncodeToString(priv[:])) - // ether - priv, _ = DerivePrivateKeyForPath(master, ch, "44'/60'/0'/0/0") - fmt.Println(hex.EncodeToString(priv[:])) - - fmt.Println() - fmt.Println("keys generated via https://coinomi.com/recovery-phrase-tool.html") - fmt.Println() - - seed = bip39.MnemonicToSeed( - "advice process birth april short trust crater change bacon monkey medal garment " + - "gorilla ranch hour rival razor call lunar mention taste vacant woman sister") - master, ch = ComputeMastersFromSeed(seed) - priv, _ = DerivePrivateKeyForPath(master, ch, "44'/1'/1'/0/4") - fmt.Println(hex.EncodeToString(priv[:])) - - seed = bip39.MnemonicToSeed("idea naive region square margin day captain habit " + - "gun second farm pact pulse someone armed") - master, ch = ComputeMastersFromSeed(seed) - priv, _ = DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/420") - fmt.Println(hex.EncodeToString(priv[:])) - - fmt.Println() - fmt.Println("BIP 32 example") - fmt.Println() - - // bip32 path: m/0/7 - seed = bip39.MnemonicToSeed("monitor flock loyal sick object grunt duty ride develop assault harsh history") - master, ch = ComputeMastersFromSeed(seed) - priv, _ = DerivePrivateKeyForPath(master, ch, "0/7") - fmt.Println(hex.EncodeToString(priv[:])) - - // Output: keys from fundraiser test-vector (cosmos, bitcoin, ether) - // - // bfcb217c058d8bbafd5e186eae936106ca3e943889b0b4a093ae13822fd3170c - // e77c3de76965ad89997451de97b95bb65ede23a6bf185a55d80363d92ee37c3d - // 7fc4d8a8146dea344ba04c593517d3f377fa6cded36cd55aee0a0bb968e651bc - // - // keys generated via https://coinomi.com/recovery-phrase-tool.html - // - // a61f10c5fecf40c084c94fa54273b6f5d7989386be4a37669e6d6f7b0169c163 - // 32c4599843de3ef161a629a461d12c60b009b676c35050be5f7ded3a3b23501f - // - // BIP 32 example - // - // c4c11d8c03625515905d7e89d25dfc66126fbc629ecca6db489a1a72fc4bda78 -} diff --git a/keys/hd/test.json b/keys/hd/test.json deleted file mode 100644 index fa9610999..000000000 --- a/keys/hd/test.json +++ /dev/null @@ -1 +0,0 @@ -[{"mnemonic":"measure slogan connect luggage stereo federal stuff stomach stumble security end differ","master":"c177fa4bd21420b6ba2246e4f7a43fbe76545d1204174cae942ffbd79a434d11","seed":"c237f7aa198c5bd560ac8daf5b8421d03855171465b2999b07159671e9186461e7d75dba6c7264b963108431f8674ac8d095b7a22878fa0ab8b582e5d6ea1986","priv":"91bba8805845210665d7a9c5aff63ef69f7604fbeddb485706d31f04458f572c","pub":"0210ddc89abc90bbcbec8c63f5a4ebb016b58063b9d1a77854502042bdfcac5e51","addr":"72e7d6e9cfa899043a0783752a4876423f8effb8"},{"mnemonic":"car taste absurd genius miracle toy earth true glare mobile pig forest","master":"d7e07c472b05a2d668328c148ca07264afb4b53e078a2e1c106470b51c6ef81c","seed":"fda7006f5e9b8d1c02404df6d4e4497ff5c2edf29c801180a046dc54fca2e019554da6e3dd2c26073a7871c5ac529ad465ccf77ec3608727cc47ef88f998ae2b","priv":"1122ac929a0a3b2947ef99c33c20b657cf7342ea09be92869c363cfc52118200","pub":"03d0b431b56ae65aeb5a572654445b3fc968fa9d73995d3b21243cb07ed1ef0067","addr":"63eba204c249c795cd9dbdad58561db56b1d0c9b"},{"mnemonic":"trophy crop coffee oppose pelican help sense note bar faint hen aunt","master":"d1baaea05c34a4bbdc6791ada5aad77fdb0e626642cb884e48d25cd4ef6c9bed","seed":"1cdcfda64cb0e4f5806a48ff374e9f5f7d2939815e7adcce3abd898a7a9204eec4a5822997ca556ad797b4610c4ae6accddc29d80fd651a33d5ed911892479f1","priv":"c4bbb8f1ec60271c1e4f9e019ea45f82ca0ee3c42d8ac268f898fdbdfc28cf48","pub":"03abff20397222f9cae536d6b6776ba48c9b51898f7527dea918058f986fbfad15","addr":"fb6abc72817a9d2c6c1a2fe652434999661e1178"},{"mnemonic":"embrace office author among dream island social gift ask drill polar festival","master":"8d58a57b66a08bc0bd8dde7a718432a01f7aff03cbf999aeb3830d7a1c3d0d54","seed":"65b81faccab573d4a4272ab7c46e5fcc7db66eceeab6796d6dd70d8c54d6c95c3b73a637210a96a95df5ef736f51eec1dd3af4ccca53e98fb7f16d4e22dc3f52","priv":"dec3ffc51d5c9eadfb11e11dcc640f8cb294a21cfbb4a230f164693d57851b3b","pub":"03ef202a875683203e9d9643a2943cb40ff5a69b6efb3b0dedfc8ab1c6928261d1","addr":"db1a5fd30abfe666a049f5c6689a0e3db3ebec1e"},{"mnemonic":"aware gospel lemon tomorrow east wheel member forest walnut virus shallow stick","master":"24075bca853e0066909a6ff06ff02f196d4d641c00677704a6472810b0e3263e","seed":"1a4419cb19e2e7686fe68187aa55a2d4fab8d655c505c5666963d61bc9e92cfb990402d8527f9463b2deb3e86894055e3c6b31cf9995ca5bdf9959db755c9e90","priv":"853665c8f66682e50db33fe699ee72dae036422bee03e37093ed95c871ae8309","pub":"02a4e19e61decd6006bec54fa9c7ada7ee63ca6df12640e9fcf4214faafce791e6","addr":"155dac0e19dc24880b5aed827ebabb05bb563b23"},{"mnemonic":"perfect chief lend clock bracket guard extend medal slice vague cheese child","master":"b594e8d22e4864bdf75ddf29de16b7b207b2bbbdf29132b859f9c71c919ff669","seed":"631fc64164825a9769c4cd376cd736d4dd4191b7728e70b1e84b46322cb8bfb01b5b33cc6707d59bed09f6e7c82335541cd7dfc51ebedfcc2786713a9d141663","priv":"eab18ec583e155fd4ece4a14248bda80c75a6f209a1e4a9b1801e1a707b4356e","pub":"0247995311612868a8d1f6927f18ae5163a9d64a41d8f4015f9dcbbdace9277ed3","addr":"1f42f6538f64d844cef39b941986465076da3d54"},{"mnemonic":"edge early ten vicious piece begin observe ripple neutral farm volume accident","master":"1d6462662cd27419936c1f5b579eb7ebbafe84a6b1a58906c37fc0c2aa612d22","seed":"fb9588a1e3a2d9c26dcdb3cb010b8f868b29c493c95f7fe16761b2a666a8b96ca62997646e8d2cea1ff8ec3b85bd2311741ee327076515ad075623853279b57e","priv":"081847ec4f11a7d54ddd78c6f0fb3cdc32508e4956da14e0d728ddd3862124ce","pub":"03533c9f60afc94de73a0abb7d3e98906fa72cd2aebb202fdac32e2014452779d1","addr":"bcab563beb9ead1a87ab5adabc708502dc4081de"},{"mnemonic":"escape crystal wrist method cave retire wedding unable fringe inhale vibrant inform","master":"8b8597cd8ca42fe10236cc933bf0adda507132be6c41451d6ddda615b4032798","seed":"84582da23a6c4cf3d8f75be55db0d2710e10e31e9d6cee8288d827ed17d6585f19d81831aac12aff8d2724ace9c4220924e7d778eaebb3ff7ac4976b5ee25cc9","priv":"d011566a0c3996c99cf02ee41aa3f24c3328b5773ad0c9ea23f1bda1967a7e2c","pub":"03dcb9dd25915f827965c2d64e258eed1e4cf55f9fa3a9a8b5b411cbccffb11de0","addr":"54eea7e51aec6be8eca7a556c0ba5abfb702b34f"},{"mnemonic":"alter buddy rival question bachelor expose unique menu east sample also fence","master":"0eff009e6a00061a23a9b26f365cc00b0189825fe2eec0a3e78928fbd9f4dd7b","seed":"afa260446549711688b754edf33e313ceaece5502d0dbd8d82bc3c797151741620e403575ba6b54b0071e7122c8ae54893ccf29a43de209c67f7a8c296e47c84","priv":"39be182557862e0b7cf6440fb23568e54772edf734b4710ef571b37a6c27d16c","pub":"032c0d9bdbb97f2b7041734968eae96b3283573b9eefcd3ea1ce286c872bc8df4b","addr":"cbc2321a8e91ea81a56150689921b65a402b5c63"},{"mnemonic":"jar toward train panic unhappy control artefact horse deposit liar minimum pink","master":"009a99faadbdaa139f7ad2297367fdf92103c75194097133b51e0dd57629d06f","seed":"75b28bd52420c950aad1b4270fea0f8816c240e1bb16ad7f35a4bcc234e1c0bce4642422ea359dfae0332417c188a10e1b7efda4a9129809d98a179e8ef618dc","priv":"fbb6c27c23346fb30aa1aca0004f3adff649067efcbcdd58f9e8ed1be9167624","pub":"02463386f13659d68ca10edbecafab3294fddfb989b8012dd8a306c1e716ea73bc","addr":"9aef504159fcefcce23e49b64fe73d64b652751a"},{"mnemonic":"wise undo month ugly case garbage cannon torch sight burst flock enter","master":"e8533102aa8baa896888094c49fd096151adde972cbdd46429095b6081226d88","seed":"c64eab45997b8f27af96667bb8b3e3b1f13cd1cae3f33d357ef8996e958a24f78c6fff1dd21a7aad45a236d02e93722a74827e723415f4c3d2e28b5755ce74bf","priv":"7b28255abe4b5dfc46dd3e4a78aff23fd519ee20d0fccf77fa1f08dc87d4c2a8","pub":"03666213b09e6838c37edd56d858361cc7252aff15c86d9cbb7fd2ffaab2797eff","addr":"8de416131b81c2b4fb347c619e162e5b9d8e9171"},{"mnemonic":"fever hotel cup cover lake cream hello drastic scrap appear device skill","master":"c0c7ae8be6467f73da04bf31893fed60a7d2874a1b8b40cf6b947d3e0c072fd8","seed":"ba8ccb1d6df012c48cd0e97e126aca7192fc49ffe58fe554f2f96b85f7c8ee842e582a7967e053c4ea26f5ee0730dd7b78212b397f5ad89c0691c151c5b649b2","priv":"2d28bdd1c56e6f0c953b97ea571d7ee13f4b53557e9de79de436faee8b984944","pub":"02d4ef64e150ee986d14953bb42d7da5a26e184ae00d33c648e552ec31cc81df62","addr":"1919c6f2d0c93447d4fb8f10b8af4c57a06ad235"},{"mnemonic":"camp pizza test idea attend urban pond gym solution denial coach oppose","master":"e85ce81ff0663a945753449ea5a53a72e429a7badc3c681d7c13bb1b75a4d2ed","seed":"2bc62e90ae9d83635b316ef55f4ada1652dea512da332474598f53f93268ee1e18802ba19e75df651cfe931049ccc7aba7b96d43b62182e0e5b0e21a1cc2f489","priv":"bbd3109cd6edfc583ad1fca84b3c32def7d41e36f1994ac40eb5fd9f72211a47","pub":"032a3e6b6d55ede0c25b78a2bb860adea7ec8b3dbaf7340197ad2d0c07e1673a1f","addr":"4f9ba3935c15ff8ce14f0b09ef498e50693c4c90"},{"mnemonic":"solution buffalo armor capital enter cat banana manage caution loan people gauge","master":"1d894a5d9932bc19f91fa92f0d03f25136a77b4eb961ddd742b74c54edad9332","seed":"b833db5ff34a1bddbbee895d96518261025bbc6a9be596d58435468f1547ff378f504062aab7add0c69763708238d0ab42a90f6af0b790caa1569d1cc089b605","priv":"4e26066e7ff8936e63fb011173f70b0206c1b6ecaa519fb252185e18dbc19705","pub":"03fd00f281ba6065cdc8f6a8cf17cdb22b2ccad62eeb535708381004b2a260837f","addr":"e6247dacab881ff882e412630350eaa6de14817a"},{"mnemonic":"power answer mixture choose course crop decline border carpet absorb long artwork","master":"1d74c0120756009f821899f220d3a9e77291e0549241481b657ddb84af1b66f8","seed":"cd9ac735fee9bbcf45bd79b31196138b3ca002513bd1fb973eae4bffd0c5732611cd67006af3f79dd127ce21532947a0c1355cc774faee82f58cdbef6f8bd7fa","priv":"45f7df4a90d4ed0f58c47ab4839220f50689cb2a5663acd9cbb359d6a23e465e","pub":"02697233abb54eeef1f03a371b0da9a97e85ffe404707b5b7ee3f0e3d2e2f0768f","addr":"0f5addad3faaad7ebaf37c3d3f2576a0a1a5e533"},{"mnemonic":"patrol room turtle cinnamon remain tank butter hazard expose winner rough pull","master":"91eb616d5be757e91052fe74042515b828e2bb14f5666370d7ec37c45018abbd","seed":"7e3b9d910c4b16b06e813b2b003d9c0e8c76ec520702be210d9ec2ef2406e7f473f09f41fda56b6a657c2f1000130e11a88362209c6b4b47362e786b7880916c","priv":"ffc2a31bf0371a095cadbad2e0b5adc5669ceb6faad08da818c3c64e4af53b44","pub":"03b50efecc97cc7d7f101fdcae02662d49d118a63f03180889d8321019f245f6aa","addr":"0c43cd72c09dee746c3af1691b495a8c02286612"},{"mnemonic":"bulb neglect chalk congress cattle found balcony easy tube sick journey quick","master":"a7c632878e900903d4e0e6bc57291f1e64981d703e27b82c2da00dec800d5570","seed":"aaa765dce33f6b289d37fff2e409a540a29f3830a7baa0526eba3317d559ef59e8936e8285b6ea8a62753ec72616163e24963e49d795f38df210836ffc7d8807","priv":"f8b281b658e9a584087e16eab0179747db5c38193cada4fc85364a8f743bfec9","pub":"0384df6f5de3f50793f62eee838d30334501d6339998a25889688ba305998d15cf","addr":"cfe9adc1e454387351d4ef2dfd086101a0012863"},{"mnemonic":"arm asthma voyage mansion hurdle alley ensure team coffee palm spice general","master":"48e37cc4961ff1234938ca5ad6ed22f668b29017067c283ebf2d9642cfc2e57b","seed":"6bec879e82e5d243a6bbd5a0a5dcd21a6403d450f0f498975d5205da7154f62350cf0afa034f921cfedd4dd4dde0b6e3e9cc118b16b6682686211040b3b80b6c","priv":"b0b487d336dbb594947dab6717a5f140056d998f9e8428307491d12b3f9e3883","pub":"039db2ffbad67e7e824bfd0cd9fd8798647390b8c9a583807995a9b49e252279c3","addr":"1353002776f22c179aa208bbdddeab3c369c51be"},{"mnemonic":"spread curtain furnace trim funny usual age floor crunch blue urge pistol","master":"3c44072b545e2e955892ee4e6e5949b748d17d47d3ebeda85fb50a341bda7668","seed":"05376e4a1725d48191bebb1e03bdf76880d82b033f597182becbdcf78f167b260bb5cd6b79681f7ecd7ec75c241f90cb40b2d57d108bcc1b7766a63002af1960","priv":"58285cb1f39d00c6aa84a32a69e0e108ca80e33e75b7b4890e182a7e19485a36","pub":"02e4194b7eab20702d498ee7eb7cc98c3ac8d8b2fc63aa66bc81aad93bb1aa3b71","addr":"9b8ded654ae3336405f0bdf768d4293c462ed51d"},{"mnemonic":"century outdoor world grunt member stuff holiday intact property race mutual vehicle","master":"9b9fcc1fedcf63ae9fd216f9a7253f85cdec90f9b1fdca0c36b03169a5860ff6","seed":"e39f8455cceaf542d4062d998b8de4d7e153e594224ef7d7069abc38acf479fd2485f0821fd9af2116c58180f0069af32d10f0b7222eaef6622de83741824999","priv":"e7b4c942473ebc56868904e588bea3342f761528ca90f2add423e17615ef80cd","pub":"02059867db3a2ab4307a5ff502e9f89c45837927eb2f2b75fe55f0dcf25df9e1ee","addr":"714b9aa6afc10a40d702076990a451dc3ee4fa4b"},{"mnemonic":"world trade divert sad unable plug stereo autumn father ankle biology clown","master":"dae1a9e15469905d0d20172bbaa768be4ea4900594080499a56a69d1ae6d0557","seed":"50169fc286de6432685d85b4352908b079ab4fd11f1d8c6a82093093a9161650c2e10d8407f65f8cd1cf4d9d557590f21f5c717a761e7918ef8ca9b73f410120","priv":"4cd8309f36881d1afbfba66b9fcfa09f948d544db0baa3d81d3bd4d2067950b7","pub":"02a86d26c5b309f49017d4778b13be315cdd1d7c3baceeb61fb91c78bfafda4447","addr":"36e8463e55df56e01fd08b8fafa3ec1704ca5480"},{"mnemonic":"observe minute art scheme pear lava search dove cube entry orbit worth","master":"b7ad8e5b587bf747fae6c42423fc4cafecde0db7c9443d48afe10115d95f9b93","seed":"f3ac2022097390a9a0ae0e47d7746e6bce017d15d97ab74b1f99f70ed1c1e9b3534bdafb69e2aba1a7fa2ad787e9ac6b408f2259259ed4f744054504b05c2001","priv":"63797b9d76fe914825f90664c4a109501be006ce9049d561b9f6798d5e518c33","pub":"028b851a2e41625548564242b16e4bfe07cbf685e2df45dfdaefb4aee9fcd607c9","addr":"16d7f83a219857fe095aff5c31e30333e06b329c"},{"mnemonic":"sphere diamond electric milk furnace uniform tomorrow fatigue mercy isolate judge arena","master":"f88c8bbcf7deb1636c5d96003a2bab945a518278d9d58782cc9e7c9fba4facbf","seed":"5660e5ac88a5c43cf14cdae6929c3894ea5aa3bccf3307f85f1162880562ca352153fc1955b21e8533ce844e79583ab95df0c4199b9bac4520ca1c2821ab4f18","priv":"700fd3176db1c0988d7c35d5ef2cd109c7f52b583ae665011f5d476e5a7b3ff5","pub":"022efb00f6c83d296a12f787239fb7905b7f0c27e4fbb62ae62fe43a91cffa9bf7","addr":"7e4a94be643599be266227f349d4797fb7befb89"},{"mnemonic":"syrup unfair confirm hunt flee armor limb travel hint ski mother credit","master":"01aa87dd513611771cfeee1a39986b13fff29760f0d4c7cfde678e70fd053909","seed":"0e54e0db6ff149c9c572a14c3902fdddd567c8ec361ba3bcccb3a407e3e5c6767ec71eaae2c75aa1fcebaaa95e14920e803d824ae4ce64b13413734dd4526836","priv":"72258e31f535c698fc029b953da4c0a89448e5633cccf27e3e6680bb895dfb99","pub":"02b9e8b06d6ef0ae29f911d48c7facd2528a45f432efb4f2c1f1eeb6056380de2b","addr":"90500208588f51b84399e4ba62ffb653d513cd43"},{"mnemonic":"embrace travel lake capital dream shaft focus kind card hood enjoy memory","master":"04e38c8074b77f3ae174593b3c69cf2f55bcbdc02bde68079691e2d8f4e26e6b","seed":"f9d883ef73a830ccfea41726a150e50c9c51b9acda9e4d022c0b8852a57f6df5d8f26542ef1bfaf83eddbe276b8f16cb7ef151fc512dbe005e473a64a5b84250","priv":"3c1b914b34fb0e5866ef082def1cc4fa589ac0d7be5813621d22fffe68b0d4eb","pub":"0381cc19aa68c4ce5bb656a1ac6d1f93375ae096826f99b46548b69c4a9d07e30e","addr":"2b82395c3c65dfe0c8a82928bb3a53e745e29d26"},{"mnemonic":"rabbit choose combine yellow permit raw puppy interest spring work wall humble","master":"04d834acb4020196f894564e1fe631420ce9e801b27bfdcf221c3068aecf3eef","seed":"1089688a78e4c6e35761aee10a12600d9f48eca57d239eb4573b4ccf28925cf72561c2921b31bdc5b00a222c537ef8c37773cedc7742f61633f1adcf94dee039","priv":"132eb740a216f2e92c7c5f96605ae61824ebcc4fbecddfd17689a1452fa174c0","pub":"03ad014b5a58c19ea616716e555dc7f30c67b5fe06bf77cd91e179f8218ddf89fa","addr":"8e05459a88d149b8473c0411a175c0b070423e05"},{"mnemonic":"bracket what unlock tooth melody wire chapter verb grow direct spin rescue","master":"f64c4e7a30ad534ca260cd280f1e8a6055e63f546d57e61071d5c7937273b4e6","seed":"56ad6c16f5bcdad95f566e8628fcceec9f00cedde68816077e0b6db1c106fc3203052ad334a0fa4b232157ba09983087d853240495fd010ee416a38cd3158108","priv":"37f99cd9868a0e44bf26a0a3180cb13f7e4fc0e379cb035b30bff23dac6518fa","pub":"0218c1d6b479b4a8ed804f62c84397d0ba8405a1a266c5318130f0c8473a60412b","addr":"224d710168a45dea667015231a3b8f910ba91191"},{"mnemonic":"position nation recipe recipe friend defense friend engine that leave match finish","master":"15aef2c47f684437bf88e44e9e518a5c517f16e163efa24f1ed8414d5e975933","seed":"15df2473af5b7147abb3b7d17da3d9668901d37ccc86ff652c9ebc75b596e8f3939e77ba39194276a659bd86947a50fef8ba147058db007232a4648e8c642ca9","priv":"59eaffd27a11231bdb4b39137e6667fe2c3ed81e6ead13818e4cd966729d558e","pub":"03865fbd6db962067b2547f69afd7effe57fb3dd3342bf5255ea6d5456dfea0842","addr":"0a0c1411a031ffc35f95c214e9a580ba4eae6c02"},{"mnemonic":"sight broken hockey empower hair never bean beyond glue small coil barely","master":"b6847c7371864fa8e19e57718425d640a027593b535d779b815e003098294910","seed":"3ad83d292efb99c2fcec6c12433c5fab6d250ae5895e0da6f1db3103bc12d82527be2853711532331280d3defa5f8bfe58fd325d11621c9a10b5c7712b02821b","priv":"9c3f71613d8ca92267a45b562e39e7e12305473be0a6498b3d2b9fa4c65b743d","pub":"02f9461c5bbb2e8ab8281f1384b5f0d412abb970b82e43ef0f1c44b9476319d87b","addr":"501b211909a1647afffe57f1ab7754d4c48940b4"},{"mnemonic":"pause usual cigar festival vanish direct amateur bone orchard cloud fall fat","master":"acdcc1f311b27f850eade92937a5d7a3a9ea1513e2ab5d08fbacba42ea267c30","seed":"cf00b72b84afc0e4b0e2480c6ae55ec1c5ef8eaa0bfa531432b3e9578fdd4ed5199cd24ab22e1cade76f0b763d901becebe686770f3409a8aafd2ee89f111b00","priv":"f0412e04a062aa3cb70cd68fcd327446121c76c33bc440ff93f63e05cd1aeea8","pub":"033708eb3564ba835b779fbce8ad6d64501333c05d0fd798c92f926256464149a4","addr":"92a06b244988b778f0986502d8ffe1804f78d10f"},{"mnemonic":"caution unusual response boost dose jaguar nice exhaust chunk tobacco cable toward","master":"7c584d3382f394a4d07684df15e04c482ba0dd3c8223a97c92c091bc95d2021f","seed":"17e49b743fda3aafe81ad205605dc7012a2096cef2475b7b12e79e54b625de459de8661ebdfacef620c851a11a0237c781ad2a84e7e30abe42f63d8da460267c","priv":"9666bc12bd5dbf4eb4bc1a8acfa021ba8f862e5551d16dd97e8e49381259196a","pub":"0314e1d0b675c88061db3d87de6bf4728ce8ec170bafc754f4fd846341ddad619e","addr":"9b695fc1b1429ec5f697df05a1f4c850489830c6"},{"mnemonic":"dream walk typical enroll knife gallery kingdom dynamic extend course shove power","master":"a0bef19259cafacafdb4854e37f36b332066b5c571538e970a7057ca0d97db1a","seed":"7d2bc8f37a8215149b75577f9efd29e0ada9f5db469e9125883804162dc7b100373f020667c06bebbcc593452dada790237ba11ef638573210d2fe67c7e7f205","priv":"370caa36a7e3a5aead2d4abb58d57b90299b4a65484613e5f39b0b7d1733e1ca","pub":"03bfddfb81e4058e08f3ee57b06065194c252e2a31b074acbb15cc7c5f6487368e","addr":"6299fc81f05eb71fa12dc69b2ca4ddfb6514af29"},{"mnemonic":"apology benefit donkey van target neutral success hen easy capable smart stuff","master":"dd96dfa3d46e0bf70df538f0da3b94cdbd7c20e170c8875032285ed7f6654ba2","seed":"c3e6214d2db9684e4c7022311861a013853761ae9900ea823fc4bc6d70bcb8de98f100664f0a04d32e18cceeba41539f9237e89400cf94e0017fc66622a902a8","priv":"3add5757d65ed58816a2b90411d2019d206b56692205724d6e412a26da88abe9","pub":"033607f86548d8e432cc23c8c995749dbb0bc0731121b90b952465fadec31df521","addr":"e2073969ad58513da3df1225e5266e03c0917e46"},{"mnemonic":"sing eagle hello october action alien equip tongue riot pave oyster fit","master":"03f58c7803af441682b522de573e37b218fdaeef55d9637c1ff8c58e01e57564","seed":"7b9cca7d24f97bf461619b101ecd343455f9b00146fec997ddf3e1c569c615e010cdac3b6643a6e9f4ec45be954bfde0b0320e86b0e869c121ca0adca7d11b5a","priv":"21f52146c31e0a6ab9016b717f0435b36847d5b72d83183b3719890171599068","pub":"02f391dc750aa937a7b89dffc9543f72e73d6939fda1c0d74dcf99f27140656307","addr":"7719d5badc862468acdaae65afef4e1e2ba5fd08"},{"mnemonic":"proof symptom trap diary biology tail cement interest fruit tobacco soccer prosper","master":"a0e4189e097622681654ff2b346e79bbffb8e4e7be139567fba8b2c6aa427096","seed":"557153d485c01cf29622ee3a2e1fdad38c815a7cfe72eb18c85605a96c30e38b16ab37d9a2be07cbee7a211e911bdaf460d47a07d83f385fdae9217eb70487e0","priv":"57a2ee34ff6e6cc2dcc3fe3b907cb44fcce0251013877d46b04e24c9aa20ab73","pub":"026172d3d801fb6e855e2eb0f1171de15e6823bb13002b4e9b01a41cd430da7f69","addr":"a1a953df8d8ff38614bbed7ea9f704ef98a37435"},{"mnemonic":"wire gorilla pupil since trust open amateur evil chicken razor minute science","master":"bb549a48f5610f28b23bff00b8b0de2c93bf4e093400989632c98feb3f45967e","seed":"b05c272f522ec2c53dc26679e207f2c16b6506de02e8fb231175265445218fd8617222a374beadfe1999ed617d5a1f89e0a93c85bc022eff6468c4646f3ea381","priv":"2e96c265f6cafb5912bb2748ff4e0d4b9e960d0b4fbc92967a73591c6d7f54c6","pub":"030d6aa64cba047b2ee2c5af2d3893e17004e66762696e6375b09e32e3675daa21","addr":"e065248114f65902b5cc3aefcc1bbbec4d7ed597"},{"mnemonic":"deer meat share below retire when crash original boy wide leaf blade","master":"47f23c913c2e53d34f7c5d869fccfc07a9a5a7a2e2e811abf9781c69aebb4ec4","seed":"7f1a2f19bab3b121415adf5ffc709749b009fdb90df35b6f3b7d17d8eeeae0d41e0f37565c5320b90edb50076d712aaa5e606a88a44460cea67cb686f1886984","priv":"dcb974cc926c246144d1e6c1c5b3babeb4de3be7dd24ad40d6fbbbc592f384ee","pub":"038d6fa489c22c5a8d95d6931144de5d61748be81076b8cc2f6a0c928065f098c7","addr":"4c8a5b45086b2514f8094d3579b2d420b36f7af4"},{"mnemonic":"accident symbol token cotton enough false cereal verify item army pulse sell","master":"70b049648afff7bafb6ac1d8f5a2e2d78bea9fa93c2924f0cba70d4aee27dde6","seed":"d58819c9862ce8078a2b4db0a25434f03631bac4143590f1a245eed73d41f68f0ab089753064eb879b2edf1a56ccb83d0fa88721cbe2ce05f2c46c040dbfe14c","priv":"ffccb427730c5e0b70f535e6ed079888f64b56b8ff51a7f5be1f1312ab63567a","pub":"03e4300d0181f901e200b71f607729f6db5b422c1dccc6facd28f7c694975d2bcd","addr":"66cff13f2cef89b9313377ef24b4a1fbe2851a64"},{"mnemonic":"modify monster ridge bullet lazy sweet output acid shove hire warrior broken","master":"014daa371dd0446424b0b8cbeacbf8209c5136f184cb97346e82ed155b535b58","seed":"a5c1919d9fab0049de70600a275930979ad0da3a3da6333feccbb1aa41ce461ff1bfc5fe0fa6db126fcd96887dfdc2f531a522fbb90741aea5cf2c7dbde8d585","priv":"b66d283958f01a72683b8c7637dbe3910575fa853c7cdfc395904dc73723fff3","pub":"0298afdd5257542bc7918449a8e22a85c5c6bee8311ebf6c712da73232252ac3bf","addr":"22a6f55327b02536e91a046e9a8347c38be6f111"},{"mnemonic":"economy relief sort silly pizza trick urge harbor coffee flash fantasy sorry","master":"f1ad3c0e0551b62d80ac54f85aa89c9f241f0601397b1b4e12206a67479443c5","seed":"d3abce93f99595d45d0e9eb84aa18cf836f0d7eef60345b8eb2a9d4c87a8eccb7a0304907adca904503d8211dd31ba96e076a4b2eaa91ae575d4d1f7c815e670","priv":"4aab4cc83a2acee81a99bf7fe4fea79cebf133b1a7f0fa3f583912efd60a8525","pub":"03b241333aa683b8319975cd9ab2b046cb7731459e79a0ee9facfafa85bf0a31ea","addr":"9ff29de09deaa15e5050b5156754f9168ddd6df8"},{"mnemonic":"wage thumb correct coffee salute rice trade middle monkey height hint plunge","master":"22c4ec2703eaaf2de49e585a5ac5b7e17340a07523aa46e35503176a3a53fe28","seed":"b93e4f76a12d3cf66af70b58b30a66d5d648918be7d5db33fc3d573d6ca546f39490d3101dd686185e61f4334f4880f1e52d94919b358806812057aeda57bef9","priv":"d5e46c667c3e8c08bec8c7f7dfb1dcff3a628cb39f1eb6b8e117ccfa96551354","pub":"03219d1b8b9d5562e550d0fdd5cb6227988622d664bdc48fcad2c07dc78b82f1a7","addr":"d8f9a7f71ad4a92a07ea0c53a54395895fac7134"},{"mnemonic":"miracle penalty base jeans inhale state roof size tent chair life afraid","master":"82e0e8ce42e1a391f362bd19a0959529139153e6102eb5c947a64ba6b8699c36","seed":"d43f307257db97baf0e458c06b0f509e5534aea2bf8e2972eeef0a5408b9fd52a13df5b73adeccad68ef61017d63243dedcd167185e10402e7a7c03c88087527","priv":"8a82fb302c3b5cf10e119ff3ab01a036e002e9e2d49f0db0a40d5b6828291bc4","pub":"0233cb5096a11a4c79e54cea37e42139a1198a1385cf4e0d37c704352aa3551a13","addr":"e019149a5036bbaadf18788e3be72fa5292a2bed"},{"mnemonic":"stumble army virtual virtual plunge until pudding universe suspect palace bacon dream","master":"32da9154b165c960e927f0b01be8435f2b6ace7dcecda4416a449a50aaa56774","seed":"72bd5c92a8ab4478fa1dad0761118bd3d9a1ce6322c00f81b527701a74e0c4aeea63238017e64d4acaa92bc61af2c41a734d90567799ddfd15deecefba60988b","priv":"63c7d3a6da6149655588c4fab367f187f940101e99618de1d01963aac0dc639b","pub":"03df276b793ee770816ffd90ce2c45b6f24558bb90cedeb19f17264beb53344b29","addr":"03c20b0d41439a374a8a84ed7f139382b6b012f7"},{"mnemonic":"label script force inside outer pulse style nut meadow design receive panel","master":"bb084bcc5df57ad10abb3342888508e399cf723415d35f5440d0eaf808a56d1e","seed":"07029905fd6a538b5ba773384b0084bd11b5ede855a98189b8ca1b3b0457add4b365f98bdc75874ccaf85882c5f1aa59f0f9b77b5a823178cacbb4ff72d0969c","priv":"91eaffd2ddcb6d055c1ab3c7c87e313ba520c263312a6f3d267d41018d7cdec0","pub":"035bbb055ca818cf974da73d5d87d7cc447ff5b9dcbdd39552fb28c925c2077636","addr":"baa25da619099b41aebbbf1282dc6af9dc268664"},{"mnemonic":"nest decorate update alcohol system panel cool grape mind ivory ski dance","master":"64666caf25c290b5f46e27737e61124c34cd428b0d1a09e88ec47cd059765729","seed":"8db4806ada7b82f0811b24aca3b0e11d087cfc27e3e83b77e29c7d5695a126f577304e443f71b3de9239ca743acd05563c1f08f071eca5de4a9961fec463c372","priv":"eadb5c2704fe1eec4f121714b3a6d655d9eb985fae7d535c6543df13214bbfaa","pub":"022bcbc7676ad7693e97a587886293b6190edea96a339e225adaf3f3d6c493851f","addr":"5310b04cdfc366f6268deaaec22d7c628dc4b1f2"},{"mnemonic":"section supreme grit scan arrow flower rebel trend film sting govern museum","master":"29616b872561d14ef56f4761a29da1c5dc768092cf7eeb4ac28aad39e35ab274","seed":"4b8d6961db3f7b123dd71ba5fdc1b7809a19d84dcf25bd1b443b610cdbe44e5d5391aaaa4374ae9d6ca988b5898dadaf5fb79fcc09859851538842cec7acd36e","priv":"da2a60ed2f49ed3b6c1ff78698e3eedb2d9cbe9a707dd91e047f8a17db4f8e92","pub":"0304262df894cfd35a5330eed4008630b6527971f58075282290a070906c0d69a8","addr":"656996e8dc55902fc01bd95e93edb12e1e7dc440"},{"mnemonic":"vacant peanut senior skill helmet absorb turtle regular inmate hidden captain street","master":"7c329d40208ae70f5ecfe8b3a5930adfd09a2f618098e549c972036bea9fa4e1","seed":"b7fb706e9e43c671d401c374984ba22ab5465e15d8572eef3c3302a3fdc77ec8b5cbe7b2a8e42fca582a74fbefe6b755e442e6389592a0845aadf56975a4b212","priv":"29ea2c32ecc076c6e25dd9cc06b9736d730a8306a007df2410143153ec0d7402","pub":"020ee0b300f1714f378676bb533ed50b8336bd288180f4b55a338bb1ada82e0054","addr":"dfba016ba98cae2160c861d8e5117b5afb76a50b"},{"mnemonic":"setup asset fan host pride decide museum fashion disorder coconut school cause","master":"53bdc111a1d4208f6d04234dcdb764ca24c2f42d7dd1de46cb69dd00594f9c67","seed":"0039f1f4e2000001b1af4c47f72dc1f8347a6b7c0559a9625881eb6f7492c2e1fd186b778fe30540ec9dae03de4b8e4ad414ff5692490a547e1127ab03dfadc8","priv":"899611b8bfbc35a6bbf5cb80c193463849fa665aaad680d576f910bec97dc8f4","pub":"031a099725389ba4d2fbe5509cdeb5893a14a7d743a6f87be7af37701e99be18d1","addr":"5d12852d8132e60b6ed5707c4a589107c7c40c72"},{"mnemonic":"debris bus thought unhappy coconut sing sign piano exact favorite zoo title","master":"c2d02edb9583033a0db1b44443769d5c7b9d545aca03ce9d1db0c90c97e648b7","seed":"411ae07dd870bb2c367b72b5d131853088b501476fe0e09896004271dec37068722bd8952aede6c4ea32371361842f9507c5854f7e95b6e1685d8315c4a635fb","priv":"91047f9554ccc47f0c641022c8779e064ccbdf969827d374dc3419fd462c9ca6","pub":"02a6a4280980aa2a570d54d10c295a94acc7d22040a2299c79b9e72808274dd0e1","addr":"f1c8da3f0438f82da710f6e2604b5adc033cc0d0"},{"mnemonic":"stove romance diet season ramp mango swear behave rotate steak alter parent","master":"039f8ff7fd7e498c643ebecc5cd54018fbe4aceb34a92877746471c3d9446517","seed":"2df95585063422c193cafab822373fbcebb38780acb2349ba1e3d5b98f3a5c63f1631fad81649fd22a5acb3673c3c1cc4c93c6fac5e28bf9ce2c2d25a8215543","priv":"251fc43c061854edae6e1bfd0748770965d44ba5c0ba1cd9784aaa07a17ebed1","pub":"035b5a07e862224a2324a8bf3af20fd4dba7157baefaae03124b51274c4b50b48f","addr":"14f3a5e955fe78fdd87fa3b0eb3ef3195b7bad3b"},{"mnemonic":"cruel equip glow protect trade clever charge gadget valid inspire canal unable","master":"e47ebf7c8d4b5f5b80555c25c8fc89bdcfe7eec0d39b2c18adabfc81c90b676d","seed":"5eb48012a0412a9911b697a3b838605813f73a885a967be55432e73870d703f8db4649a59483b1ba26b739fc39af73e4f3f12d78648e78215c98c08428e5cf15","priv":"fa28e24225703620c1dafbcc09015b04b3839f8dbf170e454a8f6216c01f7800","pub":"027b56b3e5859e3df96d60366bd54a5024ec84efbba102ab1b4c85383f34b61d48","addr":"23890ab09f410c91db179e68ea1d942d25bc0c34"},{"mnemonic":"nest wool midnight tragic exit enemy knock oil tenant survey opera sense","master":"7074c03dfebcb8ed77af28e9b01b77d803c6f2ac88b61a17ae902797c82cbab7","seed":"c4740919291e1af1c7986906a374b081f0386c40601e4f832cdd3f5c4a453a0dfafa1aaa02b00d98f49803a16baa8cb64bcb186c4cf045eb803d8ffab66fd54b","priv":"1f0dbcbe498866989dc0e0b55e6f4b83b93ed2191df2db3ccaddb3f789e434f9","pub":"0396454c50b1a4ce149ed251ebfc6ab07f0d4c42ae84a80c90ca1b64112bb3ca57","addr":"8198e949ce71c8a950f39a8a691f2ec180106997"},{"mnemonic":"brush sustain penalty chalk palace slab learn decide agent private pigeon then","master":"3acf99c19afbfe290a99911c085a656eec61af6f976623c9b6d2d1500e7033dd","seed":"38ed979eea68a00495e0e4c045cfdd1cbe5aabefe628538c35a6debec1be144d41745cecb2003dd870dd87c4246b64e6fa4662173078ad7a4fe471bbc14ab9e9","priv":"1424627b12902bbb162cef56ce5609ac356e68e3ada9005bd92541d0d8766559","pub":"036155ad03bacc613c9fbfb87294091a9bdb7845e58231f4d585603153871a8c3a","addr":"1792e857fca4355189ade1f45066dad9c986e7d6"},{"mnemonic":"autumn sudden learn laundry erode claim exchange jelly jaguar vault deal humble","master":"1a616c74e30a912dad799fe8d65d6ffa77245f89e81a367310fc02d08be13522","seed":"976e55f1fbcebbd1e448edbe90d68d407d80bd5ae197082bcd7ae8e7a640f3246e0057c65271e9e403297b3725a895f15c502284ab342ce1416f40c892bd73aa","priv":"701e7206d44ca9269e1bca00dca53d7287d55fc39214ed4c7e8f7201a68d6792","pub":"031a31e47cc6d75f0652de6698757b8fb2ed1ac181697158f0bd50ec6e7abdcf65","addr":"a73ac9e548e47d6f1f3ec200593a6693297a9143"},{"mnemonic":"priority dinner offer glimpse sudden light work absurd unknown process gas tooth","master":"d969ece198e95be043e46dd8ecb45cd2e5bcc09d8e6b00bfd7aeb59eabcb0ce2","seed":"aa9cc6daf79e31c5e3ed594dd896b1ca39161add5e5a7dba0159f4a8fe262c51d742e66a19f28cf01f32a90fafe5195b0b359e87f5a5a60e31d883ebca08d433","priv":"81d13a5954925641ace6c24f38c68954d782b094002a689500f015a401d5c6cd","pub":"029b1e4dfd01689451ea069e8a193de0b506d87faae6eabd9edf5dc49633c0a03e","addr":"bb2704f3f0270cab3a5fc918b58561bc1505f718"},{"mnemonic":"glide sadness text grunt burst balance ask hair include refuse mom advice","master":"5a105765bef30fb458b9cdc3d6758479f003f96bdfc1d0c21ea1e4987f768ccf","seed":"0131a60482c920093bf7b7375a70bea607a2015bd0bc9deb04e99d214a0c3a4966b21c3bac01544f816a8f4c3583920758e70f8991506cea52c9450c1972a9b7","priv":"41505f80b9b0941d93341815a72fb32dea916912e3dc1b7b7c763fdfb5c541f8","pub":"039df863578cf71fd48dccaed45c21d1cf176c924bd5ed8ec5fd8dc1bd6fcd1a46","addr":"396984e26d5b3a4cc3cf4a5a868ac88776541564"},{"mnemonic":"jealous subject gap april eagle goose double door dynamic robust impose ordinary","master":"ceef22480f535024fa3fc2a7cea96559f4fe8133e45301807d3213ff7e49e0d4","seed":"52d4a03cd2da0a541450a4530565a5901953d1f3ea0ee9440748c1796a5b8ec8ff674a8cf3ee2fda215a720f0fed119ccaa97619f6fe76b736b6ff804c2dc299","priv":"308bee98e778b1037cfd69c0691b6cce81b1935c776a8473a1b3a49bef313305","pub":"02ff9d7bab97fa367a753ded100c11ca4bee7173c04ddb242fd928502a58149587","addr":"7bc8cb221d4de586491bee3016d9129a42fe0527"},{"mnemonic":"panther camp coconut patch blanket census able melody bid sketch protect illness","master":"aa867cfcb578d828df3a6cc4ed1496f3af72f94635ea82574bedf2d88f9fb0ae","seed":"1bf0752a4872e6a4bdbf9f15dcda591184c8e1c61910d958642b376086cb9db6902d7ec0997afa3a0872ae3fa4fa7751605a4b3a3ccb3e4fb5a6afe26e2aafad","priv":"ce6de5f65b6a0cc1e9c4f7751230aec5f2b5401686e7e42b81f1d8eb55f77303","pub":"03f6c0da8154df0baeb15a7bccdd79252c38901ce2dc59e6e08d2d292bf6668a71","addr":"38a888c98b1f68797a879b64e5907b909f81c386"},{"mnemonic":"great history exit include clean have vague stick victory else iron trim","master":"6fce540ed685440130d194a3e8af78417f9b73df783721ccf184807b3973e384","seed":"2459cdc80eda19acec0c704f020082b617952f652b109c268035607139ba2710dcb8dfaf546257f09f5a1b19dce62e83f603f561d2cc2fefacdac6fc902d311d","priv":"26d08c2b95d15b5e1313aa62cc275b10544f0aad3c2ca677426551d5a039a551","pub":"02d165d97ddc4cb451d52895521d7c0cc217d1a004b9a760aa3eee40edcba4ca37","addr":"7bccaf7fc14e648667e8d7001f7b0777bef7813a"},{"mnemonic":"pause you skirt bundle opinion soap wall doctor head method tent lava","master":"b97cd03b20895737ec084f536ba06f459831e6bf2eab51fc4097ca943014f29f","seed":"b661487c12002df5c65a204ef12698be70837ec522fa1bf17d789d0d0cd0be443a819e4c6a494ad8d66a8ebe25ddd833d6ef7d9dd80e3e5e276ab94e0d572e5e","priv":"6860cbc7b6017128bff9c6d48abb20200aea06a7e8c9168d46f51260dd7125a9","pub":"03d7666fd2ac98121523262fa6695c719d3ea6fbf8abac8266b7c8550a498a55fc","addr":"6a2c9c329b85c35721b69d2885cb8ffa3006ef1c"},{"mnemonic":"senior liquid release beauty echo castle honey limb junk carry clarify high","master":"b3dd9a9379270f2bee11afa64bd9e49e4d9f44fd997c383d651fce6b54e8a82f","seed":"4caef4408f37ba86781693fb979534b9c9534972c7b866f74318930f180a2a36875960ceab41e8725ee4e25f56d160455f7d372a7d08282ddb5d7c1d24f14daf","priv":"6d9ad9c1011761fedce7f7947b5325622ffb1cd6283eeb22cf5cfa3cbf214e69","pub":"03f173aac293bdfd7a98b5055feef56e70d07d3e0549bf278bcc7fef559c0a413a","addr":"93ef2c58e7de60d861c0dc994add27a914477d20"},{"mnemonic":"scrub pupil rural fat taxi area example spring doctor ripple obscure asthma","master":"bf805260160dc14eb96077258ac64d1f67979f7702c99c411fa075a3813ad57d","seed":"ece2913f94e791b8c5c37dff29cd19f9725bbb0a1d84e7c3958eca1b646858de1b3188c8dfade823903a4b4fd12b892bf55e570ed68286741dd02aa4ccb08820","priv":"d158bf7adfec3d4d7f941fd9ffccc1c089075fea66fca2039dc4e2b2a7d1a000","pub":"02d5c76872253c3890a8e1276ec4df0c874fcd46d1f7b84462893776b6d14fe972","addr":"a98c98b13f7cfe6fea7de31de3fbd325648a9357"},{"mnemonic":"first shallow crawl asset vocal special rural bomb random pair shock live","master":"a0f6894a4375e267aae6dc2d23843375250b44bdccbc63d1436a2f172214f928","seed":"7518a5b622fa57389790c2484ad833c95e5cf2caa12f71ffb0fad4c9fe044854ff1f7e97b188545679ea936816217d2a26204a0bde6eb7335328dd0c86814bcb","priv":"027d54b7a844be318ea4442113e4cecd464455e239c0726236e2cbbd4c559fe3","pub":"03f5c6a2e2a82d331268c789527b5ae6d3f36e3fdcb344fdfd7e200d5243b075a3","addr":"bd4e60a76b171fde2684d4c7690e8feb7ad06854"},{"mnemonic":"famous vital monitor opera strike coffee shield throw emotion enlist east smart","master":"f1a0708b891c80724310e95b29183394390ec56c3a6828bb4ec394a39726c256","seed":"61f06f35b43abe9256e635720f4e74c8e3796ed4222c8d914c3ceb0f26e48d9ff772040475acfefda1a907f24c369190b48f50feb2fbebd3a84c0c9d3850ff14","priv":"8c2d6f4673846749f8d2e2f9902f28f66d33625d0ba04a11477335390f908552","pub":"03f8139b274b297d1d669fa505ab797a7caea82e76c5d7a3341c71133fe3dae164","addr":"bc940ec509f5275207ae9b086be155154aefa3ad"},{"mnemonic":"flat cushion trend region glove humor below edit ticket west multiply black","master":"2e72ddd445cd917369177b7060dfc92883b4b56e301dd6b0c7049517c102ac22","seed":"85ca476c295a5b708beeb6af45aad1eb6bb691fab82fae7c6d4dca48723f7819551d04395581ff769554ddb94e0d065f4c710afa7674f0c3480c1c2c4299591b","priv":"a57387ddae40887dbb0f99e8c84c092ac1fb8e245ddf3c9909e189ca2b70d52d","pub":"02d19eb0bd72884a3d753121d0d4489215a369aaab5ad3bbecf47f2246c5ebe928","addr":"84141ec76f71f2bb4dcfc9f81fb5333b9cd1ea8e"},{"mnemonic":"domain produce address tunnel burst emerge divorce health frog rare cook series","master":"983fc11c91dcbfcb3c1869da88972b03f7cc51f54db49533c012238ba89ea234","seed":"9d7cf4d9d3c664b8e51db516449d3dac01d290d774cafa90326e0464290faaa6ed6b780f792e80955ee5e6d7aa8ce0efdec13c20ea0fd88e5e40367f6df818a5","priv":"b96264f6b7f9d01e386ae43893c2a6b8683162394bbfc8048dedd4ce129e52cf","pub":"02ac9b86bcb1d8c6991572ce5044b58560ddfcc25a26dc4c74b12271c263e9f1e0","addr":"345821fe95bca3c777328a7148106d46afad6861"},{"mnemonic":"dutch oyster switch layer rapid fat prefer bamboo stereo staff spin midnight","master":"47d4c05e953b7636bdaa099a136986544444911d1fa720575872370f2aaec934","seed":"f120c319991b7564a6bf0086d918b39aef44877b361883f58db6f95551a66bfffd1f9708140c07135d40d624ab78bae8969883a2239b4cb6de5270aa5eef59d9","priv":"968356e312506427072e2e628a136e6e0104e3b9f74d8a00f384da0d62e58a30","pub":"03efbe8d47bd3c1c6ed07bbb357e6ade29f46d70d204f4af19e5ccba2dbec7c811","addr":"27bbceb99a49bc927eb0d6434b41c873ecdbe782"},{"mnemonic":"green claw tiny bring meadow tone improve advance federal talent drop fruit","master":"f0d9b5313bed52a853a177c338cdfa1080fca511d1a3157e3aafac06a6a753e7","seed":"8acbd6c36b27634ea9017b1ff25913a3b6aee3ba578272ea70d753dd1390ee31e9b0a7685c76aae5bd0e3cefb34fe6d077a7aa0a1da2fe3a2b4d8592907f7c9b","priv":"633d8cb5c8aac8d9e8f3e540ffae0f9a2fe54ec4b9f95c4378927be49f785bb5","pub":"03479063239cddb13d026158bb3519ecb95590d0be4abe036668f3bd134ce8b0b4","addr":"5a6321ea26d9fe346e9af87801f30f823cae4e5f"},{"mnemonic":"model famous make lawn wrist busy food envelope town menu hint dove","master":"034f244b9742152cc762f84ab5fcd03ea6020e30d766d209240f4a1a4bbf4859","seed":"79c41d550c0fa03c15114feb0492e362030a17a72d2e3d05064d459ff8a5ae877c2d94243615ea0f41bb82030e0401ea6a51eebef49c520cdf9bd923f9427e12","priv":"3dc937a202f6c5f20a3d57c657f16269b84f52a4701da93bb1786ea0711335b5","pub":"03e26c7ba82177671230c877902563ed09283148d9f83f400006e11c735620d94b","addr":"b4faab756175074173121e758b65bf2663b792c4"},{"mnemonic":"leisure buddy divert feature soda reward moon doctor fence neutral bomb truly","master":"9e8c30422c780174c05f3a5c333e116be6d54acdcfa666db96e0bc3587fa457a","seed":"728465a73b67017cff82a9e1d5b3cc77276f286e491e9621c21317485b78766fe8828fd0f03016ec67a9e9a42c355804c875874206b60d474c09e49e1eaec89c","priv":"90c91a0f640add78f765fa475ba8267e5e3533b0175d29150138b659397b0a47","pub":"02c0b78775eaf3515a49cf8ee65dd95e8fea30340601229dcdf2d2dcb3d39b3839","addr":"0c300d4bc57ff741c4c634a063c24823a18b1ac9"},{"mnemonic":"excite cargo radar baby paddle century average nature tackle blue rhythm garbage","master":"6a4cd79ab70b5555d3815424bbb8c232351a14511aaa3708dc4449ea80fa7330","seed":"7356daf4bbcbf682469878ee2a8e7a35d659d8f19095059e7b59fe14d9893c054559bc2beba994c527e8417f86c3f57a69b3f42954aa9a4647c91155fcbe2488","priv":"ae2aca6963de88ac0a4e709c4f84f5ebbc2d1a18f55be9c036e97fd46200ef48","pub":"0304f4343dc04ad6ea1c528296ac17c9d47a42cfb744e311f206bb154abab6ff59","addr":"ed8d1537a6fcf980fd7297ba56f1638935ae0fc9"},{"mnemonic":"must trophy era antique goddess local green rhythm gift van target island","master":"52e55a55dbb99a2b170c489c99d50811c47be205294704a2d6e7f234b2a938c6","seed":"9797425288539f83d965bea50c769e5a681c7fd6860502bc7d7d953a36fe16d8f0af0e6441a92b421cca44ff0fdc17d6118801dd17814308af5f6f1436a2e28c","priv":"8eacce7419f6f8b94e426adcae21818ce6525f0ba624bafdae44f0838d36676b","pub":"0244ae10f79e38d499c76996fd6ace738b1fc3dfa60042775f200315cb1e827855","addr":"15b8bec456e7346a6446c9679afb13a7e4e82079"},{"mnemonic":"day include route train grow number traffic across acoustic render save gadget","master":"553843ecb6e4e0383bea60a245b7f34c46d8d505806f4d900c7344b2dd4e1787","seed":"abdb30b82471a0c81df74e7d8f9fc2315b7ed04580689d5ad91f8947cffa9375ef2b6c315b695e642f43d08edcda3712afcd48e86583b00bdf5085d2920ddfcb","priv":"ea826d758734cf1965b67fe0133a2b78aecf582aef9efa46c96c61cb512ba593","pub":"0304501989badca08ee05c3984c8e299e5ecfc91feea52daf24cca7f236684ca81","addr":"9bd24b970d41b73640a86beb27f3533d2bf35c82"},{"mnemonic":"safe favorite ticket bus picture tomato unaware lucky spy creek upgrade duty","master":"8be9a1fc81f80c427683964bc29c2eeb135a3ddda8bad041399e63053cc37fac","seed":"3b7f10be92522ba2544356227f415046ba8b2faae9c3dbef1563aee039d00afe8b476743cce4495c264ed01fc095fdd09e3c2159b9b91ae01f49e5610f3dc375","priv":"114c0269408ee0ad873b847793743f06dee7be10da15d0db533fa682a644a017","pub":"03876eec35fcf39732629c5b3ea22c2309a28549335b9f221001ceb0097ee8565d","addr":"fc82a1a044603663dc758d6987b8b699d56af1fc"},{"mnemonic":"slam jar adult liberty small adjust right sheriff cover below space fiction","master":"75e789f7c7da1a83a34d2a2a9b54d4af6403292156cc775be81ade0edec4d566","seed":"ce1684c7045cbd4ee4c6c23d52ad78dca82e426256dcdb3a5f5fd9c635e0dafff12612e981dbe983e1ec5d88d6bc3294b84f8705cfb553923e397da5044b896a","priv":"bae08dd84c10433159fb11a08f8e3df9fdc503e5cd543a4e9231e96468094a4a","pub":"02269218f35c468c3fead430880577410b580b9dd979d68c94f6531adba7dab809","addr":"5e44c323c10036262a3b02974a6d69f953d0e359"},{"mnemonic":"real acid movie gadget duty hole apple inner essence confirm laptop duty","master":"132081c3acbf9bcedb0a237fbd41c882232976e1bf5467c067892a80f5d30691","seed":"495b41f5b0f22b227458857db55d2787c126b832dfae01384ad0213eb28d79baaadd13a365e63cc7c250504c5f9a2fc5bf38e174769c33ddb629a012219a38e2","priv":"44b3ef5a4c7005846196bd9b7987308ba1bb7923687749509cfb733b3aebc95a","pub":"022803c31147ee31f5fbcfbdb2313c5ef39b80b505cc21275cc01e0527dc6ed6de","addr":"063cf369f1f4122821f7ba400ba1e8248535fd44"},{"mnemonic":"banner indicate tell thing elbow mechanic express stairs robust rival shadow matrix","master":"6e76cc6fe8099d9232c107ffb8959c3c6a24badc35579975ffdc29316ecb2b5e","seed":"f1224c30cb0141c0da3f5cb31632ef8cbd88896e5ce98a5290ab708f5c0c084043fb19a4e360c17e161a3e6122e8fb9d3991c9ed7129dd5ee26bbb2388e9b7f0","priv":"215dad8e633e3ebbacdca2ba68a9747ec69de4d5bf794748500768272445d516","pub":"0259f48c2e291b1d0b29890c10ca516ae8e186d06bec8dd2d966d0b336b9a68a8c","addr":"7863b183b3f98f4ed5ca402c3f1bce45a9d58aee"},{"mnemonic":"boat minute dutch sadness globe congress color sort feature boost regret gallery","master":"6be1882f4d3812eb5cc92b5ec4ae762b565596a01b1c4216f16337663d33f85f","seed":"dbcdc6e305e0330f5fcaf159763664a8decb12dc27003831213b93c241d886ce26175c726b6f899e8de4f2b15aea6af2be816eda613f00a3f8bb3ef3c162027f","priv":"e30847af4ca7d0bf9f76d2c15906c955de0d89ce994abf7696ebbe0880171675","pub":"02a6f99d68bb927000aa3cb6847e349fc7f0412a75869cecbbcbf223707b7fe8c7","addr":"eaa5c8da5482c10d473be2c62206eb82312f3ac6"},{"mnemonic":"icon echo become average ramp undo actress sea water struggle interest trash","master":"d07e7e040dc9b1ce70fa78ff50d10345880fcabac783c380ed43885532d79ab5","seed":"9498c9409da005532ea8fa71aa658c9b160c6630498514e52aec48589ab60207f2770e4cf0f47a04a2d46a878b3b2a2f0f58c478d708ec9dc8f54b51ed1f0506","priv":"33a881e07441283721c695c58caadeb68e5576a526ae465ef48812b98d66bd9a","pub":"03226330049e98e5513799ded19923809dbed40226e958f9c36218e8eeb5cf47dd","addr":"b02c8d95cbc1417b891ba5d5c912a6e3b8cb6748"},{"mnemonic":"scan book mean egg situate dash chair water surge major sugar shield","master":"a50dba88cae4daa6db49e8cdbe710a305429ed2e4ff43c0b87cb0b88956f8f02","seed":"ca8bf187bbde692601b88a74c124c967cdd17810a5b4db55254a22278add4880b8360a66b5d91c0ce1c105f78873994361d2169a3d39bac0807a6ab7cb6b894b","priv":"4ecb295b77c3b1296fc214e554e77fb47df10cbfb22b980ba6e9436a2d884ab5","pub":"02c302c47bb2ead02062861ddb4c876b797607ed2a775317c7ad258c97139767bd","addr":"6f6f55426f790072f9752fd182a68710c2b3e72f"},{"mnemonic":"hint sign broom plate brown beauty figure song stumble setup polar road","master":"e4721371d82355bc7be6836a7915a19917d2efb313eab36abca855fc00f4cc7a","seed":"7f654f0582ce0c83d46e01477fafaecdaa7321d095ba1468ecd9fd6c04c67471a2e32187c02178522d11d9b9160de10c6cfd74eef79d6c50d013044a5e6562ed","priv":"612986c34ddfc5e93d93337f68645bcfaa2bdd37c8a6beeb7d58cab6e54ce3b7","pub":"0309c0b133a0af4f468285b0399a3c3cdaaf8c2b29ef61a4f8ef19d526b23eae6e","addr":"dbd39ec36261d32e313a82b4745c47489de5e955"},{"mnemonic":"eager item digital loop loud drill script ethics crystal tornado pride cattle","master":"1ed90fe65b73b2b50464a59268cc2a7a9bac67f2fb167c5b4714dfcb354a24ba","seed":"2e5bce8308d9ee56a168da570cfbe30f0dfa341df84cbd7674f198b4e419d48c65e1ec2b8600a2e7608bd148291c54ba29e5e7ed0a39d4418eb212ac6d7811bd","priv":"ab27d9960f7821dce58d2271652b42f8ddab5edbc87a23ce3177a0454b775167","pub":"02e1ed58d8c50877a6133c16e793fb6608515accbeb46ba07cbd3972c274534066","addr":"54b513aaef1aba872f8f521bd3b86c885563cde9"},{"mnemonic":"asset toilet hazard chief boy over trap session abandon jump wheat group","master":"43ca7686bc87728e62a5406222efe3ff40d4364a7904f7307437d1b2b13ced43","seed":"e04b7a46a47cf1c4a9382aacf36a32da16724eb1ba82f65a3c66679d793d410d3952fd7bb0c735bf96a089521acf7ec4e1f41b179b09dd75645b7bdeeb539292","priv":"e7295badc4984f21bc64f9ba723a92799ebb18acd8315686b5040feb603f03e4","pub":"02cda17b0a54b09d9389a06259a44004a569a7d862a9397d33f9fb598fe374bccd","addr":"f69a0e9ead6daf22623a1235062510360f0dc7fe"},{"mnemonic":"flat eagle owner ladder enlist chair next good solar drum service escape","master":"2de24f772282ea286aa716777f39a9233b38a5a8018dcd730b74bca33c5bcbdf","seed":"d571b7aca82b969fff273b5d4e876188c5b1124684d3ab8056f69bd521b1d030b617d201313ee42068f48dac836443ed6e8725ae2369a955133cf74682e6090a","priv":"232c2f9a62655637fc64e4173855506ddb4d3530807f4dd441a137981d636c11","pub":"025996bfa0d3593c05503476f4c340ff2bc32290affa52a130f2038b72deba930a","addr":"ea8a8d16976a6d922be30695d49a670027cc065b"},{"mnemonic":"hamster such legal analyst despair robot tumble embody coin taxi liquid cart","master":"f78ba19a1149f8dd5ff019f40fe5efaf8e0c5f9df5ef2a1b32df2b9a0cdaed8e","seed":"9d863569bb0a87d17b02c10eef8aa06edbd9ed37ecff427001f2e43cd4f101def938da306ecac02bc5ee83b886857e43f6248eca72e65e67828f243c625de0bc","priv":"5a2a5c105c9393cbec8cbdd79022c23407c556a503ede10645d744f20ec9ebce","pub":"03a14ba5b2261911010d2b2a7602b37dee944891b1e49d075b6729e62627a252b8","addr":"73ff0ff918c11d261453041ee18b38194d3aa57d"},{"mnemonic":"gun monitor turkey humble private essence limit member bike person cook ahead","master":"c3d138412cb4861effe93888a20e5072f887b2b3d3feac310fc8f40bb523f98b","seed":"6c79ddee8365c1c293e6424cd0c4ad5fa00256e9f8377e5692c3c60c1550cd4e00d3f08aa61441609b3954c271404888677aa4f7e075d7e93ada2f452984133a","priv":"865fdc61a6559f4ef787eb57210c09bcfd82ba9aa87a13a09e62746470eff4b1","pub":"03777c19e60200e1fd48d07f17c58c29bf6440aecefe503421bb13cd347bcd3e6c","addr":"a77712c1f028f11782d2805950c79e11d2229002"},{"mnemonic":"bargain doll comic scan fancy soap fragile benefit private sword share milk","master":"b26f239a994fc404b1aeb31ffd7f0bbcb625c881585dc57247cea88ed890b042","seed":"928a043d2007258b4cea3a478dd6b1cb133ca290142366af0ac60086f880cdec35541f080c8cc1d8d76cae811b5138d9de189557b37dc6726ac1df11ccc9ef92","priv":"ad650db8c2457981a143a3cf400ef1eadb5790368965a5fb8f28e8e0dae1991c","pub":"027ce8003309913c6f99fc6a5eb2020400118e3e253f618a418816e772b5008a75","addr":"67996609609bda5dfb179da0fe5e6c7614ffa922"},{"mnemonic":"father accident gaze obvious visa deal plug narrow shrimp motor pigeon sheriff","master":"643240ce9abd6d36e330c0cf47343823c3a3d4b533f6887aaac16d737c8a1a4a","seed":"9ebd83a564ca724a559e57e896940ac08d28a71613e9b414170539b29a5187a2ee91e3fd4bf258256e26ec5c41af2a57fd8dfd30f054403599cf9b4f45af5839","priv":"adc7eba12216571143e05626980ef0644521269bbe8870545b7cab11838537a8","pub":"023b065c65ef208f46ff43bd1051b494f60b1a395543952e14a3d53a6d1f347e96","addr":"7a7b0429f9706215b02ec49c205ec4710705a68f"},{"mnemonic":"reflect slab donkey village mushroom style brown pen mother pipe raccoon mass","master":"bfc2912b21b64143fa0c5a924573da251a9ca151aafc79a9038b96e21551dee4","seed":"fc21dffbf43c67a07c5333e57d238f07d0e1b987bf4f0ec763f1abce471a2e0fb27e733d5098fbeb81ed9cb2d4093ebc9c565b196c9900f39faf4da5448a2b15","priv":"d34fe09f482ae273ca07b2623d5b13180db5d14693025b57aadd6c7c51e640ce","pub":"0329edd6f8ab6a57ade9179889b4f54306a45f89b0007cf9843755b3aaab725586","addr":"c69fbd3b6e36a75ac8583713c1e3207253ec53de"},{"mnemonic":"lunch process rice hazard word vault surprise useful fiber trouble pride mean","master":"12caee441e7ec1c4109c53e42c8cad66704ca395108237f68953b137072d1aeb","seed":"19033ccf459d27009a9072905bae12152c877115e145eb5469f20ac8d763570d2d0ef57cfa6a482da6a1f2c38e7dd43fb6260a4826b54c0f03f0501df94e4132","priv":"4a2616ff7d529e66e3fb200e7531b4a08911a338e6a80c80182a0b98803eb14f","pub":"03e996278cd3c0374adb59287c00a526fa8a409a53a2606fb230748cedbed12f14","addr":"0f96e89ff4109143a838165bfaa158dd64603fa8"},{"mnemonic":"boring unaware cram sun mistake rule view rubber gravity humble detect zone","master":"23b29bcf96e849e44c0e8848e86596eb41908018dccdb91b9fd81b35cfe24523","seed":"25d1e2d98bbe47da86d732e8975f5c2ecdf2e107b641c6e9a259a49014dc35dcbb83ded97117bde45b0e78379ab0b7785aa8e45e2a628442be1ccc9a98e78a5c","priv":"d2c91726674b440f3aa7f105c17848c1e63d123bdc6ddaf88ecf0e6db40b7d1e","pub":"0367113b62388057da87fe1c781210074e0200b872a7243e05a8c9f39ced994acd","addr":"264fa5eeac6f6b37e249f8ba03168cd17aa7e258"},{"mnemonic":"extra hobby pond foil below injury light brief struggle gun visual recall","master":"80cfd73c33f507495340ad9370aa922b436b84d3f584d7f65cf6173b367331c2","seed":"d965ec811bf471bbdeb7aeb4c0fc43d710cb47fa63806f29661bc1aef4873455c6a97f85e675f6da0e975ffabb1356d310daaad51da951de68927933937e85be","priv":"67654951ada1ef3a6e15b3941d0eebbd1bcecb831bb084dac0d70d610ecac13b","pub":"02a1ad9bcf4e359f15d3a447b61b9f18bf2dfd56c52c20f267ae13b04bd60b0d25","addr":"13fe548ac9d9ecfd28e5c5b5d0b865b89b36e8a3"},{"mnemonic":"copy thank warfare visa else rally shuffle gauge method favorite dirt mushroom","master":"f76da13cf3b11641e547c33aed72ab423b7dbfed236da81ff3759d4ba3ba3aa0","seed":"24e7ebdd3792e56171fc46aa5112514874b67fce474a0ea4399b6cab23ead2dd6bc5201826f9127bae7419504de04342357c90a34884015edf094e52a7080d0b","priv":"0bd271e0b2adf4aa3f1b0ea862eb4efe72958d40ef2153e784ede4ffed2d4b51","pub":"03b42c815258c481e1e994ce430135aca9e8546585e82927066067a7f3eacf0223","addr":"95ee4a4c887ab69a23000fa3bb062d1bdd96371d"},{"mnemonic":"rude wolf aim frozen bargain false remember circle axis arrive virus echo","master":"98d35496c8e4f142a6be9c704611257b0520a14b328203fcc0b6b9419a71e366","seed":"ca47d7e6f88717ebac85734beded4a18c6a46e6775cb64b7ea5aa167559f90bb5d8eb9254599df6e09999d8dddc1e487c657c95eab703f756199ddc3196a5962","priv":"9dbde9c5f35f2fdd7bb33208c733021a8ed055af962137c23e06e252cb999456","pub":"02ed94e8e6ff816a2b053b959b261e7d8f8809f58bae0cfb84459d885da88355f3","addr":"38a0dc2d9bdffd96930010699ba2f39fd244c3d7"},{"mnemonic":"deputy among shuffle online fence mouse clutch joy away bean hybrid void","master":"e13cc05ed1c7f3415610c4011f994446c9c9c65df5e1568af347d42b31e36d30","seed":"f3b73f8483fd0cf17bba1032397207d4b593f54140391a91df47c5b8960fe5918b0160a18a1a2da8f3acc6585fccc19911c613424c91b47afab4eef5f06bb569","priv":"d323538934f97f44d23c78be6a5f6005a882126475ba4a7c953b19bec7678142","pub":"02e6c50799013ab284a676715c3c575be75806a5676281144cafd4c17481ea053c","addr":"788f0092868345453e40b0f38d44f4ff4af0f2a8"},{"mnemonic":"panda rule subway ceiling awake decorate forum cluster place club surge lunch","master":"f0aa8e87884a3e3462bd3a230081a29739fc62fafca9aadd9353986d27de4509","seed":"7ad436a119093e3862065629b195087e0162f2060d6e2a1e653be2e894cc9c3c4ddc2bae40f447ef87c0f3b2232420fd938c155938b4ff5fedb3fc7bd26e9eb6","priv":"9db3eddb02be190b266cd3bc93f5e45d126577bfdfb1df60ea9f2f3bc21cd2ce","pub":"03c4e1511881edd8d598fa65bfb4f9dfd93dc1f2f4944c790c2abc650492ce0a20","addr":"c61ee0480e8379e854a631caec02572b91c2b23a"},{"mnemonic":"addict foster exclude debris moral uphold couple surge reopen blind trash real","master":"9c7714714335b5d3bc2057f206da041c5b0e74213413c2cb9c98f521d2890209","seed":"4905780290404b998ba3ea764cf22ff5ee689aa9d783a7f6ccf57c9d2b4b27e4312941a2e4328232b6e0d2e7729cf30978b094dfa6ea369b34b6da35ee2ef73a","priv":"4e5be9010cf1a4ec010712d82bb0d18d5b1b1cd3095a56cced0ce00f430e81e1","pub":"02a18e4eb8623e1f0fc37434d1e18531ebf5e2dc9bf93af3f831cc72389cb3ed83","addr":"7acf8d7f9f6fe56e21ad77cc6e41b3b49bb542dc"},{"mnemonic":"bracket dragon until token cotton giant enter lyrics apart supreme pupil fashion","master":"dc8282dcc0f6d147d01f8ac326a3017380d56e242fe415fd17c0b6ea92dfca0a","seed":"b1a0043eff67b480d9b3b2c0b6676dc17da38225428cec06ca7884060b830ae243d50b659cba06166b6e8eae8d9c9d67a38554f5feee3315e90859b544833dc6","priv":"7c19323897d7640d225bbcab428731abe01c7b6160557476fc0bf97799f6cbc7","pub":"03f1a65a290bf4a7ad8585680304d187f5aeb3e51d44c9941443450270c457edb7","addr":"72caa875e043f9f2d3712a87317cf12c34980ace"},{"mnemonic":"catch unfair toy shadow hobby tuition remain leaf put blanket fall diagram","master":"611504571157c7451ce639658fb04945cbcfde1b2e487f9cb97ad430ad3c3801","seed":"b1b9002dcfec6d7bf1d7068a45615abb4aa076ad65e34f15d3f4006ec82384c3bb7d737fe7680e58089281ce9305ffc178bd1a23e95087c2fed495a20316ddcc","priv":"3fabb4604bf9163d245a293a4b50a4f844277afb9b260100ecf406fdb24a6d9c","pub":"032568275e2158b5b88f191d77cfc23742157a4c03863da61ccba04a29d6a5fc43","addr":"061151483994a2a2f420b081148754d5807cfe96"},{"mnemonic":"divert spot love tragic vast error crucial print snow filter fantasy forward","master":"817b4fb465a25b5dd9921ff72634202f30b98ac3040cd5006ca5e18fa851f4f6","seed":"824e5275f61c11ca6db812ffadec349e61afa0313d4d299c911eaba5ddd38ccbfa39a42d323f43aa4999bf95b997958a6ed0522930bff6968dc9cca2adaaa204","priv":"43919dba40cfbbdc53b2f8c097b6c66a6a391c28d9478fcfe23f29daa4f80194","pub":"02c32a7eec00f33e70c83aa4281d312bfba257bbe920f349dd3b674decf43e3aab","addr":"fb3e6b782cd14938a296f8986daefcb9c1424232"},{"mnemonic":"marble start nest primary author steel video science wire sister tonight invite","master":"8d62341b89e0c045322c270870d8c438ab41ca077b96681b9288ce2b04160b8f","seed":"ff79b45850f134169e1d12bc2c95c5f48933815e3062296a93644c8e88ec70f2faac59c5e0e20b1fe8799989509190442356a67596657156dd7b1eaaeb976adc","priv":"75adc55e735bce443ba38fa066c269d20c986d18d31b9c67a6f41215dc6205e2","pub":"0262ad481271c2b42b162d09eb549bf2e09ff953d78cc3b58f9633f0a2f0a1cb32","addr":"289c5796cb64589fc90d10c269093d9525249ae4"},{"mnemonic":"mesh rose keen want voyage net brave bargain session creek shoulder glimpse","master":"d3230ab8890910c45a3bf9d9d21b8c24a6a1aca2b87467b42c75cdb9204e1f2f","seed":"d61ef67df124c9b43132bf496bb3b18220a28c7c540247a11e25c2dff3ab8b7d0dabbfcd8125f03496a8fc4f888d6b8f8df9828ca406a3864881029e95578c2b","priv":"92d844eea97086fb63381e19e56e3b494af47e7cad3257a5ef1b46e21c4cc4ed","pub":"03be77c3a96734aed00ac4a0a18151670a213a911f3a9d78cf6f4e1fc33b7d0aca","addr":"e3a1325741de4de93501261a3850b374423ec97f"},{"mnemonic":"host increase panel pact gorilla alter cause cook voice ugly crop that","master":"22daa7841a31b77e2d006277ba1afd48ad7f066b4cc2b778926b4d4b8931271a","seed":"c1b9b9f1d4097d76288576869071b7efedc756fbc81bc62965c462fb0ac49ede2fba8110e4afaee3d9e187933fc28783aecfc9ceeaf87f63e75f4bc1eefc1860","priv":"2aedb3ffca9d76ee5070f107bf5c0dcb583bef571b1f498baa8708495f8f466c","pub":"027c929945ff29b6a5df3d4ad096849a270ae3052aa1dc74b7a14d4288421e47fc","addr":"97944948d7d679a5c9658168f6b1ea9772c49ce5"},{"mnemonic":"shy garage devote private degree cradle special fee plastic lonely legal agree","master":"b2150fb985a296a6548cd57d30f25bdb2a51c7163e96207353ad064ed0eba53d","seed":"474ce9dae1748e7f1c4096dc603c17696ec21f329b508083ead0651fe00dbd404a1703a7a90f0bd2f66553af28224c6abb93563527a6413732ec636f234b472d","priv":"2c079aefe8f9d45940fa7ca547243a229ac8aead5570a310ff0ea50e9579416b","pub":"03368684efade7cbe5d1017c8cb099718ee9b7ef52e7ec384d507117d1716faf3a","addr":"e0a6539483dfd061a878096e5cd0efd475b9318e"},{"mnemonic":"marine local subway mixed width zone palm lake sort radar matrix pumpkin","master":"5b1142363291deddd7fda0bd7775c7f2b1bdab5959d17d87830d96c3d07c15f6","seed":"c49978eee2d39326d8950c89a69ce6cfd4d51dd84973bdadb5dc517bb60185bb4354b3c5fca5dd0d10a9d8793c205304d1569af0b739bb796cc3f604edfd8959","priv":"84f09a48e36698ca0fa65597368284089059688c2cca84c72a22510f37989c85","pub":"0262798b5fba21efde82c22dd36df8261745c8f7046704e239996c634302efe8ff","addr":"6d81cb6953042af66fc1fa7755f48f3c3b529495"},{"mnemonic":"morning vast nut patrol owner body between neither earth always trouble mechanic","master":"abe0226f5383b2e40ac23a3cb7b486521f7b7af6b1108f24941fcdeef71edd81","seed":"14189de5d7d30504ea20b94fcdfa6054f70ff63f4378cb3a6715126216b571075879cd9fa1c1694ee16c656d8f8a2020adeef01f56dc814cf341aca1ee9e8e33","priv":"8da48fadffb800299535e930330f1c2f9dfeb45772c58764451079696ab3275f","pub":"0283e5b3d662399b88cac949cd41d65e33dac46101c6be4ab6718d7b7d4c1c2df8","addr":"bece5507c72c79ddee993158241c20ffeb20596d"},{"mnemonic":"weasel emerge sight shell cook develop entry truth era radar panther prepare","master":"2233dae87c1e1a6a98e1df4a573f6139dcfe49db3f2fc663b44503ee267b0c95","seed":"787e8fd15da3e7723f91521e3fe4b501b070ff5bbfbcd2b4af147a6067d751d5d1d992716519ad71b59a41ce329eb282a94cbd15bdef52567c8279c327651bf2","priv":"ef6ec780a7823965a871595f4f0c2e2e7ab07409f39ed825b1efafea19f39440","pub":"03a545388da649a8800ff9fff4bb33f70d94000e4b1a767ceec92f5c3f7b880783","addr":"57222240ca41ace976ea1ac308bb027ea4c64d36"},{"mnemonic":"switch sea bomb symbol foster flag grain bicycle case crystal august crazy","master":"32694a657bac54bb8b77e7d0d84014e41adafde6023723aa5779645c7c798d65","seed":"2719e5e2d4ea727d045817bb8cff56c62360b3c1c66522ee74d1b3e5c8d6ebd98700887d532f9d1f17a64bf683622b44df8dca30ac1bae5e296422cbb7741790","priv":"47b1b2ec336e0257687c8837c9aefdca2f45394bace57de882d7eba6c61da49b","pub":"034ad373c9e20284f233959b09432c82b0e7b430eb625c9edd1d5371a7038baba4","addr":"0900f4003360d4641626e75f3fedd19874b11671"},{"mnemonic":"asthma make clump clap tongue away used shift fiction siege tooth purchase","master":"0f28a391e22257fcc97aa8c229209ad0734e9d0ec8ecd67a203582f2c0ce7289","seed":"006b61f87ea0d6f9f87b0410ebb5bb54c9b8af72d3dc6283152b6e66a299b8ae0650ae528dea7b6fe5c6cf1652bd1b2c67b7e1c9ba5ccdd4111589216bdd02d7","priv":"6ad416539a8a969ee72e48e1b20e9502b90078dce0b5a4245d7cf12d4857eb5d","pub":"0274de9f743f31744d6e7ecf30c74ef56201c71b2ab56d03eb849f2adec2e3dbfd","addr":"67e73523c5eab9e70230fb7a806793419d28df99"},{"mnemonic":"nephew kick predict rotate maximum giant fit love float kitten embark another","master":"dd3cc8f83542c0fab49c660198ab42f48681db60661015e15fe4da87840b371a","seed":"5795b7fa476bc8f7b07738d313716d991a7bc2fb303fcd7012dc54e411bf7111d9c9159c9b28d74d5614b1f3a738bcdd63666b6b14b896311df18609521695ef","priv":"d84c0f29a4b95296e349bdc8bc9283367f5f68155fe92192a74f8a08e3c6e38f","pub":"02bc5af041b0710cedf1cb8895da55349d68ef4677670e89ce5da29f43bb063027","addr":"ad020570cc250019ba70e84f13a0b0c388443c08"},{"mnemonic":"filter vendor slice outside win urge welcome behave valley merge gun talent","master":"e20ace834dc8b88a259a3c6f983a8065ec612205e25da42103e40e968d1bbf98","seed":"1cedd43d959db14714c7e6f2f2caac10f548115f54bf7fb10ff4f178bb410530d8ade24d2dd770f92ccb459ba2dcf433d064c9c24f0d59137a2f808421e189d6","priv":"ca111d268b05839d504787ab4173f2d53cc459ea69c4965bc267db40b3499f18","pub":"0316b77b50cc08af7251303e190a4a12a96ce586631188d5f2ead491825db0b27f","addr":"c691a61bf6a5626bfa6b11f79a36c89e5f7efdf9"},{"mnemonic":"salt vote cook live accident leave define home section loop fiction sport","master":"30f08d7392ec4b37ec8fe00847aaaecc975ad1c98d64625b6e83525fd363b89d","seed":"85abff82357508cc583ff2c4cdfda7867467cc6889fb46caba56624f8c14e6141231c6b26ddd373b9e3504d90ce8b01da123ee72ae5a4db46aebf4ac7b8dda44","priv":"297a3c7969c15e6a3b4325ec6b4c768128aeb99e81dd4aa3cdbbd488e124b73f","pub":"02191258d0ce26b1e6adb0b84d19317fba6818f06993a46df1829a61a682a93185","addr":"a1082e1177f32b0b369429050324ae1c06461e44"},{"mnemonic":"model today toward awful apple actress hard reject discover type must member","master":"58168653609c2e12f079d799a7a344292edb46cfb7cf69a85f8a608acc6e47b0","seed":"bf3a70e5a322c0fad6db542bd4ffee2ed3ff85073e6d3ae01ddb7cf30773250c294529d69dc31f86ef390f30907c6da925cac78d10091d9df0fc97a6e48d9860","priv":"0a7c2b48dd3ec606816404246a0e28c36790c3b2f398531ddb7f1b7aa7e7d624","pub":"03f12f02b0cd5d3146eb28fe6a57eafcb542ac30833b7153e1a9121c3817d0854a","addr":"06eaa20c1fb4487be17eed4bcc57d49f1eeba446"},{"mnemonic":"popular among unable purchase matter athlete fever acquire mom install glance where","master":"fedb71f6c870bf049aa1355f4858675ca0c9a6268be575844d2313365df45382","seed":"be3448251aef8d22e97fa58862ff534bbe7a854eb0f1d574ebb49c4197328783c9f7a1b51202e5a37bf5b2410e3b6e11322977898c75241ed4806d1972102457","priv":"3f27d257bf6a625ea3dd1cc4ca9787c29027c105bda25d3fb44df992baa4ea45","pub":"026abcb82486454ef9ef70f5991f76cb263684624b040f9c7b1265569e65087036","addr":"197ff1aedd06d9015acb4712a4a3ed76b420be68"},{"mnemonic":"kiwi rail hen destroy path mistake protect carpet occur jewel pizza lazy","master":"7690775869756887b1866a93233ce2188202d12a4f0e01501e381b8aa120fd2b","seed":"82e3b78430fbad5184c4c7bcb1873d922de0758894d770edcc7a487ad5c10dd381345aee23f7d996dc8fbd44ed171b3e6e9b6dc19ba5c093925991aff3b303be","priv":"b0af5290094803ecbd0076266db8a65837d363be36738f267df6a5c37ea87b26","pub":"03a4b20c1179246419b5b5cd861ed440f3856b616c4bd5a04e0f9d45de91e25daf","addr":"ba2734783c80b277d6196850cfdbb7f1d599fd3e"},{"mnemonic":"cannon hill absorb ozone play derive duty quick unknown divorce history march","master":"668302ce757bac9a084220ac55e22027595a5bbf777dd344351fcfe668e58ff8","seed":"9282bc012e007bb31f889b9b284ed8dd02bcfe5b14528ffa0e128fe0b3d2bc27d3ce5240d14d581b5a530f66ba3c7146d891595a215b8faca2a0093287155171","priv":"82f9994e259551b52e63de92d93f21222b01c9f371c8cb0e9af15a6ac93b3fa9","pub":"030c0ca2aa6353264f3683210199ee7ebc1c051dc657a47f8ed9e95d50ecca2840","addr":"285debf5e963ce3fbd66a5fbb0841cb8d0a67745"},{"mnemonic":"wild saddle spring meadow spray lobster enroll album coconut chat marble follow","master":"14f5a8838df5b6546b7179704bcd40d5a168393bf9a65d0d5b80658e750b9cc4","seed":"565ab133d78d7fe7e8763fd73fd89ce7a5eeabe6841e5cdebb9a86f867c63f1ac7f3e1ea44029409bd48befc187f762480c3555d62fe9ab653ec2f8523b55516","priv":"229e28ae8746b90e772aa80afbe866cc08b0f49e40d4b1a512be21ea728ee0a5","pub":"026f08a2daea40b6a076b79c26de11bb1a5f74b9d127e79e1310d5a40675d5da0c","addr":"b262603b81f2f0ea718ee4fbcc9c807cb0317e70"},{"mnemonic":"firm mystery spoon brown rely mutual isolate degree stay brick brown abstract","master":"ffae4ec244b67e40036dceb4241614869beecad4e84fe6e41645159d3d5edb23","seed":"4e88efeeda99c5136e145dc0fc827d1a8edc96839311ae7c13e80443b4f8e7a907040d9a38be8d789200314110a91404119e33797e4ff5fdc790404322a7479f","priv":"be1343cf39f3758c560e38fb2b949c86225aa5a32af5328af3f476c94186e1c1","pub":"0379e9a16c9624525c15070ee3730fa02a9b8dac0d1847263789ce4df4ad22b533","addr":"2defd48b2cf9556c1bf6fde9307b17bad70018ab"},{"mnemonic":"shell open sing action exact cream scatter slim right sausage victory case","master":"d0bd4329ae716aebd1dbc4b75a06a4e6103540eb1185de24e180af67174cfc61","seed":"e55f447b58f363276a8f67672f8a4cd6a3bb014b5cda555f8d94e701dc775c4092e313e1aa102f36c98edc9f1c76d863afcec6dada643667f8dc612c43cba71a","priv":"31818b15c3b42238821b8a127a33e90100c6599d6c2ea10797f111b5a741860d","pub":"03c749cbf61f0e5b3cf815c454804486f64dc15e73c53b8957f4a1b0c1b3f36942","addr":"586fd2221b5f4dd31469ce689ba34160ecb002e1"},{"mnemonic":"mistake eye absorb midnight box nose bronze joy body trim give purchase","master":"8a97dbdb939254072731791791f1cb5f86bd61bee1b1a7b1c0220362b73f9048","seed":"ff955704f42fc8451d66092b720eee4153c1edfad5ac3b96bc87d0e1ff27a1655eb4c1127aba45906799197e1a92dfbb040304cc5acbb228f20c828d0f28689a","priv":"81b5ed5d49563e225a164180c53a55ee86432ee9e59ff5c6b1ba2dfdee8ecc87","pub":"0214a81bb7326df6f884b465b655f497c20bc68d2ac499d931945a56a20b21bab3","addr":"e4d30cd4f5b383401bdd02a01bdf1e7003ff9e7b"},{"mnemonic":"stadium blouse more trend reopen sick test trash glass bounce brain total","master":"a47cb7d914af1a75ca7ff6bc0192725a7b4b4daf386a039e9aefd8679f8a9f66","seed":"2a9aaff54cc77a16b4ab472b006768beb7403cbd11cc78aea80e19765ba685abadc03dc27c6444960bcffca5e206dc28f5564fdd05292f68ed825bb06ed6fe5a","priv":"7125901a72c60386b41bb65e8bb4aff64334ba8f2e032d2c032869b3b3a648a8","pub":"03a74cd7b3d21dd8698c7cfa4c30d81a454a55ce294171f30aa70f564f4ed71751","addr":"4a8f9540cb406aa75b0d68c2eb40869a8c25da92"},{"mnemonic":"fetch use target promote later more increase logic oxygen provide original high","master":"f06c1e5b33b4d18d65ca7e0b7627c23ae19da34a6aa55ccc8509fbe9fa25de3d","seed":"8ca3dcf901cddd77ad4f6db2a2e3a48fc1a00a81b372fde0dc926c4006c8cf81862013008d9e119d811512b9f98a84c7c655b071d28c295a5dd565491b961d45","priv":"44bff7bd7e57b709b5adfc54ec47d084d80ab9549479f4707a27e06a06083f2b","pub":"028d649230f94064c7837760706a615e7a714cae79a7b2363d493f9d4300b9a2e2","addr":"23b883cc57bdf88831c021ad62b2ae475e09d365"},{"mnemonic":"boat cause tooth danger box anxiety luggage panther engage human army language","master":"2c0c2474241d615780d2a1f34c4cda2a98e138c7bdfd13c97b341ddb8f5e87e6","seed":"98246a445ad873a5e8ac532ad64643c7e4d0ecabe60c7683996d58afbeea843c61cb9518461270cd2786453ce2ef39cac5818cb1aee0f336da3112be523349e6","priv":"f94665aaee7b5a07c328d74e3f5a51bdc0896f899c739c284bb9d882636c9b67","pub":"039f75b5dd06095b39778b0b5126907ad39a9c034dd5fc5e33f53cc00ecbecd8d3","addr":"af2307aaf8e07bc2feb04eaece0063867e64c4e5"},{"mnemonic":"much youth team what empty door language travel attitude rose furnace all","master":"df555390632d0ff6d8e472ef734e8e3f8f83061d5ddbbb2034f9370310356e35","seed":"f450c859e941b9d5e84126dd4710bd0113adabda8f962d383f8ba54bcc53d0e6e1da264d1841547ebd7c1bdfb8c29089a57ce05b64093653aa57e0ba51b0084e","priv":"89705fd7c86cbe5c18758ab9d4dcb7b1b6df12979c77a61c128ec13672b4433b","pub":"027949604d41872f518c8fabd333f8f351f16d68cd7e79e341f1b8368fe1b79842","addr":"36d1cbb6eb2510e0e3c2e76c2400dacfd9eae736"},{"mnemonic":"hamster adjust rally crew clinic skull private oval vast object school liar","master":"face99969ad94de93d7979a246a8e69e85dc6249bfc71f58ab6d774449e4f18b","seed":"ecc06609969bc31a47adc214324b7f7d81d09e0e3cb32eaf6b7be548f74eac5a9397300f0ff5650bff02ca895db55241d49b7037a54cf70e3fa62a3edd7206c4","priv":"c1d424295f77f3eb9f3a71c3f800d9a5292a2df311456daa694f5f6e12a7abad","pub":"0334e88812c848228b83e80283f709bd9827e991db6076a22f7497a3e73b641ee3","addr":"5f1a48e1eab155c3a698b69f11c0db64a556140d"},{"mnemonic":"dove grab grow giraffe pulp lift judge pluck dignity theme cigar annual","master":"3bb034fc63ce92269589e21c4fe89e16081e7cb3a29ec91f5ffb30bc077d914c","seed":"6f44f1782162a9d78af64e243dfe4d44c1ac521dbc8a00977e5260b6ea5d7aba6c205bc51b6c56b5139274d8b07bb31a728702df2dc2efd8f4f07c09bbff19b2","priv":"c2d5188d3db0a2dd9853104e3978c27d490eec8c3601259c4a4bf6e0fc30260a","pub":"03f7de67b6490d9cfe61818b22380450d5b5c815767c4efd821f3962ef4d430b58","addr":"0b5513fa903ae028a8bc3153b5f50b2df555a77d"},{"mnemonic":"wire silver blouse theme lumber modify muscle among orphan genius diary crystal","master":"28064c9af3e4436ebc8e71b424d749bdc6599b56f7ef1ead765606b4920d81cf","seed":"2a132c76e5b88181c24491f83f72b215b7963972f98c3d165c3a452f88165b459bb6e3756a511f40f9de0d47df6a030e91484a2fecb1648b9f194199143ce49b","priv":"232ec9cf0fce12247cc6335c9c8d54418a7db5aae86365558646d9d69b64af02","pub":"033e30397518d760b53821e3c0b3b43b324853c919b77a855250abe95d3924741f","addr":"dc7c6c94e8f7823485edd555741cbf224087f137"},{"mnemonic":"pattern syrup now tired gentle accuse rib cruel cluster wagon sting situate","master":"39f3af4487b768e1f9c7b04b0f713d4c56a5250994850ea4b20ec010a0879028","seed":"387138abf6c255b137a365dec7b8141ada4fe9fc55d75af013270f2df78328048981e69487873ee8740da3548ba611cc90f5a9315efafff651ec41df50732068","priv":"7270c0bd092550db36c7f5787dc20d17fd98edcf34d3d662085af7dfe604c8ec","pub":"026d65397b9ec78af76ec8a6ca1270cd0caded21aebef86160d4ea446b3dcc2f6c","addr":"35566b676261d80bd15792cbb348b79da3b10f56"},{"mnemonic":"blind force awesome radar law patch warfare defy device exist chuckle because","master":"b5eb133b2b7cdeb1bf5e6d3210f6a26b79b544ecf911f6f8cd838c7a6383e0ab","seed":"8a4539eb40090aa2cee32979ca6e8a23c1dcff202c935319db667cef1d2d49cd2a71f9cc54bdacbbed179b20feab254b932bc3c900d24216c089ac4f5c2cbac5","priv":"45e109f71861222311afe9d12b8a2a26d6f3fd0484b97a96bce464bec83346a0","pub":"03fd6c933a364638f867e6fa329d5cbf35aa9701061743ce5f1f6f6daa7137b3c1","addr":"dc3b76c2afeb877b256d7a9375618d0ec526fd6a"},{"mnemonic":"chef flock stem illegal later shadow tragic story tongue also fade core","master":"b7e82f75da29acb35a7714d3bf3aea45196e1857b5597a25b8a7ef6b69e9271f","seed":"7d02c419d5370133b6a0d0bda76a70b784e530c9a0b389cf2f6eebaa07ccaf946859cf4a7b2076814909f71c9c84ce3c0e45ee8caca9a753d5c2240029ca8847","priv":"555a830f9fc1f99debe0fbefcf34df402655484e5054c3fbd6c6a127e3356675","pub":"0238bc6cfb2c3c335b1564fe159e478d700a95ecc34ef23b7af3d571da8d136214","addr":"d3e9edf902c8dc5fabd17c17db492b15bdc33ae4"},{"mnemonic":"paddle appear actress output peace maid foam share afraid quick into erosion","master":"a3eb9cf3115d6b2f3cbe4bcc4f06e879b837d3b8960853a955f1231b8f95318e","seed":"a6b3ea2da0b83408010911cc091f9bb6d296fb13c1607cabb850824591ee5f69d0a2d4576a4361f3b368d34469f53282a1f9adadab3f8ab12956efa6d323cd5b","priv":"a37a2cf232918206e68593863c195d4319548c85d113456a0531b160b1c4509f","pub":"02a129fb596143418f94ec7bb1272aa1fda227e606c99f86cde12e8e7dd9b06755","addr":"69cfe226958b42832adcf69c7c84b734459af9f2"},{"mnemonic":"they garment wave wolf rubber firm toast hidden grit puzzle march rebel","master":"9c20ee12718c0fea98422c9ae0fa861da154552ffeb9e9991443edf224557309","seed":"99880bead4bf15beec406d9e980b46db9cfccd80473fe36d3471a0be1cce8f13bab732ace2e3589b1edbc5900c6641e088dc7a972bf11541ad475d97a66bd61c","priv":"b38db625f8ee7badcd89d159fa867b7d30ae946f199141f63af8e36c59750150","pub":"03ba880b842c952123b8bdb306fb0ec8c3c39e6bae28f2241242858c5c9c8c574a","addr":"24b75369a914827ee1e2697d5f591a58cf3f7be5"},{"mnemonic":"virus stand margin found heavy gadget depart idle guess siren mandate sock","master":"b6489aba56cfbac38041a70c7442bd298928cc37706dd01481fae719a2cc1222","seed":"fe240f7a830cd984b4b07cd77ba9a4f6b25e753cd2c981231e1458ed6775969a6b032be398838d2b5a706563d575177812361fa7cd35798e9a260b5454f3cc53","priv":"801663a31b3fa9f6788c826388b6d7272c53b0c331843c3ad19ab8f97eafb1b9","pub":"03067a334f5db13f9918aca85c5465042a8e994b835d6491604ea7c6b5d8a4403c","addr":"10cbc824bf4e61e2eb4091c0b1afe0f24ffec681"},{"mnemonic":"logic drip eternal frozen equal defense pudding prosper destroy chase faculty position","master":"df13ceb0854b9a18c97c8c972bc42e85231d26c4cdc87dfd3b8870b8ae0bda01","seed":"df990ef85f0d21de059f96b7037b905062b9e098a5f401afe29ae379a60c611a45cdd93f98f4994f231e549f739478566e71e7793fa750e92630aaa661b30e99","priv":"0395a33ce515a68172c9d8a324fdcb81073cd903f092581beb8ca73e8fd3016b","pub":"025a43eb1e0914d6f3c9269123280ec49ad469058d623230885b1f5dbb5f8dbcfa","addr":"6fa784b66d9a3c27073fc463e5a306916bd64374"},{"mnemonic":"nephew august wise enjoy age comfort hurdle cross feel depend south current","master":"9c01203e9921c9cbc2a05aff4cb90757f3d2e615ee6c6ef2d79100b48a48214d","seed":"19b2972d829bab57e706d21f00356d24cbbce556251aec246c36cd7a5243898371c92ef562ab2619244ab5e4854b9f76f76e2886b35cbf591a154a2e915a8a11","priv":"29af8262b1361dad291ed3e682a77a6bb09378c6503037da5c236b5eee1ccc69","pub":"02bc9c65596cc3f49aadad747651387a44d922de3f8b68a9876fb55e50372f1fd0","addr":"c4e1dd670e6c2ffb3a964315b0f7a51b2116126c"},{"mnemonic":"elder badge muscle tunnel sunny ring kite glide post slot injury crime","master":"e5dd0863b56bb3058b0aa457e17bed226f7f8afbc09c7ebf3cde93ac5912d22d","seed":"cd12f2dd94caf3a76292863e9528acd822c915385d8b84a09326b498ad5f1a60a1750686204b2c51093a3a3003ea558bd490cec607837675d2561a0b6f666a81","priv":"0f8717c113f78a6aaf7d57a93d5e7ec3a0326c119f792e8d16dee61b485beb16","pub":"02be9b54e62d1d26d08c1a2126c813a3a3a1a8d399440471491534dba209b3b8db","addr":"dde70795b05c51858f513bb59e2e0aa9d0330aa1"},{"mnemonic":"lunch cereal approve swing poet fresh sphere spray tower scale clerk main","master":"3c7e4e9876b819aad6e94d6decb42f615923873a72a2ca8b6df3b8b0ee1c77b5","seed":"0f9fb7102299f4b02874a785f60009c616ffc1e74e4386e78ab3abe2124257c7aec23b8926883dfd343f7260bad204f1261bb76cf0233dae8785c5e3dc9b015a","priv":"17b7b6f6184325c77195a60bcb15358b318a53ec2990dd46d8f60d0bf7e2e245","pub":"03eddd35bf621d1a943edeae5f5a5242687ee7f99f14be22f694653e449b77c177","addr":"06e8ee97a22bb6b2d458bc408bee7384749ada83"},{"mnemonic":"night law title fitness critic soap runway patrol carry drift damp state","master":"f7cc66a4812f3a394f9d52a0d83777f22eaf8fef4575561e26b0c636c4beff55","seed":"99acca4b65136a2b94c935892e265d125a1e8ef834e52efdb7b2ad09d973806dc318c43b0805924f5b239b74e6e516615ebf42d0379baee78ab63a2a24d03bb3","priv":"14506c9564b199203e8222c7508dac642fc6f15c981a7ed0fd21658c18660f04","pub":"0205f6b2c6ac7c0785d7f0c9aa85258167a314bacafa71f478c2577b5f9a3f9dc9","addr":"b380fefd78145bbe311a87e314ddf3b33d9bb34b"},{"mnemonic":"predict either bean grace myth scout number used void clown route member","master":"c7cba4de1441602a0b8ea2e11a4d72d7a21cae827db034ed4e43cbb38e608a51","seed":"8e80bededc4b64dac814dcb6e8dc5ce3acfb6f59988f13e24106fa7b3205c72eca6a16ee44ab51a54ab0a07d1e7d855fc75e3bcdd5d652e10a8fe33f623b15a1","priv":"6577584c26c25b3d6b11a1f669030008793f3d173721acc811f2dfd470d9e136","pub":"02e7f1c5213aded8dc3a44b14874cd9098a41e5cf0a7c83b7b3e045b8707d1d306","addr":"17614a88c0e044659cb6f99334fd1d8a83390df6"},{"mnemonic":"actual between river curve keep sing hollow bread theme corn mad easily","master":"e5498c15a99ef460088da7513360cc0e8ed3de095027783154425011575afd70","seed":"55fdc52505724e42ec76e0871860226daee30280de52f3d0538b8cbcc426ecd2d44287b4f1f11c01889ef63a6012896311a81f202c41e70725f3dff333f357c0","priv":"05b5a9a68afd24c6970b1686297582b3cb806729a277a056853f8918a706b0df","pub":"021a01e00670749567cd09de2ed8d0a66f0a0cb00cebb969ec43dcc9d6718da372","addr":"fb0c39ecab019c2d259baeba4819d924f8b9d97c"},{"mnemonic":"route aunt shed razor invite board ignore tower penalty claw absent solar","master":"c0f943565964df86bc140e8a8099ccb23417e7b86bf3c9f4d8aabdf7271cc721","seed":"111f3c5d234f0c02921ba5b30149d1913956a6c37e93fafaddbb3bf437b6709599bd623ad6ca97610717db77802f9c591ba352e7b08f4a06a4b897b9ac25c8ab","priv":"bba974522cb69e90b6b10ddd32f3b313bf5dfc129628bd2f10ad84a742a22cf8","pub":"0341c52f99a97637d09d68695b7b28f0c99d3fc5218d297e7bd95b267d2d7cac6c","addr":"5b4e4a18db22862daf7c43ec209bcb61ee139904"},{"mnemonic":"roof select rather approve must trumpet during more outside off owner blanket","master":"840894a95b0850e37a7424cdf10f73361387fffd96783a988a5d0e27012cb2cd","seed":"9eb1782d3ddbca4be52803a2dfdc85ef8ed55bc9b939246b9220dd911360c7323908996bfdcebf51b87c31c55cf2109c4792cf54b60374bff8f2c46bdfb97973","priv":"2db028d5651025a18a06e2c9bf77282f4bf35a8f54788624ffaadcb0caf34474","pub":"031c85b1faa9a2c9b3ad80328c54eb24cf27837d1418dba04fce05565f91e3344e","addr":"a7e4da90a801adcb7b3d9b947e760966fb4aadd6"},{"mnemonic":"album ball volume coffee motion cattle album wing unusual tornado bread stairs","master":"8bdb565fdd586d6aa72a53ecf88e2c81d48552034401bed5d130c862f179d159","seed":"aa0aeb0065b4c8e008fc9b1363fd4b32c0405359dd99f3a27670874bee96e8f1d76fdc807bd903289fb66b33138b92902ecb0d2c1627ef39353eb973b21b0003","priv":"54288cb0b5530aacba3ae1b16945a783e76ffde7e7c523c0c1e1293f00b5adc7","pub":"036974570620961a4e32d0329c851cb1e4218566056249c534ae92d77aabb73438","addr":"d7e65a2d95bb5d705ee894e16e4b6e4aea4821ec"},{"mnemonic":"start staff chalk volume emotion liar route lady sample mind casual involve","master":"aa479da35fc7c15a84e37a118102c41bb62012d872e34fb4f1317b67f9d7c452","seed":"70a8a8b15f77356e12438aef9fc97e6e6279be885fdcb28968db25d5c7bd2a3685aae1ee882d49658414af583c4339fc97f75f70f5b6ab23d184768cf12472b5","priv":"e1f12833fe2e792a0d959de815678a79e1e86342c7a092faba765979fde1d93f","pub":"02f127e13853937be361e47873d965fb8a6d602426c89389ffb45ee712e86e8231","addr":"4fdff2b288741e9f96b6595136c780d979403e2c"},{"mnemonic":"canvas fashion mandate will phrase spend galaxy good advance dismiss inhale holiday","master":"71707593bfe88f2751e6b381282fd71177be82bdc7b930c89c3f30606e0fd356","seed":"c0367432ce6b26e2d0b279b008b1d7d55e89b50b3dc55244360eb611d3af8c4e2dc6ee92f38e5e32309d4ca3b0b5c9eb9f8ba5edff66650dd052ac01f65ffc7c","priv":"0d53e4411bf7c498836412991515876c671967b55704e2928d87f3559a922911","pub":"03bccf2d3a8927babc9cdb6ae16addef1734739941071149122e780c9afd83877e","addr":"e1f22608018d5a6ad02dcac24a9ff28e065ce2c1"},{"mnemonic":"area thumb debate bracket unhappy muffin liar cute subject resource oppose nice","master":"416206edbc49f77c17405abe51397e5d5b547d300d296334b9848e4a844f355e","seed":"a08e97cf029eef0c4bcb3b2dca43e64b7a358199ced33a114c390ea81bdeef23aa7a4d6255993367426d051a56106e485d78f9b4057b4c50dc242d95484b39ba","priv":"9379dd5b24819205a9c7cc6a30ca2a416e6008af93817087b16778e9fa022fba","pub":"03e0796e8edc870070f179c669ef8acac6ba5d745c954762e5738e6db4d73317b4","addr":"ba2f7b307d6c8ba32f9f39174616def7551c4dc5"},{"mnemonic":"ahead face gloom dutch simple battle either hour abandon slush episode view","master":"5c953db2136db4be64531ea6556d5b93f1731332727eafa12630307dbc65c587","seed":"31d751f855507457129f25ecfa2ab8a50db37da0fb13b62ea4e232fdb8c7093c236502da769a0b3474a9436351b87df03a69c70b1b96c61f1675b8fec00f8ab1","priv":"aed4993762d4e8e31a12b500f8beecc1a3e747c2ff290c4e70141de4ed12be8b","pub":"02c922d80cccb9faa955b2ea0a90d3f72a88d8dd203a51e0aafb36c38af1f4c880","addr":"cb41fed3b24d89ef058d25d7264b6113e0481ce6"},{"mnemonic":"van custom clump rug floor what joy live art weekend unfold frame","master":"ab89a9c945f11e8ba88683d2a13cab657a9c938bd9014f19cf552bfd1db49bae","seed":"fffc2e2b6c4e1ff826e0d68ef4a2660417278cfce527ca55e48c5d3286d78ab4d6ca874514d70164e9040641281478b8c3b078bee6447d78262cc0556b463c4c","priv":"cfea30906faf51cc15f5ea6fd96ed92a40dc4bf80737a20ba37280e63ff1ddc0","pub":"020bcb8f7581415d4fe27dc7d0dcb25e4e4883d1290284f9d3028a6d0d618daa0d","addr":"57563ee5328ec10f7af2d0c44b95e5084afca64e"},{"mnemonic":"icon series document grass dutch green blossom report violin beauty window luggage","master":"9a203cb69ec2d8d19660947de9dd0b46ccbb07c9fcccb63da50fd3383c5f31e0","seed":"4acb08487e8a407ea10685ffa35b1c040e4dbdcb7e18a25c94a459bc7a2224246a00b66b88e6bea84948ed07f818e6e1a8fd4ebd102339773e704ce048a359ea","priv":"64d25c6a43d0aae389e2bc5b8f7d260098d85dd6a8ce929e42597490e5240ef8","pub":"03602214319ab01e65bda4711f9d03be60da39e092472d50492397e8f38d90f8fc","addr":"21fed5aa21ab9fdad79aa757d1408c0921d08cf0"},{"mnemonic":"upon legal wear defy path object fold security stem face question hint","master":"efa4834167d9f43a0807a950687e79ccf9327ec707fa4324ce8bdb40ed65e692","seed":"da5371985f4c48954726882bb278971512f9e4ee681645fea98415bd3ed4c7b049bfed3a3105f4d064b61de443500f53b4996c1fd7d2835d6b3e5b52cf67df5f","priv":"963ebebc47e1bf6c8f8cb515d7044f2095f61a8f77ecc2c7d5f8d1900af3b41e","pub":"0267d73ad34ba786e92207f5485f8aed4c634bccefe1a6c6a018dd30a9969bf1b9","addr":"f7b39221ff5352c17537d201c7d8422ea4c2f256"},{"mnemonic":"adjust symbol absorb winter dilemma reflect private all eager naive bundle lucky","master":"f8469edc4fc1bc6f3b934bc6ff8658f03fe2bae4d9be0b2689caea9f23d708e2","seed":"cfcf7299ef520c324a79db53e24326523e1d2346f173ecdd2bfdb38462a83c290cf80260353ceac5089efdfd9c819c3f0f15ed653ac3c4719b0ee6f0481335de","priv":"44025bd2acfbc6710d64d8b71eeec4934e054ab201419fbd553f6427e33d5197","pub":"02bbe2326c3d6c372c22c3aaf8118742442d237830428824160c5e703c268e06bc","addr":"81986a5c30d253a2b2ad8cec56dfd56ee3435772"},{"mnemonic":"fringe betray observe subway nation dignity stem omit topic lyrics index cause","master":"b8656cb35da2ecaf6b5189d8d252a08a15495afbf756ad1365ed757bcb46945b","seed":"cf0cce225311bc1fae42b654561de73cd2720d5a2e280cf39a1391cda8937fba9e69bb5b73b31e929d39a5f58f9505351f752d7666aa81211f69945ad81feba2","priv":"d55bc330b3ab7d09b0da10c1640c6fdf10909e5c6318801c3e7f877654b8576f","pub":"0222c2696c6480e840a7ff5d106f025d87309a0754a3638fcec93a6c7b8ab1f48e","addr":"2bbcd167f45d4f265075a2aac85d0ab7582d435e"},{"mnemonic":"ski labor urge doctor repair purity winter pond virtual salon number supreme","master":"283171546741970d2804029ce72b5848cc479f32f719b4f28670b00729c9ebf4","seed":"4aff8616a56b882083dc3f586afe1128f17aaae7b0c751bd24109094144c0f7aba69dd63cc4490301a72ac950e6a9c71959fd387629429a65178d1d4c7850322","priv":"2a0f5db45dca9a199102d2b920615cf2cd2c3a1d06d3fe72d5a64291fecfa116","pub":"0294a39a5a6f878929b7c18b0df75c7f42318864d84eaaaa68891f075f51906231","addr":"5173ecedd00d5de79bacab582a5b3de6f0534765"},{"mnemonic":"surge move forum tongue female cart foam coffee hole screen short clever","master":"57dd827d6deb98495732fbf12e0098970959ecdf113d441bbe6bd5064abc07f2","seed":"606c47f8d6984ce47270900cadf4cf5df3461f9293beeeaddc537c2e4b1d3ee7456ec7165c51e267d3c02a8cbbb5a2478626e475483f121ca5856005d0cccac3","priv":"3895a34ceb1de14e7e863759517cad044901cc7c8323e8565bbba98f5f3719b0","pub":"03a30052a8169da7d2342be9b0e2788df3e5ba7b4e6fef048662427476d875f537","addr":"9d9d8be022457576a9bf8a6a48f760fe346f22e1"},{"mnemonic":"ladder now flat food giraffe myth tattoo client party address tip avocado","master":"9986ab1b096cc4a635c2f99e7b191ee4d786b090cb1e00bed2cf18d6ff919aff","seed":"2bdf711ea898c4d62fc1c30a4a55dcec4928186c9d118befa4afd8c52d14291b3254ed926b1b1bbbcfe5ae775f74da99fe2112c7e2c64013b8f3b9de5adc18b2","priv":"cd0cf663053d6ac0d9785c3a56ae190fb8d0da670d6529e2f4572c1388dc6d8b","pub":"02ea2969ffa84be7d76fa55f4a897ecc63ebd61858b7561d41e179a38c7dbf8b79","addr":"a640cc723fd1d903e60a9de68e0a009b5e215812"},{"mnemonic":"change velvet mobile copy column cabin mountain shoe hub collect gym armed","master":"f80e68b799c63dd914912454f68a3c6ee5e01530bc48c130f1a4cfe46fdf2265","seed":"1bf846591febdca13c576bcdadd352b4b8b2ab8e346ab7db8213120d5b2f7a8031144adfe06a47f1d200f69c46bf9dd6dfae8e2d8dc94089b4974275960964d5","priv":"370af5ea565ec8725dbb8f63e141b12480bf43d39c219d612ff28e2a5fef031f","pub":"024f70c3096eeaa522240b50c1ad7347f1df1e764a305b8e618489788bf15865d7","addr":"e5226a6737202e5ea8d44f84620317f65fcd4ffe"},{"mnemonic":"crystal impose connect thing cement grow gospel reopen hand frame child shuffle","master":"a8d5b74cb00dc99c4fefff90a2f203b7e73daec3c7edfc71723894db050771f1","seed":"4e7c12a432766826d61cd07bec71147cd4282b2777b8ada1d09be5b873b9c51fb90ff4f4ea75739254fe7124e24696f66313d75289dcfb64ba5f5c8988b27ff8","priv":"7bae6919d134d0f150972cb0d96b0cbb3002d0d3b70efb2f9b03541c3830ae21","pub":"02daefc7677b5d77ec5fd27cead44fb3bd2d089be2b2e9744c1dcdc2e7def701e4","addr":"dd3ece1b6e903523289949e7aff1de580a536746"},{"mnemonic":"seek rain danger defy olive pluck people trumpet wide pave still cactus","master":"9d45b99a256e90347877aa27845d7ce7a259a8b50f7039852c60c16c372202c4","seed":"9c3f7dcb4aada2a8c204bef9a28c039dddd431f3daf5e70feb240be712cbb3dee3e5b65ed1e681255e9bb53bf762d82b95dad1bdedb27d0e18801ef1c5edd7bd","priv":"f43ce1484840f98f862f7d9c835bb3987fbc0413cf9121233bc29e829c779d45","pub":"02d82770b2af7ebb2a5eec49138178dd7899783a1ae1ea43ec3b2a13d6acd90c4c","addr":"49c6feff9794634c9fa66c76150375637f52ccc2"},{"mnemonic":"cat bid just hat diagram mimic field engine light elder resource render","master":"bf8a65e5cde0094db2ec4a5d776acfc944b0b482343bbe167a4bcb0a3492a9dc","seed":"780befda0890785a11f947a7da4280b897ddac841fa65e7cfbb01b09a46af665c25dba88abf759bac86e02d25d90c41347cd872f8abaedb158743dca746e87c7","priv":"b3f9f0ea5881318a1e011283a4e845ef6fa8e1ec5110bcdbb02cd37c4321c0b8","pub":"0214709b38a99a173a8b030bf9392534ae50d157e9e247f83d271be86872846336","addr":"9a7dc12f808fc5e599e2c03f73147317e381822e"},{"mnemonic":"eye thing material display own coral ankle spell hurry empty pitch sadness","master":"1a7c1facdec5151ca8d52af1f507f45c6614d12836d2604421138339c81dee2e","seed":"9c741558ad4c72086738a34898567312930af3221d13b160a39467d966862405a7f9b0b8718207bff6e26929cd33c578457b0d43e2e6358d488016c6ed7754bc","priv":"960704fe746bbf00a1c8d6bada8e500f2a7155af9f8328b7e4da7fc89fe079cf","pub":"0217e48b2a7ca750baac93ffa241b6fd3cd2422989096e0ff5eaf89f23277efcdd","addr":"13c55c8720eb51b5638331330ca19291213fdcfd"},{"mnemonic":"attend analyst stage network secret matter tackle safe stumble rifle lemon minimum","master":"e23dd8723b90971d4e03e21655e597b5f8110f0388392eff572e88db7f644cad","seed":"cfde90f605bace06583d24be20b13f73b3fd0acc60fcd93c2cb7d4eb6fcf70c885da2da7b709ba036ba20c275d99dd3a6af434b00932addbbd7b51a10cb5ddf4","priv":"ee54ee95a349da703f6d192fec6f776db6141a0cfa80372be04ef8b12ab65f82","pub":"020850e7d1011e08d7fd3ce20083b6c2658dcbdfdc067c979bea22d86403da9992","addr":"d834b0d108165f814c2616c91e18ba8b76a0ce92"},{"mnemonic":"student list element dilemma air faint eternal beach approve virtual fold large","master":"0dbc34013e5fddd9a1fc2d3e67a2d6d7445bc31e8343b4bf1a9c4941a24a2691","seed":"61b310aaa1875695f855a341f64b849774e3746db36303ada42eb60bbc91bc0fa7199c10f853e1def5fbf0a9ff2c38dcd803866d5473808a5b6340d88260cf57","priv":"ece1069e2cec7f5d270c3504e0cd9d8806eeb7ce8ce48a138c92d93d68fc9b7b","pub":"037989ae45a6a1f0ffcf9f73f1910a91bdb1ec39101810f3916d29a70b92232949","addr":"10c79559de51b7b96a7e0aa97f567289c41df1b7"},{"mnemonic":"ordinary fade chapter cheese patch injury better toddler rare manual rug opera","master":"ef81a17192ebb6e980676cacc7c9ace6af5d449a3c976d4f9a8a541dcef9d7a9","seed":"5a277523f2cd468b96db9dc30f8dec2d006035e388ef5348bb327eecd108d9e2815b3575b0f6d0da7560fdee6244194eefedb25edafd6f53019a91063478dca4","priv":"86e5fbe3136bcb11f0ed6dd97e3fc30afc0590d38b637fb19589947bd33f26a1","pub":"032fc8cd996500910443186db8432f24eddd6e04e00aac15db80cb5fcd73b7ec5e","addr":"db0aaf4c44693b2b93a8901640b940104d4931c4"},{"mnemonic":"leg easy evil ceiling candy okay afford apology around duck access ostrich","master":"098f864a847ca737aa5866f14fa96e9e5a6958758b56bc205d5c45f77b2f6fa5","seed":"7e6d013d39c652c2d57ccbec782fd0b9da7610d3c716b1c5f374daabf44f0a21726cf39b503850a5fe7daac263cd12dafe5c81a38b47e59b254027ceb298b520","priv":"1b5e814a954729ec4d4d25e01b52e6a48fc3beec84e43153cf9e5b4d5e61b852","pub":"0207214c051cc66259f234100e278a89b7ca3185ecf264d596ac8a4d3baddea28f","addr":"45cc1c7df7fb67a482dde6285b4dff7087857970"},{"mnemonic":"episode suspect cinnamon recall shell search allow hedgehog web avoid hero expand","master":"ede0db7b34ead2b35bd378d62d1b202ec206a389e27ba6d70813e3f98544f7ea","seed":"186c47e08e2fa1151bdafa4c8d16c5f6d8e9a61600a7ed76257cd3b41338a6d158d34ab84448c34c871243e211fc5082d3a6e199749ecf5bcc3fd8341e2b7784","priv":"d19884813f89a780962d2bdb40f36debddb81d132baa29795022b9498f04de0b","pub":"035f028dd1b126d6ea1b8091ac9dee9a3f44589a166d84a88ee982bc040c67d1eb","addr":"77b6f1f39bd0c5c636763b855396d1fcc5109778"},{"mnemonic":"safe run differ offer valve sing stomach table update base pitch pyramid","master":"1f6e07713ac34f997bbbfa0148cf2cfded624ee8eb4c89a66e2a88af2becaa6c","seed":"9c07c30f9b29fccb62670c57b8bc2210851ae9c80a3aee48c03e6bd35357626ebc6af1226f236508624fffbb52a8cc56fd21d8d2ab72a893a931c4891a33bc09","priv":"94c75ada800b2f73bc43625d569caf9f59f3afab6c2a8f9b023abf169c1a50e7","pub":"03263f919a4f79646ba17e1521c15f30d62c545d59c12344d4ce7d7561f8dd8428","addr":"17a63a29abe177f8bd93648ae4283b175b83c841"},{"mnemonic":"bubble bracket panda fury turkey decide obvious nest carpet defense side destroy","master":"d429dd03c2aac3ad66e8ea577ff48889d6ee006906f0d74be45d935c11f95c4e","seed":"d665e949ccba3afe3d3e14c8328f9d2eed1b3838e97a12d137bb188b4480b31f5f8ff388c4ea3aae961e6e98ae40177bd7ae075fe09aabfbab8140da075e8702","priv":"651abfb657e1b400e230b0fa3de8c022fc6fe33c2a80e425b13a3485aca1bef2","pub":"039d2e95484a02e3be5176e31ad41d9d38fd616aa37bc2f3032594f99b1d4225b7","addr":"cdd7ea2dfee41bc45d88e147ca87f15cf0278778"},{"mnemonic":"magnet setup unhappy slide human frequent notice unfold use ticket raccoon worry","master":"6a50fb7353ff7e3eff6054bee3ed8a156e3f4d65d712ef024ebbd58c11b16223","seed":"15195988c4a41524602465915d8c66b71acb07f8681a81bfcc77f5e8ae0071da3d900792c6666ed7f42e5362d1b22ec5de2856019e1d98d34f3bd977e5d6e712","priv":"e2e5997cea44fa966ed05107ee5347fe245ed436396a54dbd7bb0dcd45b02a5d","pub":"0251022b3f87060b140337f8a192c3037fa423b86f761c8e8b9abe13fdc7e954de","addr":"fb33e8b4227a4e31ee6d062f14129d86c190b864"},{"mnemonic":"extend expect crunch wear narrow crater opera dumb poet tone crunch eyebrow","master":"3a18fd4a5605d4a691097909a8fad033a9eacf3a8a6abbffbea184cb43bc4054","seed":"37661f80614a95188f9bf047b8b78201ba0512421b3fdbdb079d36cff88be9fcc6b2ee25a98495eec605c23eca528535adb4381b524ead9327671006a34d81e2","priv":"66b6e15ade42ef203b614a0d4db859263aab55cf9d98ae2118cbae7a2a8ba190","pub":"0318a0e61048878782f581429fdb2acfb382c59ede2a9c9f96112fc0a4dce78702","addr":"d3cbc69596f7f398a77be321ab4b306cad08798e"},{"mnemonic":"genius genius letter space share rich lava tenant drastic today vivid attract","master":"b1cf44f330ef51b5bfc09c224b83f3f678381b54328d6e407368f34f6b96a7f0","seed":"adbba0a0b7e15f2e7a8f95b0cc9e3b212fd3db246c0dd0b2dc41fe740c2d045aad24b9113dadc5b72d7e53d6c681fd702ae46b6bac877303e1ef4f9b1daa2822","priv":"4bc6a6a787283d7110cf4dd8e5f41b5abfbb302a5bd627cdc78cc419bd77ecf2","pub":"02fd610c024bf89e83940d0a5142c1b716786ae7c02e8779de11b72d3474b27260","addr":"f31609b8ee21b0da14e6d7ebab364b57230a8cc5"},{"mnemonic":"shadow ramp scan elbow cinnamon intact flash bulk squirrel pill zero tail","master":"46e4cc1975a8a363b8834ef06ff7a413a6158244a769ef15a9fcfe8981a0a6de","seed":"a8e143c8945640084294cee0afa09fbe4607059c8497259afe64dadc11b18b2d0eea33617b28b0f80419fed842afcb83fd1ab72c163c65e798bd1668cda9ba43","priv":"914a656705241622201d5ec8893d0d2484de7f4546847b3b2b2bc5afff743547","pub":"02f44993307ba52f2a927c5e7f7aa0baa6036a1e396d1d8593be5fecfd330e8d70","addr":"f966ac61247fc88e7d8a8eeaa2e682a669f17e81"},{"mnemonic":"wire list water over regret much ketchup slim capable proud then bike","master":"161946d516fc549a577b76ca6361f97b95ec58ec3bd2486dcef7f0d9ac9de062","seed":"c9af9f1c0f7fdcd56a69faf1274e563dc8ab739fad639e2032b4c0de10081544112b54ffb36fa1f6dc6419a7c073e0f3b4f2fc1a9ed95e4ee7dd300ea15d48c5","priv":"9f7f59143beb62116a592e3884d34d28a845c557be670278877c34f3749e74dd","pub":"027ab6afbdf54f5e952ac1d254cab364ffd91d49838354b02415a97421f9b9bdff","addr":"3824d1afbe44568f2ff4762157046e8f9bb561be"},{"mnemonic":"elder stereo hurt upon process furnace treat tool hole return base protect","master":"331d45143f0f94ba73de22ff235fec62132559735071ef806fb696e36f113352","seed":"4967f2af0a49298099ac49d75a3d99b99edf1165e3507c9055a9cb39a69aa05f6c07c192984e86f6abec6ab9b7fe8e66d22451aed158a6664ecd59b48932d9d2","priv":"7d547ee935de522967f92d0114dd40bb5c25d4f5aa2a1f70ad291601b7d0eaf3","pub":"03caf4c539853b640bf55c9db886e9906888e05fad3e18668f6c6d529434a73f32","addr":"816e255b2ca6837ba06d35fb834c3c246563d638"},{"mnemonic":"faith ski shell chest left entry admit smooth since hire pipe firm","master":"65f1eb6d72553cefc6fa5202583bb6db0af228fc0f008af45a3301cfbd279e05","seed":"2b778002d9097d84bb24e0dc577059a08e0dc24b47d401a37ece9b43c45585d49ccf9fdc6dfd87dfa2c4a70a226b9879f0927b0f3bf33b8f25573c1b6da98679","priv":"249dd8ddb06d455e6883a7126084aeccba0193a8ca0eadc6f924c16922ad891c","pub":"0390281dd22e02560114169d73fd72ae58ac7a83681a8d985cbf25fb39b485ba1e","addr":"9fb024edfc6a4e72e4fee5a4387c7bf09583eb1e"},{"mnemonic":"junior bracket pigeon swamp morning kitchen friend bike question emerge month faculty","master":"7a3d1634588a1d344986c5bdb8e5aade22a0fe74b5d234bce3591edfbc2279e9","seed":"4429c5b3dbd4db57f6ce8cf79533a746db6c28e1494de3610f225eeb00d2a6fef327aa17d68c75ae552c9c76b0dec4e06c583d531e45d6ab1f7d5dbcc259ae29","priv":"20b7253a740bf61bdee294c67b31aae21f90a41b2bd31a02267a773af049f983","pub":"03531e337b7ed416851867015996fe06b19a82bab432137ac32c914503fdf7ef58","addr":"e225e41ab3e0798b3631d71e753179bcd9226ede"},{"mnemonic":"farm frog apple capital foam behind grid project vague rural ugly sail","master":"22f4185158d434b8084c21d62c2fe3e653f9f1c5e2d592d72188bc36e9194e57","seed":"b92f9f3c0d496fc264acc1c04a42bca773f34137c92bb0f8fae52009166f48ed36d81c15be9e8eee8fe5f1ea2e7e0311a2d2b683285730cd6657ff862947ec4f","priv":"696f26ebb007bf4615ffedcb8a08ebc1b92be88955fb34eb5f08210970d566a0","pub":"03bb83731e190bdf7777058603180bc89a85f4bdd68fab3ecbd5c8a43f0e9bdc93","addr":"9c9f3d7c144c33f06ab476c752227c12149d9217"},{"mnemonic":"spare twenty above tape monster topple brush excuse squirrel pigeon maple fun","master":"a1ee9e1be2cb0f318e9cfca44f99ce405115ff3336d1678d94904efdb71f65c6","seed":"e90734515d14ab1b96bccb6f823abf76f21d47b450841ed1fe9ab7bec8a0e673828d09ee61b6a3f9bac0dfca778287abd21d70d45c596cd606261bd4baacc98e","priv":"d8239cc87c27ee5b6aa13d55505a8b0b2785392d26b0945976b575867b3aa068","pub":"0314db00f6e43e36e5f9e6a30cb2bb595cf4abc4cf26ada7d3bc7502b0e6be8919","addr":"fa50a1e20f2f4e490359a011ae4277ec61ca2a61"},{"mnemonic":"token cruel spot firm initial trouble slogan arrive steak inner champion affair","master":"4fd49883fd0f3b32564fa038cb60f762bcf4e65d3e297649cda474a6de9e16c1","seed":"c8b7b6807f2cef122125ddccd237435abeb2370a33db98f34336a28763996b81c336e7405e782d61f6b391b0ab2792b3788e27e67cf467127a50a6b2603820ad","priv":"e57e8f46f2eabf828cd024b4c7935126c95661bcbaf58488ddf7954b1a4486d2","pub":"03d959dd4d72e64be96260d31018ff3b3cc626ea3b80af1d6c3f9f8ed6452f9da6","addr":"e03c8d22c2e4513ffebefa5ed6e89245d36c1741"},{"mnemonic":"gentle whale exist height dress develop beef lounge apple gadget foil sea","master":"ed29987b8768b2f2636556eb1db2a69d48e6969f8b5ed455e39d6239ef376537","seed":"f4a08df5d89dd733e9b73df8a8518a0f3b632debdea655ea75b8b5b6afcc7c52d8bc0a2cf1337226c2e065ca0d71b6854109e360da8037b9c2a01156b2ca2b86","priv":"656e7a54258d7e2f4c493ae80e28c4eb08452175635cf0cf5a9111bdb6f76695","pub":"02f5f6c66a11efe81e76e7a5d440b9ca1b0dd73429426f4a27f3493f5dc7140927","addr":"e01072fa64ebf18099a46ee3799bffb49b990972"},{"mnemonic":"warm offer tattoo home elegant sausage sister cancel rocket struggle insane theme","master":"a58d8e3b8c25c182f6ba0e9e61b8aab35c04d846d1e44ccf3b305bbc03d839f7","seed":"ae94ef9d748fc2b348be876474f261458e3653cdd3f10448af8ee2caab848195cb802050f7d5d098e737672e331f1e48ee0e14c5924665f0aba855b89544f1a0","priv":"4534e2a9248df1bf1882da1a11ac8401b2db9cd92e5c3698d4610d120e6ff882","pub":"0246a4a61fd11a856a818f3726163b7f2f5f41b95f5ec513554f7237d8c85c867c","addr":"dbcf36e66ca99566f38ab8fb86930494c28405fe"},{"mnemonic":"ill orbit raise deliver fat age remind throw stomach country duck neglect","master":"9899f940702cfb78dbb9fe8d743301e2de5129f943c8dcfc4215e937c59280d8","seed":"789537517312103fd88f70345425c402bf0c665c34baf7d3e24c2c969162afae078adf365a0bc732de7abecda4ef5b12e213f4027a9e0ae621dbb6a16532ecd5","priv":"cb4acbee9d41eff9ef210ca73ed0ac71f353464210fc29b30c863a0c23214653","pub":"032779afee4e50503db9c67efc858d521ad8454cd691febc52540c4cf96ca92231","addr":"bc60e5da2c9e96698f32bbd087bf1b3b599a94d5"},{"mnemonic":"fold concert earth alley broom render ranch worry motor virtual industry bullet","master":"3eaddb6d4a2a73a1f0d094957901b9a53f4b36ef00451c9157a3dc159b523cb7","seed":"479d7ca92dade2e47b3f410fa563624cb9a7419921c687e93aba27d82af323bf1d0f04d12faa018732a476fc626df000f705525706a5e5958afe59891f10e43a","priv":"d0e151f6b58c2f48d0311fb2800e66db4fbd9ec14c92f84654907c5018f81c98","pub":"0372820ca8fc7a193815e924dc1e7fd405afd0b03e39ed8cd01a33bdcd35f899c6","addr":"90b134c6bb272ff804b6117fc1d6f3dba538e3d8"},{"mnemonic":"grid street boss erosion spike bunker indicate erase path mixture inflict group","master":"c5063e2bcf9fea3164cc8bacdac300a35b0b1dccef63e1de233ab39356249b9d","seed":"2c98b2b7703e3cc2fbf089d78184f2cdfcabc7bf269ba3b57e7b033629fd149263063e3f08c0d7fd3a785ceeab1f9b2f7e383fd2dffd7d9e982e7342ec90ee64","priv":"b6082dee45243a3fcf3313715ee9a644bb95d550cf8f275a99930372bf265e59","pub":"0282b6a0a9dfbbe648db6afcb9596fed1c02b8d7264925c88ba7007cd5cecc10c1","addr":"e9e9b9eb2c9d88b080af25d6c5fbf425e86c8f9b"},{"mnemonic":"flock entire rent cricket shadow inhale organ pioneer pottery faculty west umbrella","master":"e1beb66b50360f8bf5253b40e1fae368fe8ce267dd992a951b06896ec8e44404","seed":"267dd95caf4834b42cc69941de4dbeb3b37321af83548c865efda2b3cf9eb983c8244dbe65af863f0c88d2e0bb530d7580a0641d23a2bb98c4b64ac4b38d84c9","priv":"b35f776a36af618b48658829c0a914f8ee193070fd9b88ab34f3b4c35197ea97","pub":"03e030c12765cdf97520be291bd25d0a34aefb295f7749904b9aaef1ece99cb3aa","addr":"5c842dfe540f09579539e1fa6e961f929a5b7b60"},{"mnemonic":"all hurt survey laundry follow earn car music online reopen boring monkey","master":"56a9ee4a3e11b98885540ffd3e639369e2124f9d9b7108894cdfcb154279921c","seed":"ad2252df70bfa330e6a7c48da592336d202ff2f91d1654d34e9139ab644d54a04f88f3664822aecf8565453b58ab77a6785e81ecd7156bd7d560ddbfecd8a287","priv":"4181c26d8062eb8cdd8464524bbd2d82b56f423ee8aff8fe49385ccf98130a4d","pub":"0336b154ca3bca67a440c55add8c0ec34bdda413d57e8488ec58402a61eb93f861","addr":"2de1dd6ffa17618df2f9361a427dfc9689d7df99"},{"mnemonic":"obvious spot fuel leaf company birth drill baby lucky oven since fringe","master":"c75aa6398d3568764b147d2a951f2a93a38ca76f3e380e0574f35a6a69d0967d","seed":"d2793c736f85dac48f03f67c39b2b943b297744268dfad708ce9eddb74c649515632a25468a3d444bd07a0b9c4c9d650ae8676737e8373edd1b0f672206d7b72","priv":"cc9cbdf4b34dfcafad90d774b31313b08c6861e6409d659ee77afb75a1ebfb86","pub":"0251043d6ed5e0325ed3d7cf2caa3db8eec2a63c4c5472421a37831e96fc5a2bb3","addr":"9f75fc6e07b3935e5e8f3a39fadba8252e10cb41"},{"mnemonic":"funny online improve knife crumble critic grain vessel wood inspire venture ostrich","master":"83a4036503ba3499d266352b5d7736d5a16519870f9cac08d4706bb3a57e5d7e","seed":"23ab1c440ecfdba702427c5024503232b28aca8de6cba59d7ee1e070e84a4ce15cfa84e06c84c9907fb6bdc9d73c94abff5ce5c4828da89631cf77a3b091cb7e","priv":"e7cff4b876f286e6a8181763e453faac2d92582b0f9caa41b5aad8235f79ee86","pub":"03f2a9ed2bcd20f9ab0b50a3ed8f7ecca7c172997cbc877a896dc9ac740ebe03ea","addr":"ef1badd2e02541f774b7ccfccf8f550a0da31f48"},{"mnemonic":"elevator scan glimpse immense shoe buyer punch tomato chuckle art catalog coach","master":"ce00293fa3230ba3fff5f53d163acb0a06bcebc77606c6c22166f29d4f84d290","seed":"e06c12a0d1f8bb93596839e0c3c566b5b59421226c1523cb54f86e93e391883486e86807472313115c366495a9973d34b2c7cefd919f0023bf2039e95f22ba72","priv":"94e11d645e24aa3653caecfa6cafb3404a6b107c076fa2fc03d3a2d3127c8e95","pub":"036ff6332fa0db2db68b6a74a68ba0eba2cdff43f896de3d4b3b0d26ad1017b608","addr":"82ea6dd1ca5f8bd08633e5b69cffd8dacbdc3993"},{"mnemonic":"emotion super skull trade tell drum lake scrap alley reopen true prosper","master":"8bd8b2834c0aae5a8a207a40ece04ebf9fec51892b8c75dc7e4dfb256fba3b6e","seed":"6d9fa2ef59c1cd981a97e8d3e788b8bfb9738ebb23561d2eb72fd3bf3741e90eaca1c4e821e711756ad8adfb3c5d355f55fa8f7a41ddf260a85288416228d257","priv":"5adc84e56a3d3e6b43e1d42d01f2c7ab1bc340cbf8ce99c30cd94323e1107d9a","pub":"029aecdc08e10d442234814770ddd891241afabbb088e7dfe41f6ee0edc30a7581","addr":"19ce22a905e023e40b9a090b750870bb4d220d4a"},{"mnemonic":"federal math bicycle copy diary bind clap dose clown fabric hover draft","master":"05e5ae86313b56b4083a77339441c22cac4d675f18089028b841e12d0be35480","seed":"bfc46d250c423dfd4f123a91d8c7d556d484f1b8091132cc6e288fffb4b786d721a87d93414f71fb87457ef7b4f17d65d751fa43d7d67523d95997e357141ce0","priv":"760e1221ff1a283d14bc3fef817244affa4787036a46d3009d53911bb873dd4d","pub":"03286bd104bff54d0d01837e72b47e1bb582c13c78311a73a08dcffdf5d5e6bb42","addr":"d03ae88abf654c466a93dc167be85b7d1d172e38"},{"mnemonic":"parrot poem unique trim auto april under pear brown flag critic ship","master":"438ae7958c45b13e2f2d275f52ef71e6ce20d00545051101fdb5be7e235d49d2","seed":"85ca4c5faa1bd0c0a3b74b8a9f5afcc0849be00a0d1e67222a7b70a9f6343c0c637843756750852dd6247d311ae14f581b642e5c3c4cfea3b689dd1c9d4dd18a","priv":"f725a96177c31ae08f065255578e34f58145b921267c2a2e26f09a3fe0d58e61","pub":"02fb792c0736e01eff225a1cfc6f56ccb8ce70fbbb9c050da326ee5475fde784df","addr":"d096954bbd94038190e6aa959ebb8e6d4c5cafc7"},{"mnemonic":"expand enough goose wrestle title hamster purpose illegal peace patch moon spin","master":"fcd43f2a177b9c6f19b22a5864b41a30e9e4ff29cffad7663a6d5e5574910a2e","seed":"0dcfb2c19f6b6b6560db73bcc164ff84e117fac8a11027b0c8c2caf5c97256961e019dc1ae14752af47abd7290cddcb8400084eb59b8ebe5fe1b148806c422ac","priv":"645c6babf5d7abdf9a111ce1ef7a860466b73c47d2afc83d5091265dec741fcf","pub":"039d7f9485265190c0986c0ea74c065beefaf0b8a567c2502c122139f4f7d0f834","addr":"9de7c6791416a501bc1b3dfa5940e4ede894bca3"},{"mnemonic":"property grow toilet hollow slogan pioneer gate fresh still notable happy peanut","master":"9e289e0abc03cfab28e00b885be5328d88886a24e71d88c120cfcf697e1573ff","seed":"3deae69499f305108ec27c7ac5e844140b59316a354d08a9571e671d5f71ed8a35e060b084deb4ac2f55c3968184f7b625246c5635e8ae85cb511ed87582a712","priv":"3765a9eaffda6c370a95ca1c2ecd178a5a7799034fed7d051a37f658e1db0fab","pub":"039bbdd61b3e1570f585fe38ef1ff516a4d1ea27c9d9a2b11775f9f462b5e1e764","addr":"c0a75bc9853ea8ff8070b22b5e6b22c57ca2e820"},{"mnemonic":"grape arena buddy shrug foot fiscal move transfer beach else alone city","master":"903560571ef0d4cc0fc20d79ff830f6cd360a1ff387bcd893b436b8d8cc4a4c4","seed":"6b232fcb4175b92836ad60e8cb9bdc82856d663558adad2fd001fb71db4eecc55d0a9b0cb62c938c8e699f0bd55f3e773080cb3804d74e4c7503420b2f0640e6","priv":"b693be937db9f0aafcf2b68b9c3ad8dff86d250f4d7c7ce0bee4fec7cc164035","pub":"034178d1a76406edcea9b3e501aa11161cdd14d6760769cbd0070862148192ed81","addr":"91379f6876f01696ede09b112da349125ae3db9f"},{"mnemonic":"spirit march luxury planet review rhythm mother food orphan inhale dinosaur ginger","master":"88b72d270aaad97e466b4c6cc2d5376e0bd9d5d4389bf1c5e5fe3cd60eda1cdc","seed":"ae53ffbf1695fe13e7590e3c0d225621f392ba5885387cc5ba1ddbdff13f83051293be338369236cd2cefb39682019b257a4766eef632cb2f805c226a611d5c4","priv":"8cd4d3c8a6a6a18eef4b30056d4c23908d100a30566ee7ed486f96831be8657f","pub":"030dbc527c5e03ce3a6ba9caf81c44f0dd0c0b0374617efa819a71319879027fef","addr":"345000ace68ff89bef2f2c197da7f50329c739a9"},{"mnemonic":"cause enact push shove account orchard grunt sausage mosquito deny relief sun","master":"d66d0216c675ef09072623aa75fd8a9df788af3cf26b16d38091ba5ec8cc8cb8","seed":"07d83a41e284788319bc0e5b9b7b1849485b2bdb8cf408843184f09b1dededf8ca56160aff2f6ed2e0559e0c005f5f0dab7b3e36500db5e45c55612091818f60","priv":"bcd7f078131f5644373c0e0ced2f33822c116df476cfab34c39dc9a8d5b9aec2","pub":"026c0d381a709b557135d33bd1760de196b604b5d720269ba4e8d749b7737da2e9","addr":"7e268fec12b43d71998eba89c8e0df3205c094d6"},{"mnemonic":"faint jelly paper blush cute hope project giraffe muffin strike pistol blood","master":"3e2eece9505cdbdd0e44e237a90a023837b45c6305c01802fa278d6690afe9bc","seed":"7ff4975b81e3165068c8b861a748013e93614bd56c4af844080373a3c60d0e763d5c934ed4d4941f195e97eaad4257eb55ef4842d43ae648ebadfb82421d5b7c","priv":"d2e9c0441d876bc0c189a109a564404e00e3a7540cb2f84095da70e38321adc2","pub":"02a49b4d38662800e8aadabc72fc7fd3ff080c9c9aef5cc3c3970d6411ca92d2f3","addr":"b0bfe3ee05d361865a65678fa612cc64ba633789"},{"mnemonic":"jazz ten exchange horn junior frog surface blur color pill bonus science","master":"037073838661b05747c80ed9a91ef9fc07db4f4b9a89c56a26a517d74615a83d","seed":"92333a0fcd8cc74457ded4de145027c19de4d04d4e791c0418092ff599869c5a0f7f585692c0de272362e6ef3a8d31fd793e83701f1aaf41a0355a818ec061d1","priv":"04cb6c660a8006068ae929e97db3b29cf55093f52bb7292d212774db7b6544a9","pub":"034a39172b568cbecfe119e7c751086392e0a6b8c5ffc755453596ed74a75bd1c0","addr":"bde2747790882434b15deea070cd36c696c73bbc"},{"mnemonic":"chair practice neglect hawk panic sponsor ritual bid sick fiction vendor defy","master":"1f908e1559b37dc8ffde2f89ca0dbba2202260f6a848461d75cdc8791f53a1f5","seed":"0fcf390d0c757b52a520a2fc8c30dc740b0c481adf1e17a6e8d445f355c3c266bad1671bcdba99fba9c69e473a294c5e3f6ac51027a1048987cd3dc7a52dd3e8","priv":"6444a8b09434528113de487508dc7e30cd184c3a9f52ce20b30c7b6f40d5a031","pub":"0344d47049e125a655b9dff7de696e72689ee478b8b4f13a0bcdc71df4737689d1","addr":"3ad17b540fa37171f21fb9d4cf6cc061008ce652"},{"mnemonic":"dilemma main solar balcony differ bring close popular couple educate hobby mule","master":"2a9a19b24310a9019114beb8d3222df214ff8eef4ce190e7017bae4e45861092","seed":"ed8bd81a4515d1c43c24d69aca3ceb065d0552b79ad01db75ad19c2af3cd23a6a213163f9db3743d3b2fab6bc166954b2285bead616d1a50f036bf144856e762","priv":"1c8c89946f2dee6c92348f5d82506ddd9065f83b2eb8f8d173cf9642b971a0c4","pub":"02855f225d510b6b0d64fa5abfc9639488358272957b9003b1bc697d474577c45b","addr":"df365a12508a519bdf095aa5979b93acf59681c4"},{"mnemonic":"sudden cattle enough output make code tonight matter reduce enjoy file prison","master":"ab474b0afda779ae957963eb8643db33d1f2d879a5ebc2a79b5d8f2f9946223f","seed":"f732b62445528f4d96e0c95b58c4459e8ab7528d47ec2a925e3f5515e1459c952abbfa40fa5cd7f8b7c2f059e3df2c2a5a3813b4c37e322c9f2c8f55e66ce3cc","priv":"5d5af8bd1921fe03619088250bd74a2a1f58bcac8158230c0cc0e7ad304790e8","pub":"03ce0673f40df25344d5f2d85a374d6d40b6ab5b8bddeb5f9e2adc9120e2242c17","addr":"a9f1d96cfeeeeb011efc76ac43d3d121a2e7195e"},{"mnemonic":"oblige broccoli transfer midnight display talk jazz wall fit harsh kick ahead","master":"b5e760adc086f5be87b58aeabc63d74d018aaf2f673205620685c4ec32776769","seed":"3fd39274348d2cf5ea5ab4239dfa66dc65b33a7f4975b25e334d26b67e32ccb4865599f9b4fddfe8cf8a2630cd5787ef0188371d1563c8b9880b33201bf259a4","priv":"5e9b5b2a5628a5a57510469db849aea45ee2989c929bb1fc06918736f115edf8","pub":"039e5e293c463f16d26fd845e92d4503e551013864e5682e1c28bc21072589baeb","addr":"a784eadc4951c1e92e63a83204473dd467f5d558"},{"mnemonic":"prosper must remove pulse wink rabbit shadow harbor equal twenty air muscle","master":"ad8244b4d4221944b73939b681b275f280e1a8d42fe6583f63740865dc6483bb","seed":"a3258a6176d098bc96dced14718524f05669cc6c9f3ba5680a56c8c80b83bf50f32345843aab72e13df9bd8727408ec114bdc0099902857ff1889bd94a3a1388","priv":"32fde5f62df796263bd40267e1d1573f73d86d2fc98076008a5ea46092f8d01b","pub":"03ac2d243cf6580c8c0bdfc091c8ef1afffca6aede2ba5375e149efd2db54c23f4","addr":"504cf87560e4ccf69ce6f81aa5b0b3af45ec2899"},{"mnemonic":"harbor focus scare envelope slow margin boss giraffe daughter mouse hazard step","master":"28831264a522026221c9739fd286152e1123809699955d06149f34a0157a667c","seed":"bdb6f459beb7d6627a96b920ea39dd34b38b21cf45bafe88b66823c5ff02babd02b40ce25a9ce7b4d04696294910a967858fca74b18a5cb46f8afe294ff8d56c","priv":"4834d0601e457f6903e3dc08b3168411c351ed97df34a0932ba19f7bcecafc4b","pub":"03ba2538c15c37b3e0969adeabb0e5e1d093170f7e352ce0696aeb9e5e36150295","addr":"a259af3663c6ed69b149c94f73dddf22e4c91442"},{"mnemonic":"elite magic excite apology sleep cable refuse carpet ethics fortune assault hazard","master":"384338593c8198935c4bd0ced828784a7a26797b5e68212f7b142d25c5e8bef3","seed":"4ad678a061c1fa3351872cc3451c1410f5506919afce9ed62e5dfb05e9be36471fb80a5a94312ab603ec397cdb8ccf9acf8ce405fe7b834c9b14eddc570d5411","priv":"d07f63e9ed19bf7c7f89a598727dabde42bbe0e4cbdfc0dd889f8b5c4998a023","pub":"03d5199768e4a175f47831e46382232c217d58e94aa99f5cfcf7e85887865d4da9","addr":"427a4855b7d2222cc2d54dccc2de0b225b09c315"},{"mnemonic":"awake robust situate increase salmon tell roof agent grunt wear license kitchen","master":"c30d435feb0cf93a3cebc4584e94e00ff40ee2950cb3053ef2f7832799bab885","seed":"b49401408240429ba30ebfb5d9afd6fb74e79971be6b9f76e3810b83ab1993958f2d9f9fb5b75dee68607a2510ad621968d384873d16b4a194c939ff1358a67b","priv":"def35e61e636973967024d7cf9ee2ab0c232348c70fa25b945d6d4a6f220b9ba","pub":"032255b26a5ab86ade14eb9acd3c97e774aebd710b00e81719d04d7dfaad37251f","addr":"aafe58c581f30d3a55de219c15724e2b26dd2c5b"},{"mnemonic":"host proud little want shoulder guess acoustic spin since slight myth detail","master":"200f4964bac08715f0dc5bc750261c71ab2c5e5b70c6e20bf748aed10c4e6ae2","seed":"3fd02e2249ce332bd4f4bd3d9c0ab61e169d0f0c011a826d072153001c6f093e7fddebc437bfd7b9dd60093686147e069c4ff3806124cfeb02501b807205c47f","priv":"005e6a885009202c44f2dfd911fbd495214b9c53d2305b52c6bd7c1a2efbbb17","pub":"03a99eeec3b673289bf785c9482ee94fd906f992dbc11b6e0624e0c98c6b9ddefc","addr":"57a1472c9d2e1d80bad1e84b1a88356d973cac1f"},{"mnemonic":"chimney organ announce town worth finger donate hint vehicle sniff defense famous","master":"8059f2264cbba67a9868b20e25cd6ea7d5ac2c77a86b5f36b9890560b8ac9d42","seed":"a2317e376ede3b6bfc464a993815e5b32c7e2d896b462a3f636cad9e3837f7b454cfd3ce17e221a5f46a8b38a8eca74f6f1508d376ac9ebdbd92d6603178e8f9","priv":"e8e7e337feed5b08f418d6757b0cebc3cd2e037fddf8ecb51b42c1f71d83bce1","pub":"033ccaccdda15edadbe824e3340c73e27303df9c1e40037d0108bb2dea87e84235","addr":"13ae50b4bb386c1c5360404f5f43a2dfd95e1967"},{"mnemonic":"wolf found absurd device rare desk average water excite ring chest version","master":"5dec910d707536db8776b138103e97ed8a34d75e89d79c3657320ad9bd064d6b","seed":"421737ab059b231f6bac2f012f4472ec7215f94a5c9f5cafeeb43bb03d8b936c39afe6a712530fad6a5e4bac736b7ca12e488b3c377faf58476e9e8fe4897829","priv":"17e9344eade9c62a67b5d72af06616bc455ae6f9aa03dd48432efa2a242356e7","pub":"03776634e0508958ca0a9cf4f15b038f544a4d2d0497674ac7a1deef315d80ba81","addr":"63fde94bb741395136727075993a876ea1e59336"},{"mnemonic":"disorder improve say diamond present elegant evoke latin lonely muffin main resist","master":"e8e118fdfad2b3eaaecb31ccdb8ef3ef04e904c543245766a7bbc365dbe37174","seed":"c32d703d39d06d3c61464db0345ffe546f020678149496ee357acb0e93f9575d39ed2309f46917f89a2a299f1704958806f65404ad80aacb295242a91c0f6a53","priv":"947651ee70f613036de219df6d42b78dd5d1504af999c5c2ac7cccc656f578ce","pub":"02e0ca79766b0cdbe0cca0c4d4647e9d82740a6db151f0ad56df0881a0799e56b5","addr":"dd0179f1d538a9c67a42ca0fbc262edd506842db"},{"mnemonic":"define lion input friend used deny obvious basic fantasy initial grit jaguar","master":"e749606fd4eed5b54a718207b0c44af3dc32dafdc192d6f26744fe02b1cee804","seed":"2f67dd5c538358009d036e68d2205254ef898826613d01617abfdc83deca452603008226dcf4569f3faa21a18ba72e3f22ba0beedfc89888701ea2005be93912","priv":"59321cf870be317e697723d132c9f52b20ab43a84efa0f53d3af3b2e1bb075f9","pub":"02e681a3823e20e1482ae8888dd3fd54bf8b9843c1e480d36e72f6ec8f9311ef7a","addr":"c13389a74d1657b472efdd2fecfe736872952513"},{"mnemonic":"caution unable glue tissue toast august decide leisure foster session position match","master":"a0ae79723ea7b60a8234be8bae9acd64bad5472f789c7b8854d95862ffc441dd","seed":"9e1e3a5e11633be7f211cf442cf66b9350f2f4d84829ebe6da491e7749f2a9e6a3656feb5edd3584b723a9c4edbe1f2f530d4360f55bb1d32abe8a82d7383204","priv":"b2a560b474971b2ed48e47c0a27858b70c4485256ec288849a97be5d5eae26c5","pub":"03fe1ac82b75d9ce75fec2839d343954429207d4ffd7ad0e037c2bfe50d7f8c68f","addr":"85bf34297752337da3c79c124508daeab88faa11"},{"mnemonic":"pull drive tired success sorry raise top ship visual filter tag upon","master":"e5b018ed831659613748160d29f704367c0933b09ee12a8582f36ebac586ae78","seed":"1bcc9ff7923777f97fbcc49e5653ce6a7397668eb7b08aad407c77b5f7ddcc62323d8a566c15b51dd6032a57be69054c1273dd50e2c0698e42595258cdd05e7c","priv":"1a859101a7582121828f09eb02de30f34f6e1cda405cb36fda0279b25e1ffda7","pub":"028e0aafb274dcd1f7f8154bb6f1a6ee6207f69d8d7720c96a0d73e2fb2277f92b","addr":"ef934026abefbf19a96bab8f59b9f048ba4c14a1"},{"mnemonic":"grant enroll monster verb voice bench when certain kingdom nuclear save stem","master":"e8221f0b15c9ec7cac1bf373219481d9952b907ee29914d4506d079ae99ec17d","seed":"158737e586b7d0515efcf931d780a88fe0dbf150133a9f605bfa9c4f0df1b7d1c4f56f9745fe76b51640d45735b91e2a6391e3a53f1200824d58ea8cd9bf25ee","priv":"cb61489db37dc70695fdfd54887dcb61f17ba29925d6267f10999ef088acc11c","pub":"0272502a28dfa3e7ebef4c97ee7ee9817756e84733c1030a94820db6d25c82fb97","addr":"d941f06898ddb082c3f8dcdac5a455ba88be2dab"},{"mnemonic":"shrimp forward swarm olive laundry team fashion run tiger atom guitar blush","master":"e726598bbe78396d7d21a334ad1ddfb95285f72e5c6f015f6d76d7b018a8486f","seed":"7f59fa24106d19a2fc887bfdbd01f1f0c2e037869cdeddc6543354a29952785a31146ae4de6d7ceec9ea95df088dda0f195d491d8be3a6ff63bd427532a1d979","priv":"1bcf9039d65d76bac2b14698585db46cefc7de88f2724118dbf1b0597bea6960","pub":"021b8a68d6c12165a3c11dd81c93edcae4437c983751e8c2a4dc509f2e3bd4d400","addr":"9be822a10983a2c398dd72cb43eab3dcc2ee30f6"},{"mnemonic":"object lava wise decorate donate panther chicken enforce hood donkey lock better","master":"f2e88ff11892f72f22627d7cc7048909ff7403a121a23ebd9744a9017a013adb","seed":"9b7eef532cce30af1499362b675c2b6c3e6333f672c102d41459152f380661115461b1dee3613ee5be55beed081d1655b70d941e819754de304beed5269c5fc9","priv":"e19e47c990399d9bb11760b2b00847fe8b85d7a73c5c4fd99414ac37822b5ed6","pub":"02d0840b212aa20d204c8946877da8d6307b50c890a463a123d7eeaf877811f998","addr":"b85c15ec5abcbbb0991c18fbc788af88ff36e66d"},{"mnemonic":"blade reward angle predict text salad auto drum alert grace valve dove","master":"935ad9d81bdf740c8cec1414d56cba9a807d0d47d39b0d9169027cfa38491fd0","seed":"7888677a5dbd757788a5fa116a954610d3234aed529b85cce2bbc34413db5b7fa4b25ae8d9f4bbe367ac55b0dca61724399f70e5404e346506ea2e5708269639","priv":"a6f5a6d090cfb99f935d72d79e77d00c7eaac00b9d23ac1a4aacd6289fdd4604","pub":"0308cd34578b15b3f459d9c0507830af364ed359f27c1135ec0dce2fb9d256b65a","addr":"f05e198f7feacf7a2fdb37f598137f27dfbfafa3"},{"mnemonic":"icon aunt fiscal day never reflect rapid scatter exist fit prosper what","master":"9bf8057a5a94ecd164969fa719a846494e7fb8f40d6571ff0f021940bdb5567e","seed":"0532364343a12a5b821d7cb9c88317dbf802d8b3f24359b49ff32d79882f89f489a4f1f63e4c52ef1ba92a3789e971d56f056b39cc9b0821b3570ececeee9c3f","priv":"0b204e7b6e74dbf35602dd6914458af9860593d672f3409ceb133e431b3f6cc2","pub":"03d5efdd40e97200646f202db82895e2bbe0c16f2cb29bff1622169787433ffa56","addr":"472be066059dfe1d34abb3564037b0149137ff75"},{"mnemonic":"mass wing office match couch tent tumble rug beach mass october already","master":"1b63074ed73326c5629aa6bb9863f1a3cc2369f50f05aa1281d6b208a787adc5","seed":"8e96902f01dbbb458201370b5524fda040322026f83c8f77bc2e91e843ce6b63581b979f71368038e81aa627e3a10897692c1a215fe27a446ac914f043ff8f75","priv":"bf5a466ca37a2c297ba1ee4ff4ff26d62ff44b98b02a5713fc4b2f7427ce9e99","pub":"02827ec005329241a597b6c7faa5e92a0624179425549777ff922482d2a1f48d04","addr":"67f3445c15a8f34a0a5d374acfabc072c3fdf74b"},{"mnemonic":"lottery skull bleak sand drum domain rice eight card frown world much","master":"8a09b9b68f5f87795c60d6dc08146a2780f410f44560f4519194eb1dc6ed26be","seed":"f2dc56a6fc9f382d54b3d92785724815c9b78866ad586448cd9ca06e59d713dc136f41425b16b28d45ce094d3f817aed13bda99e73659a77c06064a1fc123d07","priv":"09b6ccac9c9109ada552b0982202838b3c1e53a816748176c2a3f6c04681300d","pub":"028211fce683bfffa2067cca19d0e003e9e86a066b40db4e16756723cbb525c042","addr":"9853d04f14981533312e56c75a32f10e98d543f8"},{"mnemonic":"advance poet beach endless idle castle inherit jaguar wife grief frequent wide","master":"c16f77a5a5931add45a26fb906cbffd87c7e5ef3d146b83df93e5a3d5b9ca9ef","seed":"26b3842ad77946bb585a05ef148b8ebde2994c800d30224adc7dc1110a4605c02a6651d30709f5f8c0a532c6976504344887bff1503e6afb6cb8b1ae0f909f66","priv":"58a69857570ddabf8a5454e97655e1a833194b64ec4421befe3e0d9e45ffe97a","pub":"033a877e03d2b871bb879b53196da3ca45459485eb38eac76e938c62979d23a1de","addr":"0bf6320bffe291c8f1c0676ed864232cc84b4e57"},{"mnemonic":"stove tennis wait major grass network mountain before inhale glare bird moon","master":"b1bb7df0cf5b8143e91787646825f92d175664fe68751c114824d5a374850672","seed":"73f5867400033e088b346620983d128294338a0988a8b4282999a2a960a26caa12686db680247520196fa9a1e34901841d999b4fdad40aee63834dab615cdf43","priv":"37af5d2736154cfef5c59e974f1954e541683331de3555976a9e9efffb7c960f","pub":"032c5fdf3604c6ef170e65007bdb75ded577aae6652f099ee41d4ecfd1020cc065","addr":"7ef3d9bcee0b3e3d131fab4dd7f79d6dad548889"},{"mnemonic":"sting nut gasp like spread sponsor march behave zoo vanish noble dirt","master":"9f74f4075e987922ac30b7f5f43bada33f0dd385a4a30a1ff42718fd43f76c93","seed":"4d6e6b8a41454924355067b754e619b663ea585f305482febb6db99d26d62fd1a1a5441b7fa1d02de242f0dd35c965ed62fb0d9bc7a857ba257dec94ce462a9c","priv":"53afc4f00fe2a5003c77e92b4d0837d7c8fc54b4ec1e76e0434ef38aa3712850","pub":"020f710a1596997eb3a95815ef79efb5a7204d3bc5fcff171e067f4c6b3692f5e1","addr":"f41ded9fb4ec7cae1a9e8aaaec7de6309644a2c8"},{"mnemonic":"tent trumpet jungle into loop target myth analyst symbol ask december rural","master":"3a8fc48e8e08afe8b32bc8e9c25ada84feb1b84922ea10135a590927eed2b3be","seed":"7c9d5d2681c85e71d49392aeb0502fee5643e8a6ed60c4b84bcc202a5bada19a99dad7f88e365abb6cce65985117d642ca1ae4733a0863e1cd15fad4edd1e8e0","priv":"56b266ef3f1a45b33ea1465c15dc6ec5779289522c8b2b6588c8cf2c182d2fbe","pub":"0206b8e7a5350358fd35bbf173d9ce5b0ec91ee8c710837b9198b5d5ef327a11e6","addr":"fb059b5167a4fb3bb07c0b3b3516bd6fc84f66c5"},{"mnemonic":"juice barely airport rigid miracle afraid funny combine address guard omit idle","master":"787086d46e0777b03c3774933f35e4fe65b4ff069de5ca9b09cb84caff915ddb","seed":"ed6db1f257a45468761be9dd26ce88f78ed7ed1c488e4affb3a8f8ff8550602848ba2fa284c930cd387188ec4f057c6865964ca93bd181bda40e4059c4fc4d28","priv":"9d6f46f7c329d6e57b2ae84150c23c983bab43e7e6ad7190bc95dbeac977c617","pub":"03ec60e506de8acf2a518ce07e3394421450db339cdb6b91ca52924b1e1c3afe22","addr":"0a4359701fca7026cfb2d196df28e34337a34960"},{"mnemonic":"uniform enter number remove obey arrive print version cake alcohol swallow mistake","master":"047c71cb3066ee3fc151a4dd961a06595d63b393c54e77c756966fbca8a749bb","seed":"3db076729af5e872e92581e3c8d8812b60dbe4ed85a59f034fed43c9c4e0015fc4363643dc8ee5ade53ddf68af54b3d63d6bd79457eba414f45bb0c809e90af7","priv":"557c62286ae6440a2a0b17ea98dbb4992333093a054b59a37345a61de1b871b8","pub":"03ad3f7e2e2279b486c88e7e12d2a97a3860aa31a3854987853a1d73cde6aa734d","addr":"ff0a8d5fca9824e71cdf434cd868c12957fc61c9"},{"mnemonic":"split lecture predict rich inflict flush bike sound credit girl pudding ridge","master":"12fb50c5a687fa1552f07cc9b56d6f5ecb7b68376c3cdae621190494ea279f9e","seed":"29d6e5b0c2cbb22e6048158990f14be89c6c2416b36761c2f4d4de70a3dee2c7f9e86bf6dcfb07e99ac1d15f66f7393fc48b00195b0981f0699652a9f3f0c340","priv":"b02635341dd14b0b5e701222337dce09c3426a6f80370b06dabc31c417d9cd2b","pub":"0365f2fe5611808dd6fcaea62ad335d9b992d1b8f91333d6dc7b96c0b3ac97b209","addr":"ee3da08bcfb0e2fd4331e8b1ea3c0905c6c2f005"},{"mnemonic":"fiscal deer minor dwarf measure goat enrich emerge act view cancel shrug","master":"4cb7b43c2efcc7f6e6d84d5b47ca352ff8aa3c1c44fd8d2de7dc75b3fcb310b5","seed":"f48a89c3f2dc87ad41069c06d0b8751881c993c5895cb548b06974194cb410122d1268a9f962790ca461e875148cba07c216439df21bb37a06600456f5bba35a","priv":"b77f4a13edd7f5ae33725c340b1f8982fd02829ba2756d70f4086dc4a38a5d21","pub":"029844babe3ab249b969895b2b0c6d3cf7a79104721e96ea3b24784a4593fcb7e1","addr":"20a6d611a9ea918d6697d2e09900cf4fc9f676c5"},{"mnemonic":"expect speak gasp outside word glue fluid neutral casual train left mountain","master":"a774f13c1b5a22667ed1d3954ef64f9ddf3f841890b894660bb291745f8c5d23","seed":"7e8078aab4d3b5d121cb17213ee1a06fe4b0ec7d95dbfccab17cd0cae6917151197385c2f75dfecc7221ad518d5899384c22d2641a66250dc581096ff5326a6c","priv":"663b4bbe218e2f6efaa30e02460985ec708e76abd845ca365de83d2bcf547680","pub":"02b78aee27b6c719f89f3f21c55e8c34b9b83e94864c894188a7e39c348622e5c2","addr":"1c716ff8774a14f48623598e80fed3877d974bed"},{"mnemonic":"grace clinic host vehicle drastic april sibling response laptop escape creek neglect","master":"0f2dd943aef0644bf150f38baddc31c3c2a95b813c1fd893ef936f36c6972aec","seed":"e21b62815782f3954ef2be4e9551f7ba47d6f471b566d3b9db6a07d29b42c2edd10e500c7e701ba60963315f21afc2a4ea0d4c187fe4e08f775d3439279572b1","priv":"df825cb149c95352cf0bb17fb8b12cb686ca246c76f7bdfd8ae4633fa18ec30c","pub":"029bb63c2664225dab9c6a93294891127728b77e7d9a9a8e187531f5f154ad36ac","addr":"55266b5a04683c1d61e2cbcf4180d7087550c9f1"},{"mnemonic":"neither help draw cup grief hood swing task okay wasp angle sweet","master":"5a89607cd2cdd7717fc0918d92e661dc7960b5f92a7083482079468afae827db","seed":"8a1d0d7f2799cf70744d682e734352e2330494cc309b2bf785cfe799f004b67c936f3987f75954e18f4eb3adece8e2a3c57ae24b3c8f747884f473cfdb671112","priv":"30a055fcbb2c88fd87963e2ed60117cdf5a82979a7829238f5093f0c27fd7380","pub":"02181e5dacd8408db30a736957d7b19448d5925417e4d38d487391dcdfb8ac4dab","addr":"9ee3469dbceacd60c741f1530646f7550b94be6c"},{"mnemonic":"fall laugh virtual service grit left clip betray wise correct walnut online","master":"7c11681ada91e9349c1e062d0036a29290bcf0bc1564428f7080ee0b81fc5a0c","seed":"c2ab87d2eab816dd1b81ae4acea81e034f2a7cd2cf7103ad3985e739d696248dc0cbc6ff2864e598ae736b58c6ac4f3898f1ddb7eff76413fa1383a63f6c7716","priv":"13edbf55d44ea6951f3825d67c2486a96030bc58ba15d282df4061a0d644a2a0","pub":"0386590dcb32fd11ada507c55069b5607182a1db6ec02c810c79668a27d60411be","addr":"71bdce836bd62d85f5a53f9fcfe2310d40bacc56"},{"mnemonic":"hedgehog light govern fruit season cousin shy tumble maple promote feature lonely","master":"f4575fea61d7539101b4f89674218bf8fb206563cd07d729a834bd7cd8e3cc62","seed":"147de64775c5b285b09b2f846212750577cd9cf77bdc64f198da75003dfbda9c9dc742bf9ef1de8390641ddf9b03db8958cea480e5b4660236e29ef5d2d6a6a1","priv":"9ce717cacb307400d04739f7431fbf02cdaa3ae9035e00e8a31d03d6cf7e193d","pub":"031b6e5958fd3a5883f0cff00cd6dd14ac6cd4d92611e97c4cdd751d76323ffe0c","addr":"775cfbe90a93b73c27172b699506e4b40020a47d"},{"mnemonic":"normal tuna cry human world wonder suit tribe company pink weird unable","master":"834e035154ca70f5719e0df0dea3581a2ea19c4f9c4f7e1348810e0a47eaaf81","seed":"c1682262a9bb26399355c5a226abf198db50fd6891e48afd60094127db569a3306b5e556fc166907a4ef90c80069d9c0027b74532491ca54560f7a85ee1c2934","priv":"035c6aa4e2ae3ca2d2a356112809945b068a21a4c3a448819d8b29ce406423f1","pub":"02a18ee68f4c04f7c9698d484b9e87a672f05ecb87d127746b67f3caa820406285","addr":"b6f3c63322c96f7cd1bc13195acd2a9485b45232"},{"mnemonic":"school kitten swap accuse vivid spirit team verb border write boss barely","master":"b97687333b05ee2da13ce7c5d488aa076a1cd16c8b21f43e38eb0606fa3887cc","seed":"7a770e511a21a4712fbb40f9cfbab467a97e5165e89f70b27dfc8bf5a6a69fcd8658bb6527d0203e93ac549a89dad65068f06e8699cc9748e6448eb8faafa2fd","priv":"de3f7ccc0001822d6320b5ccf27dd38dfdea7ba8fb5c73afe8b6f71982b06eb1","pub":"029d4b9f7e55bc7fa1e84f403a19bcff9eb9a9afb873476b082374e19d3e7c6589","addr":"2cff960c82af319d91e2b1fed8171fe04d47a491"},{"mnemonic":"banner lecture vacuum metal clutch return maid furnace beef armor excuse mother","master":"e944b1515fcab7dd33ccb6c027535d3e4d5db2798809fa6e9317587a1a9f8a07","seed":"6089209e2ba24a756beb9a5946df522adc87d9d98dab2c528d5469bb35ca2da36662d661b0daf50695322dab3578a5bc3cdd918a7097c0a10bca063568abe8a1","priv":"c0b5d1c2ba77450237956cccc68a162c2e32c62e662a0bcbc7e27f2ffa24743a","pub":"02b52a9589c4a631aeee16e8ce808a2c20c63134407bddd7986a517ecd46f6f1c7","addr":"d79746b3b45903cdefbfc4146489ea550bf9361d"},{"mnemonic":"lottery uncover blood that bench peace raccoon define scale fault erupt bean","master":"faee8490c1b9b5e79da43146bf8697b1aac582410ceccf66d1fa54a8b4e8c1aa","seed":"cb558b5816b5a3ec5d63468859b71f9d2b5c4b7ad07bc00e5e4e3dfeceb12fce337cf1acd97af6f5b8d9277cda0197dbac16c9700fd41df33d9d470cdb35e545","priv":"1f77e09b423c423043b8c41b93060c9e795b6b0e05ef0fe75eae4a53abdac019","pub":"022a4a7f860dc1ecb21faa1f827907b01b87a552f8cb0a085af3a6a0758d922390","addr":"7566766fb425c0d00ad475dcdca95e94b17faae6"},{"mnemonic":"bounce someone uniform blush plastic edge bachelor tenant office report lounge brick","master":"8766a5c2858ac393f9e73c6d842184953eb0806304fdcbccc43916ba70ce8924","seed":"cb6a680c6044a9bd171e97e38f4933a86f94a643a398e54ed042cb7d2039e11287876ec24794a0a078398e14cf471ec6357d02c83009eacbc377cf77385834a0","priv":"a5f252e60b69ac73744b617924ea8158b93d4dbdc2cba19db4506b86d413f6cc","pub":"038d3945d243fd90ab18ce1353e36b3c07143dcce74ae9670fc8e0ee12a2fd01a8","addr":"b184c47600390fb017cf60d2b5c89c28f72d64b1"},{"mnemonic":"alley wide siren matrix cigar paddle spin fame receive cave student tree","master":"2cacce92a105ed6a199a6d881ad7a43a7faa74f967b4e8330a55b263102fbd8e","seed":"c67bddd95507e4a9f9153f7da3de4e5951c53750a5842f11192328994742669c32cc61ed14139ddb72365ec7065436583b360ce6e2aee5c196beaab9b10e9991","priv":"f6dc107f30701827bf1f83113ea3853017e384d6995205dc9fd23176e802ef4d","pub":"02c3dc3ea3727f6f351a12d3f5b3fa52beb25ddcb5ec397042aea4e646d9aee6af","addr":"5ef50803371d9c915ddeee096f7131461323c489"},{"mnemonic":"pipe brisk focus nurse rare arrow seek spike guess enough unlock transfer","master":"ad585f1ab0b6e5f8d224fee37b6c3d1fdab1e6c757ea93a9df059a36b3f96646","seed":"5b76d0f7fa0ed23b52ec73d65d109d7026f7cc4c207988c6a003a142f3e6201fb1770f8e662fa8cf4acfc0f23e0620bf2f7b139fa9d8d71e5a3c5b5c2ab75e68","priv":"dfd55ba52a10f26aad26e7532f6631986acb0247fadb1b86c45ff9537924e42c","pub":"036bfbb102ab379a9dea1cc63dba5944b22d48a941a0d1e534170cca9a53d3fb0e","addr":"af337ff42bf6280f7e518df5f4f064a84fe209fe"},{"mnemonic":"coast opinion view orbit knife december pepper elbow boss junior wreck escape","master":"4eecc11aef13009bdfc444037aa185585c147be182442a33459b5a07b61aa555","seed":"f543bbe5ed92b75d06089c2335fd22db68f41e499634760dafaa6661e23178e7d075b2f8aa3630aa528ed77d85737601d041278d182458ae28c04420ddc25b5d","priv":"0fee3e3e025dc742e5a95f41f2e2c84d94bc8cf068bdc67db76e0378c1ff01af","pub":"03e58501a3f5052e4b7b1a4bb264c5f5a61d60c542a761a015606ffbf97f63c10d","addr":"c51fc7f607bb0e1cdba35f503f3e397346148784"},{"mnemonic":"indoor dinner fantasy cup move solve pride dust cross note raw balcony","master":"6346159218b27d00feda5a8fd63349956636147e058d9eafd60bd94bcd18efce","seed":"1c39176421e5c49e7fb6257ae70dd7d1ec60b3e2a1a4523bc4aec59b040708f0e48099520c0ae4de467da994082c82e0db6f1445c159f625559adefa55c7ce8d","priv":"74d7f00b88798ba5190b71e59dcc4bd7f2cb11e93669d7ba0372f4155308b947","pub":"03a07ad498d80dc84ce120f5518a541b5310e50bcbf0c669455c8ce2a0eb13e253","addr":"277346e420f814e9bb1a8ab16b11af318bd78d4a"},{"mnemonic":"please neither sister wrap comfort omit stamp roast lunch steel night report","master":"1f0fb7b99b38b57321f40b4327cc38f7c41c5688a478e4be908353df70477fcc","seed":"6d383d1ab8febb2334354e9e5261d6d4797bee2e6b9242521d59d22f982525ca87141e713b32cd60b6aea587caca213d8e0524c1d55cb209a6d06f607d7b74d2","priv":"95236694952fae12a92d15ca17c54cdfbd234109aadf6c295bf664115cc35a27","pub":"02f29a1a01ba6702e3a441386986ab5ef7227532704cbcfa08f2339c5273fe5f7e","addr":"048f26f774131d92ca52228106fe61d12e7d28c1"},{"mnemonic":"lawsuit trip betray slam tornado polar demise appear east dose produce market","master":"8e659f66e4dcd50dc7ba617e17e4dc45c75fe957b656039a73f3583944b16ac1","seed":"d982fe48080c3bee97fe1ae2ffdc0c5ff2445817d28b30bccd6f89bee138ef1e9828b04fd99cd70512cc8d0e58010ecd7c4460c0b2614211e7ebd8acd27d2061","priv":"4d053df57043c403659a370f486e8ebfd60fa2804430a6b97d95ecfde846d63c","pub":"035001c721d157c1af6dfa4d1de23852ba2d9be1133f30628588c5d9ec890a7662","addr":"bbd41b5af33ef8bd075e93a01f5377d486ddc475"},{"mnemonic":"hen build sand sister borrow victory syrup scrap rack aerobic shoot pole","master":"a4f3bc4a89dd86f38c5908d229f58a57c11f4a3d6872a0fd448043a6a214f938","seed":"3823745cd7589411813362179d13b2d2e1cb65bad1d53f34d512c349215e3cd5bef97ed86faf0096d2cfd5dd75556bdcbac1ac385c9caa9f928a19cb926082e3","priv":"5c14903308d7a83b6570ad2cbcffa3953b458572a72c3d5148a79a494fd90cf5","pub":"03b18bbcb61fe68f733542afa7c4c02214c8980ae4212caf818a8febce1166aeb2","addr":"fd5a9ed68124fee88f30a8d7f19e65e5ee47e681"},{"mnemonic":"chest hard axis own found relax skull bus frown distance gauge angle","master":"6eda34ed25b73c45cc0465aed51577fd35c45ef7e8d8e137c621c5bd6a726888","seed":"fd71ceb91c1c0c2176d7c75ef17010fca12beafc5a54feb3408a69461e1cbf1ad0421da9f31532aeb1f32ee6503899eb0e20fac3756d5c1d9fb23fa2738605c3","priv":"7ee2eab961362c9fb48f0cec5f63d1bfb0b38e819ae3fc1a4a3c6fe6d4d35725","pub":"03131e751282bed411e12a03c7b2ae4ba4c8f81fe5e62f3d40bba09ed7ff099509","addr":"f8a2d049f67222d673df66844d4355ca77a34db5"},{"mnemonic":"large merry tray craft fat clip album company nation tent increase armor","master":"c442b107b26f9c853ef65260fe813449152c2fc93d28774824153cfb4d67e1c2","seed":"bcdce56a81179b6fb0224a34b26583b1d1dc1d24a06bdeae60eb578df673d4d9ab5d8d639c494fcc024a945284be11ff55dd88d2470bb3740b3046155818a7ba","priv":"f359be0bbc26a121997cf2b6678b41c08d6815a5903c184c7743464e287e8557","pub":"032641e977e838507e61d0e85b1a2ff16f0b8d8a351f7958ea615bc2a8723cf1d0","addr":"924690289cc78854d75ddbcb2b06b241404fea7a"},{"mnemonic":"carry pipe make glory famous word shoot artwork ostrich slice blossom episode","master":"f6ad202d1f7acfe41ce8f97c809d0f8ab9c7959866c5a435faa9d551e98d921d","seed":"5b956478a0cf11e9e0bebfd97b3ca56a6cfd8499843d21f95a2ed58db8abb7b06c672e713a556c35258fba0533721cdeb38313565c8edbaedb17dbc1c8396a6b","priv":"0bf855554127bbd03b3779577449c37dfb82ca4457adaa0edf26f1e5e5d7ee27","pub":"03452b2268005ebdce5fb467e4ee5376624cb0dab31704c4725796dc68561b6f92","addr":"ce486d831a5c2e1b95a254c13393e50bea0cea66"},{"mnemonic":"inject more grid coach cause inner ordinary crucial mouse access attitude upgrade","master":"6556ec1bca4ce356846f9ad603e8b2e9a1ced7e2f875bb6330bac32baba3e820","seed":"c5248835bc868983d65e6009b983ec48b262a0da70dc66ba76cb167b9618730ff79b9da8e2321731b55ff63b8cfc8a2b59aa435146b5d2a21b8608bc14808bcb","priv":"3b783218c59cd664b88380619db7a4bfb4b3343fbf38d0a576849c60cb4eae41","pub":"038f88cb7546e49c3dec3d356b0bc70be0716a1b146c641447326aa077d91d055b","addr":"09e570c6a4c7439d6272bfd611dfe723d2fb632b"},{"mnemonic":"viable material flock borrow pear cup barrel fire exclude vintage economy force","master":"ed54a092853793849e78e0c42ef95242414a2dfaffc92d6b7c25efa46715e23a","seed":"013530be872ace250a72aabb73add7e4cc4568da3aac9447c094c49663be2cb6bbdc1fded3bffd41109eb14cf1e8ee48aa65da60166962aff17451bc86dc9bf9","priv":"669218899eadcca8823c6c10476cd25fe546f918495590051f8d45debeae3cf4","pub":"03f54a4a58259314bea899e9f6126305d13afc7e8de6b346e95934358b524a5b4b","addr":"b38f1873c88ab12cb5c839ab1e70639538b331a5"},{"mnemonic":"injury expose attend toward air brain carry neither amazing symptom number name","master":"769158e4432add662ca03b558828568f25369b5fff971076f7a303b8c89bb3f6","seed":"827d52b757b28ecee8ddbc402de54ed6911dfdf19abd00739766f70fb688f47575da03177ce2610263013c2d22e3ca7556c5aa134f74b8faf61dcfba1a4d5ee9","priv":"2d276c19d260ba43e8de8e4b982bb21e16f52b5c8e231cfb6bf71901a9137c62","pub":"0310fe6ba12f805a118c9052ba2cd3218418217e1e48da3daa5887bed6b2fe9bbf","addr":"0ca37f96efe4af7507cf85213a2aecd7dddfb51b"},{"mnemonic":"seat other color road pulse melody error hire scene lamp best analyst","master":"c4e172dcd2a54bbfd30fdea8363eb10b9f0bbdd0d1ff3d33ad3eb01e820d417b","seed":"32d43e6b794040093d6348fc46a452a8733e49a66a06cc8ed2045359c881630531e282ddd70a4d630a3ee69821764b45ab949650d4276a925cad0c3121c31074","priv":"828b3cddb3d902d31386264f84bc54d3574325f56df7d4e8e06b2145d60a0de1","pub":"0275e251466e97a728d0ab4527e04031e315de4d03d9cee50b5b52210fb697a9a9","addr":"c0e6ac260e64b92beed9f4370cb006e2697dea6b"},{"mnemonic":"tonight nature salute state carpet sad zero heart limit skill vehicle elephant","master":"7f116fc76af767fab661d90b8ce20b51cf5d0727ece353410e06409d79ebaea3","seed":"226457053ec313b3368e877c76f9f8a2cd5a7dbde6cfe91de075974f42f994d195f056d20802fef8bef78cdd49c6383e95933eb2517cde2bf353872a13d87da7","priv":"1f069518222310563fa736833f06041805cc0a9ada1ab2b704e85ad91b980ef5","pub":"0221fd13bb9d0177d081c7cc6b9012b0494ccc42ed79ffdcb2409c252f42b66b9f","addr":"401f8cd411f3c5475482430cd0c480ed383e8455"},{"mnemonic":"window awesome survey swear neutral tackle essence elephant weird emerge gesture click","master":"ffb27c19b7d6241a29a08c54605f0408d7de2af078a3eabde97ba6e973b9c31a","seed":"29aaedc60b8cdaeb799707830413942cac78b57c0fa1a4cae0542411a81efeb36d7e48e222f90b6d42bcae97202772d687c226a13143a9541b0d7a3bf7dbe600","priv":"68ab3dca6b53b32bfe8a1b2d428332415b6278cd258fecd927f9d8b371075789","pub":"0234cb69b2f76362ff4ff138f81499d5c2e0a1912fa47098c0d826f98f1be4facb","addr":"54637f8b0f2dad74bb46e7745d1957bb8b16f4fd"},{"mnemonic":"island pact measure trigger frost flee tape napkin wide kick select sense","master":"013a5ecc8a93bac063e18e79f5654cf0881e8c39fa43c467a8aad833b6a7ea76","seed":"19cee1ab2babcd2cc5cb4bc34acb350deaf24b997d603814a5509374a2f60ba133f498a20a9066cba31b4903a6c9da661dd459343004f69b2dc78ded2dde67d5","priv":"16b0960d535046bc5b95e335cd0326d0b0a902a3c81f70490453f75154a05e8a","pub":"03e6198bef79e7bbe034d1786e47f00fd53aa3132318ed99fef38b6f46bbdd9109","addr":"199fb6c909420f711c3b452df497d03da191911c"},{"mnemonic":"before shed sweet will sunset rapid color tattoo winter foil spring orchard","master":"29289b59bf6ad91e0f9b24900803f57d08b45194782e76102f5377c142c17f65","seed":"7b721e94ae18b7666bf293bdb8eaffd70c6bbd2c2ddc582a0939100f1f131009752be6759491e0006cfc424f88efd97868132fa2e6bee0b05a520c881c632951","priv":"f6d7fbb1fa8957d132b1d43414b0664cbc25020055c35635a5ae005e86e40767","pub":"0368c1403ed0df7c1f9faa90fcd60937094cc975d1ab5bc7a9eb03bdfe764dcb7e","addr":"6657bcebfa3816af66b1a0a92f8269cd3f515fe3"},{"mnemonic":"view forget toss steel right echo life candy fine unhappy document pulp","master":"5c6355a65617952bc05b16623992e81daf07695ee5cd3d9bb2b8fa600ffb2576","seed":"20909264d02b6b88a472678b6d457850ce4f67a228a4f6ad7f45be104029ecb68f25075f30680416e0e43469452ad903a1e7b0486932d0dea4b1c5f56b21406f","priv":"4495c90b188f706dbe1106966e49745c49676e5c54f78176eac166629a4c0815","pub":"03b828ccb3f9f1766cf1d1c1c57e8e5c9c96936adbcac4a8ea47b0a7e3139c5771","addr":"4a382d15c13a06adbf075cd847ae9e80dbdf4ca3"},{"mnemonic":"fetch planet injury lecture myth goat drill sea reflect tattoo story rival","master":"3725eab28e9f4275bf2dd2dd5a94aa550688b8d111798185383a58088d6f8b56","seed":"0d42a4096e20202bcaa4d1939ce86cc6975092d2e6081c149b374f3dbd6cda81188c442e1cc7b67032fee9effda37e20da0d809f0d969977ad2c547e9a075224","priv":"7abbbf9aa4375ec489d3ad3ef6041e9e371f4582eec1ed753f9d7de3b4fcb57a","pub":"0371b9cf4994f36ac2b5117a2daf84d7c072f63e51d9f7c5e547548bc2ce51a16f","addr":"d59315e071460c09d108bfa31e05cf37545b19d6"},{"mnemonic":"close raw empty danger educate metal vendor coil observe response scene army","master":"da1ffa0441ba19153f0f98af4092dbe68eb5ffc9d82823710dde6654684e8fec","seed":"f8ea358ea3a369cf72266a1f30e10c445817766080ba50991a2b10ae1f23d1fd3681ffd4cf4a7ac47b39ee9b04ea246cbf5337eb33e0d6e7c1da921d153e2cfa","priv":"5e3f256a55dbfbf2750e56067779fbc05503bea90e1a999c17a0bc27801a0bbb","pub":"02329640a5fbee753825fc310c06f9761cedfefb880d6e3dfb67eecc68ee269813","addr":"904c7b3d1cd8303fc3c8b0e3b0fd60fcb54807b7"},{"mnemonic":"ship puppy grab also merit doctor fine east venue resist loyal radar","master":"f7e49c26a890aa8deb888da48d82935a69730bfa0af67783b39d209ca803de9c","seed":"dd5c5df895a6663cea37b5e7c58c268420e290e4f20d7e0b7c98defa35fde4d372f52215b52bb2745481b8c63aa08c2ba163dd89f2a9e51a3bc92199be8d57ef","priv":"19a311da10e6f11ea3c91231a7e5bd22097701bb56c0248014958e6df186e596","pub":"023acf91dfb359e537f9183080ccd67f65b1b9efe314f682deebcbf718454d6bd4","addr":"618fb20184dd651d18d2e039ac0fa43e53feff61"},{"mnemonic":"beef hen spring repeat define hurry slab midnight liar either arch original","master":"85a6a3be23cc74b32c40f1dbe431584f8767f4116a98ace1a08c934956e8582e","seed":"cbe260dd75a3f8e7b7b9588f0a1325dd88b839a5536e39facf324cbbee3ae951903e2c17370ef673c770ff2e0fc3f1975a26f45d27c681a143f0e60fac8d18c8","priv":"42c6ccd133fbb7d3bd8bde8309f8202eb155c46829aaa558226b6e53abdb203e","pub":"02d1bd732a69043343e72e22432f7bc309e25e96d49b087572f021996297abba75","addr":"9eab0f06ec4e0a8058e4fde3ebd5a1b2f5ab043d"},{"mnemonic":"lend total guess ski divide diesel tumble heavy slight expose clump park","master":"6ad684d3e30778a46d5af816c3deaeaa0af5c4fc04cd74045dd80947faba053c","seed":"d63dd68a0b8296a41ff8698494d9823d18b4700b0564318f022b1bca641a8fd622ca403b48fb835c848f053557cb91fe4290f37ea9edc4f2428226983802e1cb","priv":"9625f841a7384f3fb64c643ee715ab0c5693d60132c4c9838c7f41e1c9163e1f","pub":"035e82a39dd7b61ad9f79ae31b0694af43378fe1b5cd6fa824ad2427da0834e00f","addr":"b88aca334f2bfafdb66c2e338a7d3b6c8be8bdcb"},{"mnemonic":"toss hand crystal buffalo during more laundry fantasy give dizzy bench want","master":"075697aef6de8c5b0b418fb3faa6038442349ded65421ae1089517423120ffac","seed":"4226da530678cd25633e2f87951c6f8f5bb4e3dda3172494dbc03ea15795b22d1042ba8265d67cfeddbc205b800ba7b7b05ed231845ad54cb3224c7ad0f9d8fe","priv":"8db99c4eb921431ead557ec1fc62bd6a9bc34eabb3516345a46bfe8c6106be6c","pub":"029eee00e90a02beca7c3813af59feaec320d26b585e5620de11efdc09a06d2c5d","addr":"e9a4a29d0e7267016b03bd23d6cc78b9eb1681be"},{"mnemonic":"camera gate trick sphere oven sick promote apology reason fiction item meadow","master":"7af52d41d0e35f2cad60fa2fb6c13d046f8aa4e0be104251dee489edce66a229","seed":"16ce2107f57bc5feff86b9dc81c98838cfb7b6274e835d6e35a46525d5870fd84c74cb528f6e2b87b0cef21bc6931793f472e5430b9582f036630c3b7c66df87","priv":"5f428e529d340883faceda659fdb36193f3cedbe2307dc4b8bee55a6845b9068","pub":"02c71ec0f9fc74db1da6d2a4a9d6a7f24980fa17e656c1d7f43a845a17625b2445","addr":"31dd6642a6d913d82b06c3793ae678670ea9bef1"},{"mnemonic":"slim guilt leader segment actor sick debate enough what rate fork rebuild","master":"674b90a421dab99750e982cd3c693668c45d7a39377cb82e3887552f047eadf8","seed":"115114f315f7af942dea64857c5bfe6a22c80031e6b1dd0c19a42a28526c0b9995b0eb39bf8e78ce849559eebdfa3c269783987bd4fd926e776984396a3c604e","priv":"2fdb1afdc8248d6afc69e387a698ef467dc0473323203445bf1dd5aaf5789936","pub":"03dd070062a8c3e65333572beea40f434d6f1b68e528ffefdfa8dd3d8b4c5a729c","addr":"8938c102cfbb8030cf69c660b04fee696a902f96"},{"mnemonic":"kind prefer arrow industry arrive cherry pupil arena strong tuition wide grunt","master":"c4b509d9b1e60d97cb8b862b96a2dfbf960b0553f0625af7430abd3951c59b2a","seed":"85ce840ce0f6625294d32cbd5f68b3c2abc3151db02b5a84b1d78ebd7c05ab24bd49a519a340cd19bdce6aee845ce59b6b5d2efd7a2b1640c7919177bed27b4f","priv":"ba8628565338b55d2a79b21fb9e47da978611095abcef86f305a0e2988e8128d","pub":"02bbbb0be37e3975749a095a9dcc025bd57368eee362cb896540c0dbebba42f0b9","addr":"4d8e97ff30d95baeb64ced528ab999c72aa4cbe1"},{"mnemonic":"slight bronze prevent civil junk van female movie vibrant soon grain suggest","master":"4d07291eea03d51cf9a3790ab0a77ebef383f2cdf184b0ebd872fdce93b0b889","seed":"4f770292818429f588226c4df9bf6053024a42f11a2499f0c2c5ce56f25d16489a2e554b99105c70fa57657b8d8b724d1879fabdfeea8aa43421d19849a0fad0","priv":"bc6ab78b16b831178cd9f2722bb8afb27664d1967cde464af0b951c3aea935b6","pub":"02673643c7fd4c12f47007a27a56537d152d607225a6d561fd0e18d30064752e38","addr":"3cd7ea7b1daecd3efdd14826508409791d8ce865"},{"mnemonic":"chief drill utility gauge tired alien bid deliver tooth amused busy run","master":"dbf20f3b945820a74898fd73218ed84a61ccbbb28d815d26dea7a7e9a9b0b430","seed":"93d2bcfeea8a87f021002ffadc33b664810eb8ed60342c8dd74a937cee64877d5823c45a4d34dddfb7d4381addeeff63e80a191b92dd7f1b4f0dbf5c5e8006a4","priv":"c38542f0dd692e74e8635dd784fe14d8c70ba931c354d6ea08f1e0b9080d74dc","pub":"0225dfa0e7d37e8903213d8d4900a2e56107e7dd02c66cdb7f86e9d9c0a05a835f","addr":"a94ac8358eca1fdb0ab8ded1cd80b492dda39dd6"},{"mnemonic":"large endless art unusual tornado loan planet excuse dolphin million reduce chair","master":"8f029c13f62099a1d280224f9af2d9458014903b3df1eb65647507e4a5262012","seed":"03d076444f817fb054603f746350c40c0551c3d155ded436620451c4f53ad1254d0b52bb0592197becf9e1fa14bdc65d04c7ab9c5bba7737841d800cb4f7c869","priv":"1cf63efe6800cfee972815f1fd71c68224594557d7894fe8902f56b40163ecd1","pub":"03cab792d05c87c205acd8d78771692507eab35d8c7bf729e2d36551ee0c7aac67","addr":"9f27d874704a788d3e3c3f63f9f1a42c27b83c18"},{"mnemonic":"recycle wine system erosion train make sting talent beauty decide beach pigeon","master":"d702a0785f59e080e2ec13280ec397e3af1c60a36bbf2c92c252da896caa7371","seed":"ffd0dd43668393be9b0949bb5872279ebd606be9ad58f8611ece8dd8b408c0714d5435c771ec87d23b83952af75a6853d94fb0ae88a9b9c1b506e3c0887f3bd6","priv":"d27a5cc824bc9e78ed2c991b8ca86498ed48775aec94dc79332057f2a36536db","pub":"02f85cda3ef9d19e68c4a3778ad99fe008904aa9a80c4dfa8d07355ffc840249a2","addr":"da42d3051e6dc70d85b5fa901e1a4c55ee12a47c"},{"mnemonic":"solve snake loyal grape island deputy monkey art pet candy enhance truck","master":"e866de4a10e7067fc8f6462938f3ea5fa7c88c93e2f630ca81dd07361c646fa6","seed":"82483d5e61c9eb2b0c588b438e24cb0a24922abc6cf0571cf3680474f1eb31496e387ae1c017d5a817c88e48020c5cc1298cfbd78d7175be0a1ebdfbf94853f9","priv":"919e4b231311f40772a47f03948b136879c13f5f0797c939e703b7082d65e637","pub":"0227c29a984f46d5a99c08f31355c3471eea9d231ad414286a25fb91bd8a3a6f92","addr":"e1ef4d05f41df82d47c287ad0347197e8deee0d6"},{"mnemonic":"energy buzz square deliver jaguar chapter analyst chat rare over bottom river","master":"3074c2d8f092896e7a197abaf388828f95eccde75986fd280c9b098586e18396","seed":"70be3c734ae665956abefaa3f94101b5863086c14d8c17ab288a3586bb69aadea314ff47dd19a4dd4295ecdab627a34d9bd56231180b20156b65660082e70d35","priv":"47ed2e3406d068624039f71e17f949c4b7865f4c8d006d6b4a635176b700bf2e","pub":"03786b91b237ba9c1c209d8386ab1fef86e0c667cf2a9a3cb25fbe06927ba3214e","addr":"67ba9f0de66103c6d6f1b799564ec38d4eb9f708"},{"mnemonic":"document move actress food guilt fence govern adjust supreme upon stay sibling","master":"6d110c56993597b6bd473eae083493e1a17b4cb971999b078e4c74c2a675f0d7","seed":"e6a300fc434aca28cb75f2113a8f7788778f2b9398290f82f8e5d989bd002659a645c18057ba64807f0d4ae3c064e56a2947d5aaeb83ff3c593e942fdd0542a3","priv":"fbf0d5b6e019bf7aa6745c4d95c0f9a428d0dd57b7af9e71eb2e39a6628b8d86","pub":"03725d6b7196d57cf1d3b193f1a6661613d02912981225beddd4e1db8de60682bb","addr":"9aad1b39fb3cd3fdef63130bb1a7c8d12bdcd866"},{"mnemonic":"express birth sweet kit special board rose sound place chimney awkward injury","master":"c60b7e5a1c89797d3ba7ce33ba487182144b4203379c04e51ec7ef4ee621f0f5","seed":"48274a66272c61abcdb72d36f16b6ae8a1853d299d9514516374096b443368656ec28f59c9f78f6707d1d1fd78c4aee00e046cbd3df66ee7b143b60e262ce162","priv":"972cf1431308c25e45efc26b86a87c85ade411bf3fe1cb6e88143684910dee6b","pub":"0243447732d68ec3287f154750f1b27df3ade846a0d4cda8e5e5f62f3875de6b86","addr":"c199f50b3c111205cc2c7309c9239393bc2c1e57"},{"mnemonic":"future desk scorpion enlist confirm favorite ill expire evidence cushion rapid staff","master":"0f15c9b1f3210c53c5c408329c3c028211660eaac42f27749a4e8901ee17dff5","seed":"c2db1a2615fb9b849717825a326e5bc2ffb8941755a529cf27903c0c3be806b4261cc3ed7afa8748d87d1ccdd36372fa02f92316f1adc28a354feeda7a0edaf0","priv":"39de89d88ac3f8b23ec57f82c83f9bf12a32762c2df4a612ad647ac9ba287c93","pub":"031abd39702f34958e3366a4d438a7285bb9d5ad5b8a29071ddf77ccea7f9c4358","addr":"a7bd49b9e2804e22072b1f336578334c53b6755a"},{"mnemonic":"interest judge only feel scissors illness quiz goddess transfer person position this","master":"f60677c75a51c5c9e8ebc4fc1320dbbc82e00a42507af218a71812d6f981344c","seed":"6e431ec0f7627bceab5dedf9165968ebfb03ca749aa8d021725338ca8e0e8ab3b00cd0395a68ab955068046c63daea7ba57117ebf7c99b242df8e63d01bfa625","priv":"41af5034dc87e11bb1cca3cca70f80fa057a5839b711927d3fab85048ff8620e","pub":"0321c6b392ae7a49201d0a7c89fc3541bf1c0c1287c051c405cf32a246df97c231","addr":"a71580dfa7773d8a2ce44c7dbbf03d285b46e56f"},{"mnemonic":"foil remember sample infant bread year evoke laptop buzz chuckle voyage gentle","master":"88ba5191913e778f76cbc28850f221e96f380724d29646f7cfd4fb6da20171c8","seed":"64485dc0ccee0c0b13c0bc76e44f8c3a26070a6c08fec558519503ed85769ce3f858978cdcd630b9c017a290ae4a7bdbeb0f66fa5e3fdf3ea227187a165ca654","priv":"117e2b0842cf25a1ee21eb2f244a2c1fcf2a3a6946b3b830707f7c96057616a9","pub":"02b349892030c73203e3fbadf870e1c8325ad0ba1747738706734f7a66e9c66ba7","addr":"1f6488347a7155806da3103c9a82954072a1abb7"},{"mnemonic":"pony super panther surround glow lounge kidney increase actual tray bulb device","master":"54c50d2520ae7023ffdd39740b46d029ae9e31211349193fef33cdaf373030a2","seed":"3d11ec99f173c1864ca6638a27554549c3f619a86e0099e5957972722b2937f5db767d86f5fa0c6b3e0a81d75a9aac5786cbf01f2245b51c9202cd4b4ea88a99","priv":"81741675b625a14760a1ee9e108a9ec6be183c480df05878cb31b45e0d0babcf","pub":"02b0bbfc4e33a79bec82682552fb4c0506528d121ef67a7a42d2ee26bd0b1661ae","addr":"8ec9b249788a123e1301100da2db3db71c913a78"},{"mnemonic":"achieve sail manual vibrant unhappy ripple aisle fossil pledge wrong cherry trim","master":"ca9ac46762b80571c25c2a9a6690181896f86ab3f728b4e372552fc9cf1f7e7a","seed":"4c1cf0279c8a29b8077b5797b6592397112b65e75e91b829a0a9f26b94803a53a02069ef774e7cb5c3cbb0a8e074c69b9afc5a4136e04913403b70046759471a","priv":"09503bd2da16f128b857cfc635cd90064446130c2477004a3870a0c5b1f1febe","pub":"022b34a4abc0a4288805719d72f0b64c3118d924d09a4dad4f26d39ed056349e00","addr":"ef2b6bfbe737261b45e770b5eb42d1950c556282"},{"mnemonic":"injury love grit wait junk bridge myself sister hidden dilemma gas paper","master":"b4781c7979c0b72d0c50c9889432fe2a54d6f08a4101778f88176dc661bb02a1","seed":"03bd824d7f4487af26d236950a69eef9c878361038f0e8be44145e558779d4accd58a8c5550bf5ea86ad169e5258947512c4b72f94bdf60b9135c28a4c779541","priv":"68354a2599b3be8ec6dd827b35290d9dfc068c267f1d89dd57851b22d69c95ea","pub":"028af1d826d45a920dcfcca8d9f86dad10d7356b3027d4051dd4c46ddaf32dc623","addr":"1f356a55f3d3fa48e5d5b36fa31f738bc8f83de3"},{"mnemonic":"domain congress cake cradle express despair devote swing meadow piece border cross","master":"a3ebb93b7fb0fac2b02408c0491f66800c220c7d47190c3c97023f3d6db86555","seed":"15494e78dec34f3fb759000cb0584e42addd40f1794bf2932c6bcbbba20e40a381bb9bc1b8dfd3a231d8e249aa3d51a257590a93188fbf116eed9321195a2267","priv":"1f1ae70c46a36ba70674c7b17e6cf0b8e08bda0a17473d8ae69bc54311239821","pub":"03d7d916b054c003413ac84402e59b976e5515f48bbc30ff8cb6bca7f4ee92c03e","addr":"54d0f98b9dad14550c844bbfce8a4031dd677a1a"},{"mnemonic":"pistol news assist poverty squirrel machine aisle sausage harbor garage truck type","master":"581d692fafd753f080fb83318856ccbf059b74a3f26ba22d4b93916e2165aec6","seed":"49abafbfd7b0c65ccf2e22eff01c78245c764d8ba7bd468fe1baf62a156aaa0a6af143c624241ac753ff8432712ea58f1df9e75cd969f905bea80c15b5fd84bf","priv":"f1d7e572b03a08cdf0ce00908c701053a5804fe566168436b90efd1302bd7f1b","pub":"03882ef7180679169f638a7da20a2b522c948b1979802cf4df83fe1b62581e4d4b","addr":"40bbf61a5ea5b704d02ae13d032f3dff4e597ba3"},{"mnemonic":"field tree license quality chase certain hedgehog alarm melt elbow screen pigeon","master":"dc22c189c264812f22664d39ea1fa2f7d986b981d59f1df2ec6f8582d640e196","seed":"37ab0888876ccb32b9ab73f144ba2a352b31b27fcf6b7f8fcc5a2d4802e7099a199242cd5f7f2a3c3a7d86e8c1abd871ca35881a6a47f605d04a063b589fb0b7","priv":"f82f484f92d1719d3e6832d49bbd493d5f7191acbc07872b345385c32f2d38ff","pub":"0390c62a3315cd02fa64216cfbcc1788d537818eab5cf932a24f9eafe6f4031f48","addr":"8933e5a789211fe61396f29fbc55be6ac7031550"},{"mnemonic":"wish vintage fiction false gap bonus abandon cloth usage hurry toss slender","master":"27f3a0c1791709a32f8ac4fc1e9c71eb24c06e2fcdd8dc959940cc1c8655a5ee","seed":"36932e48e1712c3d03261d432a17e940f1f21d730a3f22d37c1834ca0591b71b438d684c926ebdd51e6431502b8efba8e9c32cf457e68b71079864dcd0d1886a","priv":"bc0037a14a0297d3dd969b365a6d8dde9c6397dd3c8aeba6d701dfb1bc8b24f8","pub":"035ec8335e2f6ef0fa2dc6be7f3271b1117545ab02cf1c8cced03f9cfaaef7c602","addr":"5f64f8eccae09dd614ff9f7224a20eaad60c23d5"},{"mnemonic":"fatal strong idle grief present photo aware various april april card village","master":"ae83fc216ef4c81e2d128d90e91cba0b475be472d95ba77c2ab9cecaa511e308","seed":"3901e5518ac7cf29a42b94de334dc641e1db3b97b44a30d69f3865c050fdac8339dece5f9ed96a17e669d51d59ce856db902e918497ea8523e5ba49fbd06f621","priv":"1bef5a9ab2f2ebb16d9d08b958317a37f252f3de91a70b2c8b5b5ddc0a187ab5","pub":"0250e5876c37987b4189513c7a5dacb31a308c563bd09d7557f2584a3c86bc9d5d","addr":"bb82bd68b31663a75d0d007646e8575934991f43"},{"mnemonic":"error monkey argue fluid afraid hand cactus sand misery close laugh comfort","master":"1b4ea203fb592e2dad7f40b6cd4c8ab53c6a0a7656cb674f9e22d6a0e4e84efc","seed":"3c0544c9b9c32165fcaf9445e49518f8d0a2dc6ad672a01a15183ce1e2188f6fac026cebec0ac4ca58906d5599d781c18b2cd77d32992be9cfb01441d396faab","priv":"e0d0b452b3e1f760762f1bdc692225e7b14277d8227d619bda49bcc608658bb2","pub":"02e7a7156cd53cc7c8b4840772854e25b8c6c532c520770883da9d574c86551c7c","addr":"696d7a61a2ab18eb503cd724f0dd316340f96c90"},{"mnemonic":"demise know punch page upgrade gun smooth fruit machine long nominee radio","master":"b36ae5062ebe21f31bebf7b2078ec651ec579494eb764bedda7169095b73fce8","seed":"0f71fa966c1a56c3e11c54798052789cb0f450761a0227336ac50dc8206f032133937511e93fffd54103132d822b8e717ef15fcd4e68f391a398f14cc795cd76","priv":"6b9a3d2e63d666909216a0420709f127318f809549df2e99869fa70956e41dda","pub":"02d72eca95feaccd5a78567311e882d7b5eb2914d1d844e639b03c4cfa036155ab","addr":"9465a8f3afcc348d661bc198cf8220e74faa5895"},{"mnemonic":"install lawsuit guilt myself arena enable unable thumb domain lift feel object","master":"c033a48b64aff8d6c7fcabfab52087c0f7b9a4228837a7a21d8156358e5eb529","seed":"8075fb6cd8bfcc08f1678c005e9d2d0bcac710a6a62cfea46a1ccbf81747362a0e6a25cea2fa958fd320205e0f95eb8a5884c6f39cc3ad17d58fe49e43feb513","priv":"24e83fd857d2a0ef62052625d84e6aa37e96b14f2c8dbe5294107b647b369a7c","pub":"02d95869834be368c5bc37a45153135a1c4f003be6a44bb9af89e55485118826b7","addr":"631e72e50070f34e23ddd155ca0670c8c8db49d8"},{"mnemonic":"antique insect develop sheriff erosion appear easy fog kind apology stamp noodle","master":"72baea3e04811ee7447249a1140ba62e56bf473d5298b610235ec3178b388692","seed":"e751bd7ff01706f38b8d3a28ef3b1565f20a8ad221d521176347e7791d2cbcb9cecfbc8b51c2e36c303be55df280273711d94c416dd74a7e7a18ae52520cf89e","priv":"0ec2ef082498bbbf0a0686fd232a3b4bec66d867cca50bd0cb0e3221bc9223ad","pub":"03952fb023bb76ea74a6b5b9c4a035b193553a8adc1c0774f7ce4976ee2e8c7fae","addr":"9d63d52c57fd76c7036b882ed40f4a6714164c27"},{"mnemonic":"become tell dentist play light illegal work animal library dragon now gallery","master":"895a420763a2dd6fb934ef8d83762051b00235a83f621f57377a0d63b71bd43e","seed":"05975302d82f413289a1679cf6a69feaf8be733d7fd10deafe1470a08ed5796bfec454adde87e825ea80ff05586c12f5d0de69478cf72238b3e73851f691a3ed","priv":"f94266abb2a93d963a2505da57d66c36d37ea3f871654a0e4221ec911a6b507b","pub":"0256fe9203bb64e250fb0e68a7cd3b0d3c90cfa8f8db06c74524c63ebd66098ea2","addr":"4f73259b06b65db4afde238bf4b42a801178d92d"},{"mnemonic":"average anchor total witness carpet myth life admit gesture inject sustain valid","master":"aa36181d7a04a32433e6f4b1e4830d3e0796ea00b8b03d466087911931c16abc","seed":"e2bf601f15b7edaa2176e6a0e734c72f99ea63086ac463ba2dc317dd70466753fd1334cd27e28c382c99179db6a5b00003124f93a7a93da3a0018838b3b04595","priv":"235e293ad68581b4e24a554704eab59caf513b60b8af6b15fa5d8cfe4265e44b","pub":"03b9e9b4b67e3bd6500e6b0c3f0d0f69a15d0824f236553f7fa12a58111e5aee7e","addr":"3733ba0b6386f7534c7714e9e2382675e0dff54e"},{"mnemonic":"liberty cradle play vague cute borrow around that tongue wave solution share","master":"87869b74fcb6e5d4b0b5c5d53679737f275396d63cfceb1133e49458c9c74613","seed":"c60ac4201963706912996e289e5b6d886693f7277875b46ea166f4506bfc3a2652ae2fe5b466bc171c7c7f09f2920b8ecc6d9c7d2e0ba1ca2cb10b528119cfa8","priv":"a8cf8fb93cdc5c13402976952ddf2ba5c2b37d5756861536df21d02eb7d2c593","pub":"03c12a9f6ffe4d7b01364f266b835be4eda6515d601bd39399f6577c53b1289e12","addr":"cf72bf854dfe493a6c742d6941a4f22fbdabae1a"},{"mnemonic":"hip dose artefact tumble keen favorite truly stand accuse spin opera wire","master":"94ade552d985f2e8625e18360914a5046ad14b6cc5fa6abb4ada333de8973595","seed":"c1d9d325396486e588972df5ed2a281a1cef82184a90c7ed7ff1334e35ae92a15cbaec6d27c47742a28dd458474980dabcbc651d6a2eadcb97dcca08f295359c","priv":"9d3f309f684c2c61a0f05fc88e27894cfec51b738058bdb246f1a9fc65937fbe","pub":"02c1da3c5abf3dc4b52336b362614a1a7a24853759f72fae971b43940500badf86","addr":"cb143b40309bc078f3db3e24009ab54ec4741b9f"},{"mnemonic":"history team sight sibling art over pulse network sausage garbage october slogan","master":"2eacb1cbf92401aa2996b19c77a2f110faa835203cc6baa1c98204ad1740963f","seed":"70b0ab283cce0e7735ec8d05bad6178bbe5a19b747ca1d5d3f5a29c83fb634b43c39f621b11210a7d89ec988b94588b9d8b8f2f4c2a9ccb687cb807e230403ea","priv":"986837f4c2853f751c51e09e514d2d40b36d3995e9561b451474cec6ce431a5b","pub":"035ed85029803a151586b8b3da3f7b2208b257738dc43fd1af08c6f76798e82609","addr":"931b1e70776f50c1186cecec2dc8fcc917974e00"},{"mnemonic":"labor area outside toddler street now same obvious demise mammal puppy boost","master":"720c9f77cdac069406469500511e891b35f1a5782ed330f31ad1dde4bbdfe7e7","seed":"ddce9ca2ae36975072a321de56c51a6ba88b53c226d66006b81d4572af6c8c39303a5a8d56b1626510ad730d578105ee84ac079538118f9cf8e56b43e9da71e3","priv":"8182fafb8ffddf9b157f5a072e57d778e766f7fe5b1bf58ff6cf6bcef46e1d32","pub":"03399e5ef2e4a978be70fe20b7d44201b5130894588033d89e1c0b891576a7eccd","addr":"15a638bbd12f6cce559e0f03312fec99d8f5126a"},{"mnemonic":"coil room slice arrive lady world turkey huge point gorilla course oyster","master":"bf665f511652b19a5ba1b0a51137aa72e392a7149c2df6af31a0244dcdee4475","seed":"2abc97e164bca2a5f45001574f9781dd837304f949c28c102c9de3d713d8cb0443a3be55a324817e53d78b50f0a939346ad414eff0b6307cfabea6023c2258b0","priv":"dd27b678563eac5bd7565e130f6856fecfefe3b1364ee0afdace0408b5ac09a3","pub":"03ff0c0d776d27564be0a465e29923384215370508961a1a7c25c261d09115f8dd","addr":"c4e5450d737defbb8f4d406650c93d79b1820043"},{"mnemonic":"diamond empty network apple radio divide ritual flip correct phrase kidney say","master":"f451294347b6c2035d9cc0c635b777af0d1fa756e1a72c2e41863a753776bf49","seed":"9108fc851316d1f63bf92d68e1db688328b7ae4c5ddec9248d8b5012709dd14dda42ebfef74e61085ae56c64a9125e3a47184320e53ca82684074ea0d359e6d1","priv":"db4465c5493f98c16b002401e28422b630bfcfddf32f8112c10ba71787490e44","pub":"0370a09ad6af977beadc07793db44c7bbb94cdc060a12ab36949bd36a3aca9c776","addr":"b9a0c2f7fe9d2f416596b71538982206c70a38b6"},{"mnemonic":"cruel music theme kid pattern weather become same arch foot host region","master":"82dc215e8155458ad1f3c61deccef305932839a6087250839c41afc36a043f62","seed":"0bf672820da35a6601782bae8a773f4dc6381fda5fa60a3ded12cec851225042769cd147c614f0ad34515996bc1f90675c431a5517c2b5fed80552b2bba59d7c","priv":"a63537932e88d10143726eabb410b3fcf0baaa550892ec17fcef874a2df8b70c","pub":"03b01ab00751243c746766568875b948e12eb1b88e85dbbcf2b538cd65544b57c5","addr":"137ffba20e834d732918f15a7e8537f014d2f3e3"},{"mnemonic":"pass avocado year kick ticket chair pelican finish lamp eight latin hero","master":"5f0d43392033f39e4488d6d9ecf9cfc7cf358fd718c1534c30c67aac21ec94fe","seed":"577d6f62d28192b753fd00bfd3f5af506d7b9d1608eb31cad9f8b08019011dbd20aec03ad7ee731f74811ad060249113b9d2a4aaec0f9d3317a4e72745876822","priv":"5600cbd7c571ddf6d0493f88ea45ac92e33fca9e6644165365cd59f91e68eb21","pub":"036f3194e13694cb0cfa7af94b8a60cd641159d60130fd114cb496f5b828fc2132","addr":"d3b8b4027a87f928323589e9f5a85330a349b821"},{"mnemonic":"deny improve give spin carbon lobster shell lava romance jacket village canal","master":"8b58d86d8564a0f23f0d38e08f50c68ca12a7c55956ca8f34cf790b7260dfb60","seed":"1d5a8348a7c66d8d7f6b5b99f844a7ca23bfbd4558497c1eb72f6679df2e0a03404e99e97f68a3c0a47d56e8fbc0d565f4c1bd0f7da014845038466c7bd8386e","priv":"eacfcd11a571bcdfd73a64a8c0b935fa343b21c0044f8e4d9d2d882c75db1733","pub":"037fda0cd490d64febaebdf19a0236a1f7a1bc6d523d065cdb2626ca122e9d50a1","addr":"9dfc787aebcbfa396a0ac4fe9b1513ceb1cda121"},{"mnemonic":"target tunnel liar bargain bounce lesson silk lake artefact coin coffee degree","master":"86437b39d0a0db7f5b0a27f627146b1ba6ee9c2cfd4fc12663ec3a2fd06d6495","seed":"fe9740cbcde2cc458420431b44c8158a35c172637b748b4051b79dd1ac1d100ba0cc60d4928160ce8eb6cdd5232152f9b90439fa2f4a3aa40f1f884d79f0e520","priv":"5e56256b91d4e255d9a64d5e3fe5fd0cfc2eb558b683f2289d773d09008a41db","pub":"0273026ac3c43ee59dd6d703efc5fac4d31e6b6585e27820bd8d91185dc399cb36","addr":"a0d89229e673a6f6962045c70faffbfefb0764fd"},{"mnemonic":"rail ripple tuition once odor barrel winter antique woman merry nut offer","master":"33ed9b3e5babe3904c48a79769a0d8a8285fcd9b7c1154316429382876726bad","seed":"595dd0a7f36a71e38b37baf88967b9960baacf11b249edf1afa2f2bdcf68a96e867644b712a78173609202b7d8b7cf2a3cc82014ea28bb955ddc46027dd10f7c","priv":"de65d8250e9eba67bcc69a2840187c2ea7c64f44766c1b7ac0b648afa0f297c6","pub":"031a160d7d3b13d9190c2a0a684161bd00d7a3fd6f472368f5cc4bf5ef3f84cede","addr":"a0469ba7da8af387308cea748507999662a7f76e"},{"mnemonic":"mix you afford area also raw water fabric mother industry mystery victory","master":"d458f52e08056473bdc1a73f5ba148da38f58a53be4f7d5d8e5d2974da6474ef","seed":"fcfefea963149047cc195afa589c8a81189eb27bc30d6bdbcadc5a74495400eb12d7fbd3cede6ab7e67c42e308dbcb4f74cf2ba1335b873c8bdbd13ff19dde6c","priv":"d5ef3fde07814e0967f9ec90b44a749a1c2f4bae73f76af2e10a0f73681e58bf","pub":"03388e81cbddfdbad87b95d800bec6e1869bbae59b2098b51e083e97272ef82fe6","addr":"3570a61894c36414a607cc787e0eafa997ed0506"},{"mnemonic":"find fade drip oblige either deputy noodle trial hand clown athlete chapter","master":"1131d43aafe4c9a2314a3c41116a0ccc68080cfcc525fca0acc53d5a2d4c80fe","seed":"207bd6fc9c91ebe2521cb131c261de75c71aa28935feb420a2e9603659826c326e996074bdc78b7075bec54f4268c828ee8a62aafe993cd7cf481665a2303e29","priv":"22ca0a4c09e5d6a96ff37eae29507b62715a643d3ac24389217e35f4bea4d9cb","pub":"02ca3c47a5367b7c9d83057333cd716b44a429d7034bda65761ee1dc503038d520","addr":"64be7f76e0669905f362892b53491230aa4c6834"},{"mnemonic":"anger level recycle lemon material pear robust decide they hammer coyote fade","master":"0efa37efdf167ca18fe15ceace835d75ae94027d7cf4186b4ac7bb5b91d54fcd","seed":"8838fceccf5c30285bfff02ec64ee34d7518c30b9cd722ab8a732d1ced8135fe1919af7e3afab63a55f1551d43d4222f1f62d0349ec185e4d45076b849de8972","priv":"16f41120d317d7387aad821cd0374d715a1ec1049057268b3ee090210a00a6b2","pub":"02b13c5607cfd0675ec1f33f82a09a9cfd88ea6a212a84f9528fba9857d012f5fb","addr":"4cf25877cd8e38cf5a37a9dac81a9222e8cb5461"},{"mnemonic":"fall run bread slight rhythm flock pipe employ fault side kitchen position","master":"89394aaca338752755e33fde878862096328720570957a7c105ddb90599dd87c","seed":"a2fe89e4a22f8ff5dc458ff49870dfdd7be85afb9fdced1165efc1a2bc93ed44e4d0ea1be438f347f8bf7c9812ad6aa31f07c8eb3b5ec7cd40e37540876b12bc","priv":"c0c189d49e3735f5eb9c7007e1e0a841127998d7c462deaba60912a55c9f0de5","pub":"02199a2f84eab6e63c60f7aeaa56b5799c6013df61e51fd2b9e2be56e4d6e5b121","addr":"085ecfb2737f0ffc78f1ce0a15868b24d09fbda1"},{"mnemonic":"judge soccer grace train conduct duty arrest output roast candy total vacuum","master":"a5fe2db0c41ad910231deb8112f6e10998895d48655cd77b142ad9846fe62458","seed":"4ce2ea9a4984030e65ab6eaf3ce543a450881597d8585c79a66d324606c00cdcb2c3cba4fc83160f0426dfc5a89cd27a9c9d05f94e3a04e3bb550bf698076b0f","priv":"b9eceef7003d3258ec2bca498b34d3181b38aa493f8b3b1237588873751539e3","pub":"02bb8de097658d0e711f875089062c135df56e33fe97e2c828da5a5023ba634765","addr":"963bbc3ce38f6bcf2e15a3c300e7eef5cf2b648c"},{"mnemonic":"lumber lawsuit animal member stool claim know frown knock hotel noodle pulse","master":"fee5ba9a343f60a5f0f38b80c3208908e2db6f03c8a37dec5cf55d833e913fad","seed":"e1fbac7d494d3e1def8d193a71872395f24b8d62bc052ef2aa6a09220451ed59b1f74a2bd02ddc0fcc0ab0f4ad65bc17462497c431f2689d6bb9490573ce022d","priv":"8dfa11b3935e4e660e246fa935b438bf9aa9b5efded0e62db64f61cd678e71b3","pub":"036dc946490687b821115c280ff113002a160325f212b2ebde71628ebd27e418eb","addr":"3e6e6935d3d9715f525fc9a43eb1e7465a1178ee"},{"mnemonic":"city drastic advice adult taxi build local olive unknown leisure bounce umbrella","master":"0aecf2bf80c660dc6e9a987d260fd4f38daf6a00979e2e6ff0769907c6cbe893","seed":"f66f4fc74817a4edceed1cbfce8986d1cb9c9f77b23f5b33032616879c452e64b5b598518aad9216ff0b210b38cae0a6d417b7200df3fd7f2c8cac9cde2fb946","priv":"c8bb1e0db0df18c9a4254cac791a309045d9fbe6daee301d431ad9dfbdbfec38","pub":"0376d3fa96698c82b0ca3d704e8754838a80f05d01c6cc99894640da9aad067d47","addr":"9532ab7fb7493cf19a9d2e61a808fba45dea3ca8"},{"mnemonic":"assist obscure army approve salt tourist program raccoon coral economy connect around","master":"27262a815e351c2e583835dbcbb7fce7c5f96d7b8deec45a6325d02b095135f8","seed":"72315d5e5ae5936c29173566fe17da012160290050475356063fc678a8a41530edba5dafdc2404c410c4b5cebe8dfdf5cd0f6fd855d94a08ba7e856c984b7371","priv":"2849c2468ce054e94252fa34a7e704e04042dee4bda5fd82d6b38e17d2451c20","pub":"03a278a4623f9f8d32bc8198c694e961868709bb5f425f6000413e6be33cfab059","addr":"4bb9c78ec04e00e84fd3310d101f3af4949351d0"},{"mnemonic":"limb nerve equip power pyramid nest sure kitchen lady burst pig void","master":"47e667f4fa090bc0f8df1db86c5c7f835d7e43b8151b6ae51ea12b917d4b23c5","seed":"ee38177c8d3f2c0076cc84887f8ec20b9b6a874d67a0eed6dddb889c1c7af30ee9031215b6739d7858a3ec35253f0136217f888c20621b217b8aec2a900bbb1b","priv":"153335c0a20adc5347c99b869b1f1b2a30eebd4e1c71082b8f16a4641c88df14","pub":"02a2f7b5767ee89ba4aed85a5c198b9b7e62118433b61bed2f85c843576428683e","addr":"50c74e9486961c8b0bdf5b2289f5484ebd6554d7"},{"mnemonic":"toast fame primary broccoli valley fit chase critic life absent crucial chest","master":"f4a62f84c5ea1fd074494763e0a541015341f6e96d965b884fee68c0ef5e4f33","seed":"27302ff242190977db86f09e9399621c82a5f953e57dbc3a01a6c38ce8b5da4a61b0e6d5bb79bce239e5fe59f3dd12f62cb634f9347afddd89680b592872d348","priv":"7ebfe174b48e60f3809ee65cae852fbdbdc292fdb934d2dcd101f9f9be11f769","pub":"03b2b6586fe30ab7d00dd7a4da4bdc74c8092284f9d7a3e78eb9f298dc26b3b856","addr":"bfa414a410c1cbe1566a050fccc48c99a9b3c973"},{"mnemonic":"live mistake embrace other bar tell promote derive assist deposit stable chuckle","master":"d8dace20cfcf215f4cee2e55c6b9b8f65225291d629cc8f7e456778cb2f5b5df","seed":"0a5c716e273df360383a4e29cf2e2df63f47012be5f0acfac32d37241bc5580096e1538491b5daa0cb4929807a26b4225afa988057cd195d8180f5beae9a7b35","priv":"15330ed9be835c3ab25357f437b5809dad522ed0c5e1e19dc78ecbace52def0b","pub":"03b6ee1d8c8a1fe25b6982ae76008d65b5a1ee20a3537898d5c3ce528f55544315","addr":"b0a03a30af7c4a79cf777c64a86d66251d0b5b07"},{"mnemonic":"orbit recycle wedding rhythm write come apology plug blur pave job rice","master":"fc498e657b1ba22254ab35dc64173d6f9c790501b8cddd18f1edd625964c8f57","seed":"af14771135c60a6cea8c4790a008ba09c890d826c8606c94c5cc50bc8eb36f06bc8eb374fa18a67d738adab33cd849bf1d8bf744a7b33197055c75e924f8b1e8","priv":"94442c669d73ed4cfce1b2a87c76696f3954ff4fd3a867232c5f878f2fec1737","pub":"03db45a44b5dcd8b34b4a5125e54811b800879a45593af61a28a83180f75817a1e","addr":"20505c7aefd22f78b05bc45cecfae800fa1575bb"},{"mnemonic":"oppose brush collect swim cup age gate forward spirit boat century annual","master":"c156132e600a1d3c359813d2d3fab0cf5ff13d8713569cb3da35ec78a424e193","seed":"8a1ce5772eeba927d2f237acb22b9e86ed2fafc89c18e33d1fa040274d1dbce37bb2e93e1ec8e2dfbd32cb299fc966e43567f11bc0022811e6d43becb43e2e1c","priv":"f2c9a5337186920bd738336ee616ace6f7c21b68e731c8cd84dc023c89198525","pub":"021a7131768f1e6f03b1177153f36815503e411c54a6c33ee6a20281fa8bfbb8c0","addr":"50e772de1a2e1028fc46d8958f96ee5802d477c5"},{"mnemonic":"genre seminar green olive grow close siren sadness farm promote bottom few","master":"ce632e9a0596520a05d8c096928811ded1f9a09b461d2924f9e4ffaeadfed8c2","seed":"dba3b4f2981a61525481c49e34db737274b80b86ebd2eb6cc64b05d8e321f871a97938e56abadb178688373b8c29a7c752d7c53a55d7e26d660ca948c8ea76cf","priv":"14e58e498bf7d472247df7024c6465db0c2f7b390a65dd05028b42576a3d7678","pub":"02ab7825f84bb603bddf4325c2afd8f7497bd1d22b412576e8155f1fb91fb9b777","addr":"a2e64380682dcd5ba6a4a5e7347389da76ab39d1"},{"mnemonic":"radio minute vivid clean cost gadget ritual front tilt other valve now","master":"c1fc2d9a7484bbbf513ce72d4280d4d6f01ee0359c59f29a2910d44bd06b41fc","seed":"8d4a332dca82af94bdc825c3ab49b970c5a2263e8a07e848841392f4274b44cbbc57908d6522369b32a584de1d8fc012f8f7f763421cc309678386f593e2f819","priv":"fdb87e0dd6892d1b7e29e59dd43d7cc5bd7825329e569d5dad839836d551381c","pub":"0274c7216f289b5ace0f684dbd8f9360679909aee0244f5f16b65ae33b1f0d9737","addr":"ed20a72a5800b88c62873ded8f5e31bf0ae08944"},{"mnemonic":"clay verb soccer near actress august like venture goat rug brief scrap","master":"d888a8d4f3c351b37b6bf708f47ffa1f0d56dfa35f039d4c8c6e49531043c4f4","seed":"470399a3fdf3f7f113b6996468b4cd22524b05290e7e91dcedb0f8cb6d2fdd39ded069f3faa72799ed18d0692301a64a214fec0cab41b3bae69d121d06dfb2af","priv":"971aa66792510f25849cdc1a7ccfd7aa8fd82a0f42df4a947ab675fd96db7022","pub":"03f7c82b2ab42b8e221f661ee3eeebe6231f5d98ada0133431715db7302814d448","addr":"2d306db9a75411f5ee640e2778daeeac539b1a52"},{"mnemonic":"rose team vapor oyster embark shell six object rescue village rug retreat","master":"471f619784e65272a58248f67516ec85a69dbff66719eb5bd17948c4e2e27c94","seed":"39dc2669bc21baa81e45013e856e8289b858778d3b5ab601a26115beebacc708236e742bc105fbba968e364745e34a0c9fda0799b79b859c02efab3c3a4c7204","priv":"581e1940af1601b7ffc624a6465519cd6959234d112353d3a6f2ce4ab3c75711","pub":"02ba88784648b8476c55f9cc4be65140c478b835d79fa596abde69038f9b5a2b2f","addr":"bea24bf839a66b47497014c0f29f98bbd506e9c0"},{"mnemonic":"blossom turn knee oblige digital mail phrase fly soldier unaware corn journey","master":"d7f58c53d2b777e2f1162bf97573c03446afc51dc758bfaad0468c0edec615e4","seed":"f13ee4c99a6c39751bc6922c9be96321c7704c36ae6537f13146b4eda938fb8b2900e44e901223b2906db6392617d4e156554da83644731ff6e56b0b3fef24a2","priv":"c4231def1f2510c02388455fd0d5a2ccc80aacf2faefafb3534544f1b75630d6","pub":"02f0e5922755d841b79fb76f0f129ed3d10175ed4c377d02403cbfcc1c9ffd9c64","addr":"8c664b57dfede7168c0bde20acd37674a1922dcd"},{"mnemonic":"crisp joy brain treat actual later nice ensure village bind powder merit","master":"01058624d066cd1e0527da16937d9ad9bee8b7aeb76c279ea53f5c5d7e56f6d8","seed":"389060cdd3a98f5625f373a0a536f70f84cd0cc6a7d5bd8ee20fb94a2aab9652bdf61af9cc532ebcf217fb7d860c30ac1ccef4fa46b0478971653a42a1879811","priv":"7c0389b4564ae01f4c14da09842984f9b9720fca2d09fceb0244623db5cc07fb","pub":"03420010f464371dd52a34cc193d55de94a3ffb3e746c5566bf8a8e6bef686efec","addr":"c9ad4a84c23c753544d4c3972b0c3d2d86ae397f"},{"mnemonic":"three scare horse film rice divert frost gather photo weird nuclear hamster","master":"b5107f515bd7ce629e85b64264b2c9ec80595816d9bd47f04eaa6971dd565d8c","seed":"ee242699f11339f305818f44a171f79b174f45c09f2322f53ddf3094e830fddbf4e418bc3ade62f03164d8435036514791b936ccbf5f405defd33bf68984ca01","priv":"99513bf817cf2726237c70a70cf6bf5e2ffae1494b433e1d77c8b9c59a3e47e0","pub":"02641d322b89339dd17528573b100647bb082e91d7cf24bfc897e90b20f270f791","addr":"d8545d2e2a4ab61af14c04d40fcda9ad39bcaa33"},{"mnemonic":"circle pond sing route tribe grace exile leisure health cluster prevent year","master":"5cdab97cd5aecd22d671964282f6971ba4be01267c90677091d6db6b5adee0c9","seed":"929117b95286a76aa839e45e768b9f5cd23be5bfa73f929ab835df15cc1c96c2c57cad593b7e396296c0223d38c38b03a4ede097bf3b188a11631537dc6223a5","priv":"35fafc87a67c7547f256f7bffc5b19395349e1665e01a89f228f44af8086b118","pub":"03fee2e799ed5232ca3a29238e0140cfbe5f1bc6ed2c1429c0914c4000ad59fb3e","addr":"2bf9cf4c3f34de93078928aa8c6192450a29af02"},{"mnemonic":"rebuild address giggle city tired dice sorry danger onion cry cheap sock","master":"83df9579ad9f629ea3a09976302888929c52527620ec7041fc9d4e36380fa953","seed":"7cd7ab5cd9f450b45515985a2af469765286510461f42d4ee5258608aedb40b7f60365b685a706d0e0d82f775da38f0171bc8be56543113805227c5f9526e7bf","priv":"a1613406d358b4c1db8439a3e69a4d7072dbf78e06c8a8b72c37425761f874ae","pub":"0395d2c96136983d906c50caabd2f61d1c1b19a227549f7bfeea2ee327c5cea276","addr":"b51131cafeb358b0f90101072a0bd70fe5226726"},{"mnemonic":"toward turtle false distance spider plate aim daughter team jar case option","master":"229e0c7738aff8a44fa62ad310f3cb18f6b94610c83faca246c428c26f47ca18","seed":"405cc161455171571df109c3baa2b3ae25a8ab9b3c7affe9b09b32a755ea443ee590f722f9d2f3c39e9e828a2f276f46a6f9b65b024a11c6d9ae76929210ad23","priv":"095f70fb24f7f97994339cf37a6afc4e95f1a421d9b076cd714453ba2dfd29c4","pub":"037fee3b9ddecb153acb32358781fb541283c3a61ce2f25366b199f970a87057e7","addr":"f3e1bdca0ac89c2f4036f07cad45f65ecc94bd61"},{"mnemonic":"mind mirror athlete assume piece surface raccoon struggle inject horn body engage","master":"75156c7a3676b6a756cf4eba160d44d94ecbc6ae06457ca714f4313367e8493b","seed":"c754f1684d8944deeaec89ae5977458ea9843b4bfa0997a7c1213633c6203a154b65f2109e4e2746735c85ffb7dce803bcc57b38cd617b43345c2b486ce44ebd","priv":"c03717d4cef8ebc0e4bd6d78ab5ff3d5975da9919fab3cef3249d329d488fe28","pub":"02638868a04c039201022036284a8916939b6432f4a469c132748955f7e6dc468d","addr":"d7906686be6e6b9e1dc032c9e89d30ca8768c698"},{"mnemonic":"armed lottery garment beef manage knee subway market enough end clever edge","master":"08432ba7a4152d14119d22b52f8913f2e221237f125f58e4df5e5c87da81a74e","seed":"7660fa9d42eaee32aaba664593f1271cb60e092a5758bf3353c03a448360ccd74ef45b01612aae2637aeb86f8d9380bb8ce6b9eef5e0739c85736cc50b612d51","priv":"4f9e5ef095a07a939d5f3296b211fd938ca90d21f52640da2272ab812947127f","pub":"034c3bdf7e1bea7d629e2b1f82371d1d7d04bbce016317bff603a0cc2682544a93","addr":"8ecb13c1076cb132990cbd0efeb072e58fd3d1bc"},{"mnemonic":"city chest trip critic advance sign push patient choose pride lucky cage","master":"5069d7379310d03e01f740871ddb8043daa108e523ee5c2aaca252d079b9b99e","seed":"5459d94456d6fec414efec5630285ec7e05293d92c8290a07b1070b5a7fecb8f7356beffc82790b50da2fbfb28921bbdc64ac0d94e1d565f6ead799c1c04e7e6","priv":"6d334f7f362d2dfb4e7af20f7fe30887e3c91186954a8252078f215ca22e4b07","pub":"03fdb94e64855c4c973fee4157d3949bb9b840ead95906a672c1d08390e3be4883","addr":"bfa8840559e159b5cf6e7831c4696238202171cc"},{"mnemonic":"fuel derive exit magnet shallow salute clown prevent inmate hurry conduct series","master":"0c721f303dc4ba98877e76b3c36d82a82639ff6c02318dfd4547943b39d7fb36","seed":"877d16863699cca3246681de6e1b9f2c4b59ad600341c0ce16dd8c95c1f5cb1964bdafccff0af5d29eddaf9bb564552499234eee8e493549d0f6d2cea0a71695","priv":"b4f009ace3092938c51c2d7557b52900941c6dc437306883a89a51e29af04900","pub":"024cc003cb7be1724456fd703edfb7e339285883088e97247d83cc64e8283f796f","addr":"b2bfd256adb5be91b637eefc2c20efed75659f8e"},{"mnemonic":"soul junior garlic chunk eyebrow betray heart sunny average coast help champion","master":"7c420ff72c69dbc9006c4969beb830d7fbbac17dfedebbb7d7852430f17490b3","seed":"34ec95dad85e66b55bd9bde227e68b86298e4bb51b3b3514ff774298ade39fd769eea0f2433392a09578da35738cdaa31a0d71cf043204083006cbccb9ada2a5","priv":"719c2fbf2db0df066f36fb31275ab75a3905c52b04335f97f778c540e103a7fe","pub":"022333046c912253a37832140cd42243733ccded5a7a13f20ffd6e59cdf19443f2","addr":"048677f2e035a21eb91d40555f0c9ff53f335660"},{"mnemonic":"private outer service journey dry exact thank ability wheel destroy blade scout","master":"6d87dbea0c85b9ce5e67831bfab7e5118ea85d7e9103140842ed4b7aa46c2b87","seed":"d0fdad93d2b727475db3da1a5cee5a4dd8c9a0794a6a73b5c3d6078541df7e7717aaf0053edf1d4a670dbddb96a6085bee0b7bf0c4428f09bae98a46c93e139c","priv":"aea666b18ff888190a0119fd38604a711a66d235bdfd514378e6a52efe4067da","pub":"0275d06c981e89fc560ea25164baf2c238b6fe33bb65e78952e6912b9cf991a65b","addr":"32aa41676d1ab5e54575d0d13f673c352f0f99b6"},{"mnemonic":"diesel suspect urban fatal total motion other opera taste shock prize lesson","master":"6760aa56bdd6d9a29615c425d934b788ccd70b80066c85caa2091e3861a5508b","seed":"bb3df25ef6c4ac87b93991710c0b927a24c47bfe467cc3d057ae3cc5867bff989d6e8df8b790b52661ad3d310730dc55ba8fdbbda118d3fdf75a21750f2f8089","priv":"399d6d98eb0cef3674ce7d155b426638ea4679fddc624cc582e13b7f2927a8f8","pub":"03e6082570bd65f91edcdac9564f3d71efe75a4bbdedc379774ca9879fc8a57cf6","addr":"d3a69b264f967565d19aa3be68b6a20ed054da40"},{"mnemonic":"tide rain throw pink treat sphere soft season network good left potato","master":"a2f3cb3671d233a245fbbdc8b769089035cf13a9312a78826972dbb99eb4e619","seed":"0fa23be9b8c9a11dd03a5d6c1677ef78526ff2ce3e12de5195d2e1b40f2df6b90515bbb6eacfffc2e9b82ff66426fa1e3a86b51e98a733d054c4b58b6b5e7025","priv":"34fd376b792658501ede9f9f2726a94f8763151e20a3325d05eaa7e6b92b19a6","pub":"02f2f3b3ca1654334091af786f28f9b64dd599f188902cc24f2890edb62f0f7527","addr":"1f06acf38751a45fc0734766e3c794547a31434b"},{"mnemonic":"hold forest select elevator skull warm crater help sing liquid foil burden","master":"20bdfc70225db1ad0d9a1f53a1558efe992ceb7001f181a0ab5a0394851dc81c","seed":"8839e0268e51734574d033b2ac42d3de449819e0e6a916b9f59380d15be767f5a491076bb4e9c2c586cf92d07812f7338400962d28a06c2218a3674bffaf586a","priv":"8c1f88886e7ee663a9df9ad3b31871cb864bcc1ecac7e19bff14344423581796","pub":"022dc59925b511f1420f897805f13b684d9e91731c88672121dc59308ab4fd7c12","addr":"3911febb503ec0cfe4bb41bb6e9fd1924a027aca"},{"mnemonic":"power orange shoulder stove sunset during jungle buffalo funny enough immune skill","master":"51384a8d4d886c1f0a7b4b1938d798c0463e44fb0ef05f6392d5f0c3c0c1813d","seed":"ef0f86555bc2d06fb8b676196c8d046aecc752a61a95d4783f8e90cd0a3117e08c11171214fa63a8e86a8280ef98cf4cf780eb384eb78ece725b94a261770268","priv":"e644ce7c5f3541acf3649d8a44423d277301e519147f50be97dadd4ae1d629ee","pub":"0312f8f9435994bd6156ef158a80b721e73dbca17671aaac7f7d67cc847bda7ed4","addr":"82167c6542716e9c1a072228a6159af1b02f8893"},{"mnemonic":"black evoke reform inmate similar wall machine deliver gift photo axis mean","master":"2cd652f239c8ee231e516843dc9bfed097ad33378563e2cc50e07a48cf0bd28c","seed":"02da5a82f2f4a6ac1a4a962d5450899e949e702f96eee80f364faa7751b50a55b438c6e4f4fac1b6e495b06fc55f63ab9ec1d288df3d62f6644bd59dacbcea1f","priv":"f6566def1b32c210a1369b859cd8815efcf5565a2e1334afb0663115acbb5724","pub":"033055d70eb1aaa92d91e04edae35bdcf2dcaf4bd80cb2f798f2be9bfb6a6fcf3e","addr":"dbed2e50e81e7b093ccadb9cb1ec9ad86837ba09"},{"mnemonic":"sea snow child feature gadget oven this lake post entry essay alpha","master":"0ca6e7a0b4fa4522ed7b8ae0834949bf8a35f7fcfe099c237513d7ba59d82562","seed":"94a9ae63647a2b63121725f961c7e56c7c6b6985a169c43ae41434c3155ccc8244ce10d6376fcc473d7663189d51049b035e5e232834b470a404f24e286e88b0","priv":"9b029add6a255727c4cb80b868975e95086487b3a463cb35870a74414fc6c14c","pub":"028a44cde34153397149442c970964c1647e214fc15dcb345c4025cdc26cdbd3a8","addr":"a23cebeb59b458c97abd67a3e32387bbc56545e3"},{"mnemonic":"couple regret airport shy symptom shrug mom sail insane culture detail shrug","master":"37711c29531e793d6a5e2b4931b3aa0240ccef541c9b8408c29bc5b68eded038","seed":"9c054a9047e66665412432f402f94e0dc5f87d7cbc1a32f6486cd928bc2a9a0aa898ab91fd3aabb962af985da396eae7a0d00fd739650bffaf070c9af44721ad","priv":"b9f1026e086eeeac648193494b398770b7226d46221cfd7281e5519e81fd8fa5","pub":"02de158ec50efb1b8567d63331fd7aa66aaa59ff26a621a59a52ad9341330b028f","addr":"aafa96d9be89b09030494856cf6275b8e9eb387e"},{"mnemonic":"mechanic sadness easy credit eyebrow sample health pyramid bargain actor power glad","master":"68c40248a8f7049062f18ada91f3f2166b37865895d4fdc8000268dfe263ef9f","seed":"d28287812cbbf2cb8509eff491ac456ed199dd2dfc8cd3c93e05b0541c154850f09f686a573994d41f163884708db205b37afb02752a8f0b2b9785c6eff504b3","priv":"250d326d0c232bdf26b6eb8e349ae5b49e30b0507fcce0be1be3bce55b0f7645","pub":"02d5713f20005136dcf9d8653dbfd75bedca3f42b2682ec9918b92394f2b685b13","addr":"409ab6606687cf83eb6c2388d6ebe296b4799967"},{"mnemonic":"mercy spell despair dirt board clerk about symbol supply provide rigid evoke","master":"37a0b9c11386b995b71a8c8a5e150ff76d238779b8148a2137e5d4666fe9fba2","seed":"9e3ec2ab97061086be1e02cae7a0a30493c019247411a7e7271c0c5f7f40bf027ad3230a1f113580365c82549ae23c024ad85a8601a30b6f78276744ec803a35","priv":"0385392be6a34bae1ff02570948ce1217fd11700ac753bbbbd47a1ece41ba38b","pub":"03218315e18c8a5128f74186223d32ece9c3987a0427db95ef51eee9acda922c03","addr":"725139ec60574c941c133ad2e09e793c1cd32cf3"},{"mnemonic":"emotion exile anchor charge silent nose family tube view lottery neither razor","master":"d8e841a6199f937fa9bab3c3905db51899d456f9caa5d85d9d930f9981ba6ddf","seed":"c8610e5fa0b9d9a83610c4458129802434d7045fe44917de29366c6d900f123e5414fda889e21284405c4c64fe745a36966ee86fd6f61d1dce6f809e0e63624f","priv":"b567d59ec087a81214968756017868e483e62326bd7239fddb27586745412349","pub":"03182c009fea42d30f31f24b6a5d251b70e72c1262d22f25418653cee5a226bd15","addr":"9f5d2ece004dd9ddd79b164c4b51361eceaf077b"},{"mnemonic":"orphan attract pair execute fresh interest artefact shaft sail advice vanish moment","master":"b58a705076e0c5aeade31776d78d319529bb76ce748aacb266dc910595dcddf3","seed":"a156c3c4b6241c4e99bb63dc221b13fa77219f2419f7c33a7a7752b5dd89d5be2178b6c2de2225292bdd0bbcf3b90bbccceb93ea65deacc866a5a3da4944ab1d","priv":"857564d0b2bfda18ecf561ea17dccd6d1bec2100e79b6adc8a74997b55f53126","pub":"03eddc58dac77538639745d167c174b907a448072ea4ef9b14563217716fb606fa","addr":"b3a656fa40d9a7f6471cf6dbb00fa0e2687df914"},{"mnemonic":"guilt awesome champion wasp execute purchase better mirror such prevent stay actual","master":"ffd1b0b635383f57d0086c1e6e4925d82a9cb9b310d0757afa8d941a13a1d61f","seed":"c36560913942649932b4aa8027520c46155135b50d66b0c6b33a7f63272b3d531946fe3aa0efd22c6e91d5e19cbed5183ac2bc7a18c219ee3e47dfaf35ef15dc","priv":"d5d35667bd3f54b40858f3cb4c6f09feb889f11d6da386935fe8b42e3a37f58d","pub":"039cffe0fa0a30d9ab9b1ca354ace89b5c9cd21d2653eb5a7a8c5b66c03912bc8e","addr":"1f2543b17460c4f7c2d53369fce6383771c0f7d8"},{"mnemonic":"pyramid soul ahead tongue observe void whale sense keen feed today abuse","master":"272cd80e4846e16f0449c68c8ed4c78071613b57660b85206f716203014c9231","seed":"2f342928932ee8e588bb75ca7cdcd7cc61f32eb317401047cca5b4133e963776ad86474999f9013be1f6cd947cfd9cf4add3be93e686d467223864851ea71751","priv":"d52cf3cfd4e6b6310bf47db08d27ebf0109582f78419d369c4c5da596f22bdb6","pub":"038f855f837abe423fcea3ce81efeccc49da313c71630cb08089956afb73e96e95","addr":"c888d0e5e1840b29f6d85a64cd9704221fd3046c"},{"mnemonic":"speak mother wage grid column movie pluck deal bulb stem okay own","master":"60b4e8cd422ac64986d88f4412e0c694d77d09d4469b06bbc8b4d9146ca5e412","seed":"ecddae7245f9ceb3b2eb324a78421ba99d3b39819bf394be90309cea21d6275ee32a068aef8078fe3514cde61a69e31ebe091669392b5c8a442451b895591ad8","priv":"4695ad7f839e5997df9747bb6d4ceffbad85f6bb26d01c328e6c6e8f6e68800d","pub":"038e3e274ef62db04582bdf01f4c443fdc5b590da7d2c0f5f1d1d55abb0752d440","addr":"359c60c1bfe3a11711423effbacf7d857d39437f"},{"mnemonic":"unveil toast planet basic limit bubble lawsuit grunt lonely favorite inherit write","master":"32bd1431071e17e039819b0f3d9d959c5b88813cf49ca69c90fd547a4fedccea","seed":"d036fc1412c23cd5406860b96814ad9f54359e103834f5d9d1e5f79d52b2e0a8432c4ae705d2fffa9d87d4946dbed2c847a4589542f8051cf6e37689617964c3","priv":"93fac9e5a9e35c2138568864525be7a43492e11f715c097879033aa4019cd723","pub":"03b0e30e8c5bedab8f9ff703df5c9440855b96594e19a367f3c1da13aff1f606ce","addr":"0e70b83293cbdc8b5e3cbec03cf2d0602f221bb8"},{"mnemonic":"cereal forum again rail lawsuit mandate above vacuum hour tiny rain mad","master":"1bfbb49078074dcdc191bb798d3c02462d736f786d7e91461000fd644aff7cf8","seed":"2aef95fae13809c1689d4b5a6598ad4e642ec6373dc6a10b6f348718360e3397eee9a2ea24acd344260d4002b2e7857e71daa1e7111f943ba036d4d94deaa339","priv":"75d0ffb17edca54a389371ddfbeed3a930ff3ca88ef166a67101b9091636d7a8","pub":"03c1ab2904a55bcbd56d1f1b2840a4b09f665576e980cdf2fcd45db21c007fdf82","addr":"cedaa1fd49e697c467d8ce47a2d67ffbfcfe1d56"},{"mnemonic":"infant glad torch shoulder benefit pledge social indicate present deer glare hope","master":"fa580a50eb13d1df4efe98cd3e86a1927e4e9b8262a279f2e782d298641a7378","seed":"a3e088fc36097fcbb0286a2103e2b8f8c1b3e0f6d8521c82c2c93fe06a8c1b97748143b02d9196f095ec1be5044aa0d89b39bb131c4488858e549879cca4c8f4","priv":"61c933db24e871ee66fcce148c2ecc3fc85def76b1e6f8ea784001941deffca3","pub":"021922866e34e3d7e28c1f5778c70e7b8742c2c9151ca5559039949f32ff0854b2","addr":"e550531be6f31c18a90bc6add24c02895e444794"},{"mnemonic":"laptop vapor rotate chief frame trap duck satoshi obvious pen oblige bubble","master":"239c6fca9e52e705ba0d2d9190a08748408d3a53ba0d19bd51fef426b56e1ac1","seed":"15a573343b11562370b53ccc9f11be74e183b1a341ee922cdfeb8c84a4dc914d23ed6a7f58ab451cf57d5f610c8ed9f16e2072a71ab8edd82414fb9d24cacc3c","priv":"ac37a60d2ff77750624fdc0d41531ebc6dfc1786f681dcdb436ec920f91a34b0","pub":"025dd6a2cf772db80dbbe6957ad1606603cd5b065177ec93263ab0194505c420eb","addr":"5693d8a59358cd00f21dd8786248538bdfd0edc6"},{"mnemonic":"walk raven camp kingdom defy nice hero copper velvet lock era south","master":"b4292f1b198481120f507ff13017c2756208cbc9652c555807472d872a58b9bb","seed":"6d2f085ea9e128fb3652d78d9e14e38eaf793ef1aa8b455798556482a5c2f3dd43933c26ab9fc38fc4943c82cb85c8c5b027534f005d45b740b31f63c683b87a","priv":"ad8fc7544b1b79028e05e96c9889004d9c5cdeddbcdaf05bead09b2075dadbba","pub":"0285d2a820245c70d9f3cfc930d6c4e467585f3c831cb7bcd46f58d637bc827729","addr":"4c7c3cb79dffd93e81882b609f7424431e55d4a3"},{"mnemonic":"impulse certain olympic advice entry initial bean glimpse begin flip cotton mechanic","master":"b092aa1b7fa22bacb8915bfbee4018484dfa4313c5779142e71e6d80e334dac1","seed":"9dbec0ace8784d915fe1bd3cc88b7c774fdc4791ace38856dc0500927aa02975feac3d82cb9771bd69d5b2f8c11c663e887b27292e3ecb36ff33ef5b3b3a804f","priv":"19497a3611ce0f1fb43aa5c55325099b6fb18811c99ec1d38c743c3338ddf5a4","pub":"03ca79e260e5a06bd3717cd969610c06580f65aa158e770eb418653a95a52cd0f4","addr":"f83b4129ec37643eee9f5d262cfe80087c5c5841"},{"mnemonic":"trip brass eyebrow plug sibling couple tuition tired warm spoon october finish","master":"ba1d19fb67d08931e7fc46b55c02651d374c7edc6df6a3b89fdf9e28670de4ef","seed":"736522d275c19137d354d8899542497b76b304e33c348e8f446970cd77aea927e2fc1d493b5f8dcdbe48c0a535722ba4223ef52925a57db21065f92779ba66a8","priv":"5d7ece46202706ddb8db591c4e125403f9aadb33c96f259105a0648ca1e2acfa","pub":"03791637ee34fa2e798c0cd98ea21cd17a4c02c429f05a9df5197b852fb643216a","addr":"e46722ace3466a38d3b5f66d5f94786d4576390a"},{"mnemonic":"suspect brick cloud coin tomato guilt inflict type lesson panel right still","master":"56a2d9f123ae22001633fda68b5b6f1fce4959ef19dac2c2a88ca5f774cb7d71","seed":"bc3b42627e5dfb76f1808f75e8cce883afff811821dd615262fa62c98c00cc0e0fd97b213f3b386ac00dc38de399e6e56b9216e34e4deabd15d23d70ff94cfd5","priv":"0d2c63fef727f339b9563c1f8bda5edc3755029ed45010e99bff74bf805f187e","pub":"02742f8b32ff1cf54225fd667425daf286705a0852e554e3294d057f5b41bb737d","addr":"4ac1a9bbd5d9d9597587bb809db80b69485d7e47"},{"mnemonic":"innocent interest smoke fortune smoke nothing clutch dust ladder clutch property glad","master":"ef88eb840ba3b3a072860d726b16c5309b9959381db68debc03d9516a7a7205f","seed":"33a6441e74f21794565c5e219b98416a17316a7b9335f8a0f5a5ae45608b315539c9938740266b663f8410e773dbf361f67550e185c0d42fdd4b406fec4cecea","priv":"5360d32f6dad727cc98c0c1b0dea7bf59f89aad2e5127050294adb9d7b116788","pub":"02bb5f40466fe161d106ccbae569709217ce1da9764078d27d3c8375752d7d1f87","addr":"fbdf59b3297e67600290d6bbffbbd39fb6f460a6"},{"mnemonic":"employ ladder boil blossom level pitch vapor gain permit manage coin supply","master":"c550d7336d80488c81ee8f2a8c3fde04784b8f3079d63add93b1b8800f796024","seed":"a80406c58b6958a30c0bb15f3b6f9efcf7e0c8cd0f01114a72f9c446130801c539028c964321ed9ba511831aeb00dba1be82eb28977319f727de1a9f44b1a7a5","priv":"9233c90da7ccf973268310430efa073e4e070cc5b9dfa29612bcc9541ca3417a","pub":"03c070cf8379e2461ab6158755f45d881ab8fa7de1501bcf0530a871abcef79947","addr":"fcb4e5a3f2c568e0d513d1ad97c7b806a96debce"},{"mnemonic":"winter absorb stamp enroll brush paper spawn slide salad special front update","master":"ee7f947acde43c8fc5761af3ca28fd0e87d0883043ea4401f0d692ea818d5573","seed":"0f1b5f166616c83c129d6b2e0d1cf706d46fb56e60698beb77f9eb105bc0726fa7159a4a492b6de462517d692bf26a310528379ce47b4325879772f46ea0d82b","priv":"31f98cc2cdb0cc6d88d91f21960136650d3e7bca690a569edf2ddd6095026e38","pub":"039ad4a48de652c30e015c424c2ef3083f234e5df78791f112eaaab2f74deb71d8","addr":"68306083576ce37fb1bc653ef33e46ade3af0c7d"},{"mnemonic":"focus usual earn deputy execute climb broom save robust coral piece shell","master":"148c7f123552e1be3f696b2f8b0df4885de067d43f9c1e5c671ae6a3ba4dd361","seed":"a4f311017ce37d0f1199253671b0f615ebb09f92648cd33590c2292d4bbe1eb45d6f1a94e71e1438c5cc25974efb3b8ccd03272ea0218f171b01c7fde17adefe","priv":"587f36966f566888d5684aa983d86c124b4657ae02e7d540939c5265ca50ae59","pub":"03cc82a5871dbe05fc52fa3308bbde84a7744780a4c6344910989437b37b59a0c5","addr":"6fcc01f30a9e9733ae95a049ff8b3ae0ea8c97c0"},{"mnemonic":"twin over wire boy dragon drift erode human shy minor panther library","master":"1488ced839d3116ec99c8d4fef9208224ce28d270e4d3242999e8c3d1bcc1719","seed":"099d13da6ce761e666e6df0199a79e95e83d0c911279aebf8037196af6c7070dd08867dea0da8d9148dde2d14ac55864a7dfd09464282d93037aeda70520d664","priv":"1c2871733b9b2fc6224400612807d75387c37b87b925caae6486b777b0dc1e53","pub":"03496d39cdb3d666703b041d5bbb69482537addb552335c7f26d29e09d5ab8500d","addr":"7b89136f5fa6320f53c25a260b4b75eb5bee5774"},{"mnemonic":"potato lecture exit color target shell more push day catch entry erode","master":"a44668b008915d6eb656347398a007187c18cfe766ea167a89e855a77b9b9c37","seed":"815db5e7fd253567cffc54d938a3fd307968b45e95407617c55201d661f2ed581e92f86a1391154e6421bcf04487da1d3c098382a3587e8c5679704407812fab","priv":"de5ca4846103dca9d947e7867ed764c9094d40ce189cd2366befcb557325616f","pub":"0342ebbb943a1f8100441035ea11cf76c17dde7b7298d160ed56e3dc8fcdc7a8a6","addr":"68f2cf5a8b290409689d5e08f99cf1b882582e06"},{"mnemonic":"grit flavor pass apart swallow quick payment view weasel decline travel hat","master":"3a2d8a4e041357a246be12beaade6b6c36fdab6dfbcae0f8230106a09c5157ab","seed":"a69ea95da4c681f004cd5fa6d357c39e50594b66c73a42a93672c13d6dfea0ff0d741bc1b406851c36680895a8137086f6de132d2aaa47af5d4872fe08818171","priv":"502b2d14765f2f80f6ee0c10b98333e498dc7d33a46424555f8429488d57de1f","pub":"02aea2e315932b900ac7e31d5b6b82e9966e45b098dfec8990e2efbf4457e581b1","addr":"c6f8426ba017b6ac4fd45a95341e760f158f0e41"},{"mnemonic":"machine insane tomorrow island assault follow verify spatial pizza major cannon inquiry","master":"be46461a96c733b1add1465d664d74b8e1a28fc1bf25746b9e9d44ddef81ac4d","seed":"2a5d713bf4b71dcb40d0526767f8466c87f04ff5b2fe38ac17d5a7418f099b25761917cddec77d369471bc22a1f26d2d7f6fcfb00b3dbb28f08279ee0ac85f1a","priv":"097be27be2a0c6960b436acd651792cff207d877695acebd02c088e6f3617b9e","pub":"029cde9790e6e1b55d54aacbfc6d13f09fd6b5b04976d0ba5e01cf25da0a2c3976","addr":"06ffc6a5742544cb3a66bf443ec0d8894e5822d1"},{"mnemonic":"plate grid latin above champion demise idea urban raw exotic day diet","master":"9daa2224bd8c15a22941090eac1262e88dd2faeb708ecc00f404c88723bf617b","seed":"e07adaff2724a1af34ea6f3ef3e583086fa835ca126f731875f97b366322aafaa8d39b72a22dbe70bce68d8539f1ac109e3af03db42317f3807e91c35748438b","priv":"423d528c82af34cddc13f8873534984302e072e0aabc9f29b10c70335bd72a3b","pub":"03241547e0145dfbac8bbd5daca05314e2fddcc22aadaa8b49952e461fccce7d17","addr":"2c1ea451fe2233aa3d2120f2b836d11cba72905e"},{"mnemonic":"august quality apology more ring armed hamster raw gentle inhale angle dune","master":"90478d31095fcbbaa751055f7d9fc70a75a8dd34ff825f1b4547103e3367ff9c","seed":"0b944522c472688010098bad62a38a173e0184f64710bfc370e8ffd7a3e2383d630202f52b7ab9b8d41948f534b2bdd0e2664ba76f2e460fc62e73fd1684ff16","priv":"e8228b2ba4ccd5a22bddb4e0a3eaebe6a156ffef061779d264b905c90797826b","pub":"039fe65040d933902f33749f3d43cb924c6df298a969b05760bc4c8fdfb27df444","addr":"b0370814a3a0390cb3874600ff1dd48481725ce0"},{"mnemonic":"argue april pattern jungle favorite shed silk adult file cover benefit neutral","master":"3d5f13e3264550f14ba0edb8b693e7ccb5e74789359a7cf9b7f819654542acd2","seed":"f5fa70f943ebf5b941574820d4b91a1ce706fc5f9849219b7e2e0f9fb410c4bf81494beeb390383e1371817a39f2cc7a9552452d973ea8a15ab42b881c7cbebe","priv":"d0d2a3c92a4b1914064826c1a9205ce8bcb076109ab2524a2818d2ecaab08420","pub":"02040f9ca1b771a4692ff543df77d2fa8fbdd9dc5817789b1ac491a9e0908638e7","addr":"0fa135a93523a80e03603c609953a2f5c7b799ca"},{"mnemonic":"oppose describe defense consider long lesson better kit capable taste feature reward","master":"07ef0cb309577396089c024c1b48dd278d0575aed88e63ac99a44d531fc919f8","seed":"c6ab42822e1fc062f5bfa6e5d7d4049a28be293748858bb2062f4b9a3c20cd30dd02e7e86dbaca2c77bd2e1d837247cad63f8009f9f9410a0365ef7bbe647727","priv":"3b82e67931a96b68e6752ce67c1f971e23c317f8829e2573672edf1d80c68836","pub":"0248ad30caf9f25bf49bafb519ebb3d381ee9c95a6da6502e1cfc88a4a1aea3b37","addr":"17fe8e8d5f6a4a10a2b7f0323cb6ba3bdba9fb93"},{"mnemonic":"blouse patient surface urban stand clarify old pipe where spatial cargo shell","master":"8ea8f4837a7a4a3bc100595fb6dde65f319e8928e61f7da3eea2309169b9dde0","seed":"a7ae3795447825e6d51da632bbba6f8d9f5e141e593d2a78e05f7e0914ed063d629f1f84d3427e7803fd1e317ca0359654bf918724705f523e2a896077c39603","priv":"6fad450edfab3300ffdd65133f2973fd0be3daaf7864e2f357598b63416a01d0","pub":"0211cb5c4316de9b5c08e8764027f9dfa0cae026cd9ff9773dcf524c06f76c08df","addr":"2a51a4f2ba38e779b20b7a4bfba78e8267b6d6a2"},{"mnemonic":"moral penalty ladder step panther divorce bus adult math various speed rural","master":"9641e82d742f458ff81d48d486e38cbb8919a56b2a317d822674ab9e4887ea6d","seed":"8b4c57108bbc2c753be29e0b19ab43b06c7c81e2dda243535f74c08222b23789d3aee754e23ae936df99c8728b04cde066b6e6e512b54fcc1dac28f0b0763074","priv":"043dd7b6ec9ac7f52f1af6f3ff95cd99371c251680c04b3c847da42242d152ce","pub":"025f7dd3fc53ceb3ff87c2bfeaabdeac1d5f1c9b8a897bf4a28ac33b95562e4f79","addr":"9a61f1c15e55009122d52a1c3917a8459fa29238"},{"mnemonic":"pony liberty split enact quick arch mammal velvet cart wait arrest burden","master":"e5fbd41b38aaa3aa643a66aba1c3e8a01709b15f5e1e30d639db03dc87151065","seed":"b6a41b697611cccb9e117b5ce798d47bb37ce1e07341cfe972905a4b66c4b7f8596cd0e6c21e0cdd221be33de8c0a5854c5f8618df36f28d95dd1dfb0f31ea1f","priv":"7e98676864a3649911657e32afe07f6ca86dcac164f4a25e48e33cb147ca4401","pub":"03d61b29c9f5775c6d8fddd6babb2b8e77b65fddcfc14b8c8f6db262285f2d1832","addr":"36c7ac440660d8a8642d669022d621ec1e877680"},{"mnemonic":"summer envelope tumble six bar crazy forget very canvas sign inquiry copy","master":"4c8765857e92661d69dd8f64031d43df4e1043c786f1ad7593d9d6cd7967b9eb","seed":"662aadea06a5198cb230ab83449dff0514b2addd644ff618647ca788cadae3872e19becd5e8de5719e3397783cda6ab0e1496e8a204d3ea8ad524ea93a1b71a2","priv":"a1d833122e4bbf53a23695915b9f398fc8681f72cb68644ac78f5b0ed0b0839a","pub":"03620a954c07b3e3060414ee499f68a904a8afe2f7f3ada8a9db2e039302a1ac0d","addr":"9758f18ede0279601ed2cbabdc5a87e0858c0f01"},{"mnemonic":"robot lift decade april style rapid thought modify tenant wild pottery cool","master":"d43dea8679ea3ac6440623974b253ec2355e97697557c8d62b5a79eefbac54a7","seed":"bc1a90f5410aa2fe22248c19110d3bba802378c5fdf2f3a2eb379c767b3d222fc2ed5d4638876d51fc9b44816c229673694b3f3e8052257f574ea50fd6d7a73b","priv":"fa29d04ce0480d48e6793e227e142330aca85e4e91ee9488396b1b2af13aa160","pub":"0342e19701eeb5ce20b17397457db9105c092d00db7250968ba38a551fb47d3491","addr":"c8ae52e691ce5b507a152f47970456570aa6635e"},{"mnemonic":"invite pool cross silent empty jazz change smooth appear snack cloud lawsuit","master":"0ab641828b6b935da8bfd58e4910c6c3fe8cff9d18548f86bdcf7d501875aab5","seed":"4aca0bb1ece15e686bb9f08a0796eee1830b9d926b0daec50aa9e280ea8eb522f546c1668cc2e2a8beab636eeeb992569a8a8b50e2082b5cb6bdf3195a2e8376","priv":"621bb83e46364ea7bb3a1942dd857213f49077ebfd735ef33095843e11866388","pub":"036a6b24125e8cbb887c0e9806e5feb6555f3ad4042460f1ed85e8a5738a02cd54","addr":"24f1dc90e9321c1faa33d3b2fe82665b402d4e47"},{"mnemonic":"current exit average case novel nuclear recall unaware decrease maple bind acquire","master":"a0a9d482c7bddfd3a8bedc54779098ccb0c54829e7949b52969a76f4a67f1ee4","seed":"35f2474be8f9068d91047c19ea9f1471aef87eb868804c5c205692944bdd1a3ac62ab71e052047961946d9c371da2039e89cfd77aef881d23774f10b24c3e16e","priv":"75684bde10654605f673ba3f704edbc2329997c9b15128b5640b6c4e3ca366af","pub":"038617759898bdb797d411a87d1e55024fde8a1a65c6bc0391a8deda099f6f7fb8","addr":"5785b3440fbc82cef8b1fb97c8f8e62a590b1842"},{"mnemonic":"tone engine property lion used spring enhance need choose grid deliver sister","master":"a0b23f0ebfd072c71a27b964ac5ac2a58fd31fbb1b22c044631fae01b27a425e","seed":"e47ac6612dade3bab1613b016b271eae20948c7934b08d8ba5ad0d14da1417b27512550287853c6c71efbf023b8026d015b063696d562850b991664ea8bc29fe","priv":"bd8279824526377e70a20ab1ea2731f815ac8975ec7ba5dca90d54859143f409","pub":"02dc15779fe271cc197da7035bb0886d2b44026292c137f6cfa8c98624665b383b","addr":"8271679fe371b6ecd1e989a2fb2d7c8d981006f4"},{"mnemonic":"nut solve indicate dolphin crush bike puzzle outer mask bring dutch city","master":"0aa08b93b1e497f4e54d6caaccc4769e921cbf9cc155a5b8877beafc43884c5e","seed":"c7c692ed2dba467ca28d1249f4d39a5c0405a54131245312d05597ef2aa31af3bc6791850693123f18cb1c350fd79c1705e53ffee10a501b82d0cb237d256579","priv":"8f9835b154157f65bed179b6008a352b7ef7d5ce8e21227a22c461294a7410c4","pub":"02da01e33c91da079a39cf256db26b1254e132b894abb9f07bf01118b5b6edf486","addr":"3ca1fa508b336a46f89231ad841a5a14d026f5c6"},{"mnemonic":"inmate snap bullet curtain used blast fatal one join owner route absurd","master":"e4003c062456105b608885d8928bbf183aeef12a48d6e3510dc7f183514a5195","seed":"0402d1974747f32f00e4cc90795f28d6e07a12cba21f31e22e0eb269ad1dc5fc0ad5d6ed1b5d5268dc50e31fe78b7145546de0cc1fe7afec7f5e3831863e21c3","priv":"8e55c05a82e8fcfafdba94b07dc54940cb247eebd1c689b51170f4ed10628a82","pub":"03637d8eb1c87329d9367ac73d1f65e482bd13b072d791f5fc6c08fdf262afdc8c","addr":"23d0d3d1abcb6ec683851d8c21a1ccf5941f18d4"},{"mnemonic":"useful panda fold short about copy hurdle vibrant kingdom draft suit cat","master":"9c99df0058969798ccdfef6b053f61af2b6422e4c691213f1f0a59f4792156b4","seed":"4fa3755fab5aee41e0771c00362701451ac578a9d7f8b139d9fdc043b33fe3566576a7942b904047978bf6a6360181187d9f20bb3475c495985e39ac7fcb8987","priv":"2b65da5f7070729879787dea803a4f50e2df1ae69c39263525bad0b5c994f86c","pub":"03a457cb29097644eb4a8eb1713fdea43d3992b2b88dfd41fbb417845e2d373ce5","addr":"901ed83b7220c552c69c43d661dd468ed94ac9c0"},{"mnemonic":"intact pluck author dish garden frozen speed grit bar narrow across loop","master":"548d4844add02811ea1b60ea7a6c337883e818ead83782a7b5a652ac038310c1","seed":"6b3b40cfaf38ae1ef9938c621264cd373b7e15d196bf9c69ed6efe3f7a7a13900b3c89eb915fbc99457347832ef1b816da26cbdaf8bc48c2b8a634fdd8be2346","priv":"eacaee29cf8bae543732278774ef2244e4da49dac3d88fe11fd7ff50875ffe8d","pub":"03d4d894053c398cb5dacd431a03c673a4f883781d951254fb398a24de018c6110","addr":"0b0840f26af38181ca7f65b7fdc0a3309c28fc4a"},{"mnemonic":"equip energy remove soft alter mammal valid van ordinary motor follow buyer","master":"6110f719e36e14190eb39d4ae66ab2b35bd5c3fd2969145fa3881650556c5384","seed":"74163bcc1522e148a87a95c78072359a600b364eeb558d052b722e5db26b6b317a36219edab7558cfdbdaa6d62c7b078c691fcdf2acc493139a75cbd26ea3bd6","priv":"fea286b716369fef22c1c5ea7da50ad612868d81c50f5efdcbc2891e21328a7a","pub":"0269bb65b5d86befde40cd916410790f9a959c2f3aa3beb5efea2eb358eb5047d1","addr":"9ea73e16006fd30dcdfe1ecbfd2792d5001ff8a6"},{"mnemonic":"limb boring random already marriage team useless polar impact equip rely sunset","master":"20c34a5ae5b9f78bf032d7841469e27002583c800d4aee849860d58213210c39","seed":"848bed01605f3574c16480514ca0cac72c21412fb6ec38833f97fb744e4a975fd06135c4761aad05d73280bf2e1c8297769e5cb69299bcd99e638e4dd542c52a","priv":"59f09a8926377ef066a13627f032d2e700795976230ff2e58806d046af0450c6","pub":"026e3e1e7ff239b39eb4a77477b32d492f99cf1f611558885afc7363f3173a8a28","addr":"61dffa0563d51aabb1e2e585bd444f99cad8d54b"},{"mnemonic":"vapor reflect friend jazz chronic supply awkward tongue venue finger island brass","master":"4dff50c5a87bb1f9d2c0392ee7eee59977bceda605a40c0a111ebb46587a0ab8","seed":"e6f70f78b981254b4e3061270fa96d262d2fccaf8dafd752db2d0fb54f943ca99f49eac07d279b5875432dd7c0450a7bbb776e8852e5a5a82886c65803ec1698","priv":"50273043958c3d7cab07f41dba28080c507f460ff920c6b5b135d1c64dc85469","pub":"03ef40a81e58c08d1bcde1116e9e748eacc38906cec057f2984fd4bc91081492ac","addr":"a8aba313467ada95795757ab9a6661395adbbd33"},{"mnemonic":"top base town abuse shiver symptom green thing vast eagle steak warfare","master":"7ae7456584c905376b6e6f6732b8890baf4d768e82dbde95110effd229dabf9b","seed":"f88b915dc5753ee33855b3adfd292bc56f04e8aaca117023209877ac8cda5df3218c969f1491bd0eceba11ac433016a05a9aa68d6bf3fa59b51a5cbb224c902e","priv":"ea68890e0209f3444eb78727cd3f13dca20c886e8bcd6d31689dbba04d000a30","pub":"02030607d8a2bd18f8af9b67f99db31585b7a879d6f08588aafbd18dd95d1cdb7f","addr":"fa202ccc3db92eb55d45cc79891bd4be395fe4f4"},{"mnemonic":"picnic seek ivory unusual text become room artefact rigid unhappy wall harbor","master":"05638878665f27362c8165adf4b73fcba3cedc983be2f0897a333378f53377cd","seed":"8af253d6d848e9737c8b7807d37558e5a1f09d3a14eaf5794c83c9d4f2021166aab7faacb967eee25714553003cbbe0c0eed9487d4499bca430e709f0b8d219a","priv":"1357da6886941f1c50a19bc3b32a174acccb21a0415dd5a736e5d679fe505f0c","pub":"0333d6d3cbce04e1ac26ffc7c2d4323110a038dc33ce293e95d2d34d11bc1d4efb","addr":"c5aca5f8318f75bc143edda3eb89821e751ce0e7"},{"mnemonic":"faith box profit long entry that alley stereo wife nurse tiny assume","master":"67457c024bde2135b9493124ed03d0f5f30a66530c958693f02e463982362395","seed":"4e22fc62d0a60e2de3ac33de2db8d4a884905ef84071b190f8d43f57040686eb3476fff7a90d19b1bec66d8a2e62532501ac7914585ee5272c352197ee0f0ead","priv":"ba198f97576c66c34196a36a04172bde332ea3c6777ba1af203b68aeae3e23d1","pub":"026aefd0f79219acbe5377bb3578a38f71174dcc9f77fa4d1dde3f3aff35ad2f10","addr":"44c4ffa77990259e15f2b9dc59223c5807c85f54"},{"mnemonic":"brother bar food vessel shine object tape acid opinion brand indicate local","master":"23338d7c853f4e76208d97bf0c47db2dc317cd4501cf00c037e60461eb373353","seed":"e32c6c54ca4fef48630e4dd7927634ff1d21c60fc488e6f1b87755d3e79f4845a3d9f86ddfcf185136150b52dc2f721b04f2d61913d63461956764487fec24bc","priv":"3d410ce752789e05c5e02ba5e95c2765f77208c90cf32f289306204f82d6eb77","pub":"02a795076f39164eacecc80ce04d63e5336edb32d183c06dd81f50e330b6102c11","addr":"b2c8079676ea7d98e10b24d9a09e3d4519d32d74"},{"mnemonic":"broom together virus run require inside output spray day hour cruel witness","master":"3ec636201f4b0a0fc7226003f1744766875a0f8a76e19d69c6c352d86c672cb1","seed":"51bbd8710577f0a2eedac3e341727d975b0e79e2a0777766d43b0cad8b66e302d1dfeda04a6a5ae0683db18955692aebc554c4bcaffb5f9be9f4db079a550f78","priv":"9063c803e2075922b916efc668be57b734212ca8ffeaca221b587912426af4b7","pub":"02b66afbfc48ab4d97a0965e7c96582d2c4cdcae965f8aef72ec98f59b31d5eb7f","addr":"b18bf07d9f82f070da34d8a4e58fd6cc4125d51e"},{"mnemonic":"crash knee output divide essence fiber benefit pig recycle patient strategy already","master":"eb84eae9a804895edbc89020995755aca54a04a4e7b59adb96b2ad0a8b465a7d","seed":"4aab7e57401b6f2dd6502dec26ef36e36d712ce328b5190d73b9055a118c5ead12dd5f18829affbb488a71f18cec672093d58452bba1ec3775739c1169901e67","priv":"0d0ebcf8cd5c075d9b8a2d2e404d44701fc1a5dabfc5b3cb50cae523f3c4c149","pub":"0296e9cf1cfe73a4114a1afae2f05a6a92da168113764431fa57c25afe32258d8e","addr":"8aadd8961827385dfdda784993f8f135a6678a47"},{"mnemonic":"shock assist horror regular voyage gadget cook pipe hair boost release stamp","master":"74b514c25d4fa22f3ac95aae2e58824da6ea181962c52944256a8b80cf86e980","seed":"0a13bbed1d4d3d6128d1eb0bcc0595a4c72701c7e9b79ee6110a104e10e20656dbbaf2993a7a06381e9ac424c3db6b0e98be6d5c2817433660256becf295c70a","priv":"75da3f78a45cfc4e9318d5dcaaf6595002ed037605ca196282dcfc18c5e6eef2","pub":"037187c0d2d573d9c28cebed9214ac37fe20c55ac56ba565fbbf7dd79c4eeea519","addr":"4b79f08bc7daf43ea00b5ad88b7642c31fdbdb17"},{"mnemonic":"monitor artwork plug dream sniff sketch oblige prefer dentist rice degree trip","master":"e8211a763f0b7f2f0085047ec1687f9c37910d27d8580696ae843872a7cae0d9","seed":"0a48851384b8dd7f8c99bfdaee23b143479e589bcced7ea423f6fc5bee68bd5e5c45834e3f2a7a1fcb928781e37e2b3078d683c15dbcbb5032ca31d3425dadf1","priv":"8fc0e10b570558eac1349ca8ef4f47b2f6d3f148a07b94bb2f1040dcb9bf21d2","pub":"0341374d25e701d963aaef0316ca0b4f4c15283f6b8b6932d954cdb7d7af4d7bd7","addr":"9a4cc3bcd48d6998280db5cfe856f7ed85d6b4df"},{"mnemonic":"bus deputy eye shell isolate judge nominee later gift mouse leave square","master":"cf814d6a08c10f4f771f670120b52cb26b6265a5510c5035d5bab583bb7f314d","seed":"9974e3131ea54805d6e9cc124ffedf80b0ebf935cd0908c4d8d7a3b777220155c056f12a7cf3c0c6e58b7adef792215cd471c080e9f11ab6cd4776ad86df9544","priv":"ef857601132267606922590b016b10faf2405f7ff92e3d8dd73ee6843f0b3707","pub":"0317f408e6be956b15a8e9706287e6bed905a008e8d4705b6c9b6e7f478bbc57e6","addr":"70cbfc88189721a264c3d21bd01f2eeee8a245bc"},{"mnemonic":"toe present claw afford agent render direct december model skirt tape soon","master":"88f5eca5b3519ed612f9f7b15ced098565559b85db98cc57979dde0ed818bde9","seed":"d776e445d7541e997584381b5d2eb066b99644275814961daf748a76a84898c21942f23837851d387f0fb6557a0f693d98e4d23214ed34630bd74fa808b36668","priv":"6252b6cd338753e5cb6745e7ce92bb661fdd373e56796722d1766def72b93ab6","pub":"03dc54c14b80e91502c400d6a97562975ae0f967ee0a7cc5618ac0330855ebc688","addr":"afdf4a2de468ee8b2d47de70d52ad9a3239b3f42"},{"mnemonic":"save rich wage off orchard unfold call frown idea jungle boat oxygen","master":"dfff9a17815e298cd92e9a2c5d4ccce14d3df12af9b9c69c4aac7bd297639ec3","seed":"7d25dec6c87f92e685124b901b0ad423ca3554c31db8583d205ec4beb3f42c4a14777ff4fccf830f5641ff4c376c772a8a1273060d58c22b95a51f9daa812a2b","priv":"5e962f6e9e6e9ed76b0f3e3174ec9639996027fb2bec3fb47faed79e66c4fd6a","pub":"020b08249515846a566c2c9616894ddd6c2239c58077ccb2f2e7ec5a8a140ef293","addr":"dbcecdea56d7e5da2a6c96c1f36242e87416f221"},{"mnemonic":"claw ketchup mistake lesson drill crunch unaware captain perfect spell endless manage","master":"bc0c9ff880973352267788cd2e1882dbdf5613a8460414df0e570a099321bcbe","seed":"4b9cc68aaff0b0ad24c531e990f9a9b7d7076dda27cc2f21e8e75bce8f65f2daf1ce6228130bd2c8900fc677313ed4cce1c47eecf24fea0c119f70ad6d3d79c2","priv":"e36db8076b37e0d3785c550e47ccc91462388c8249d160df13391ff06f40a30c","pub":"03895e970001fb0b3566d8abcb1a3df46725daf591e6cf981c1f06a81eb202692d","addr":"6548f7cd7b619dcc8685e59456ecddb223c0bc45"},{"mnemonic":"canvas black between chunk wolf resist again joke club moral fix spawn","master":"374f2b9727601f87f72b70014fc10a38c5fea6cedb36246103e0fde2d356f7ab","seed":"217881b165a67d70c9ed44d81a1100cc829f00a0b3782d8ccd8429806b883eea17f900ed32927a7c8fb8df34d75d5264cb5704208d3dc336444c199b9cd4bd1d","priv":"7e6c83d4d58e7a55e9882e6160238c6fffebeaa89e86dc9785fb1626fd22e8e8","pub":"02795b9337e8dbaebd288d1f0d833d51a4969b0ff995ace05c329fb6d20ad82425","addr":"7618cb9305c15c8ba122949bc298b3d6daa43ef1"},{"mnemonic":"dismiss rubber stadium badge enable exercise collect globe another survey own hope","master":"9da347a5c2a00a44e9bd39e50d80c106a9f885f8c84f5c4d90a0a75dfa5d5508","seed":"7038ff726fcba91488e5fec28d436e7a2e7c462b06747769f79b785aac64164eba1ea5c125e6196b9430139d9e21af8cfe10b51a09577ed510453487cc1f39f2","priv":"86b04f6848114854a1b207b44d9475c216e63a9b051c44bdb7be3eea9d24988d","pub":"02c6e822bfe6255d841eae33f62987f9cbeca84eb8dd1dd02b2daf9c7de7f36371","addr":"bd2a4f087a519a3469cbdaed704221385a07acab"},{"mnemonic":"dignity tired drift feature file salmon vivid wife faith title direct toy","master":"ee03e61a429a846453557f202766fcdd8a3b408c00f3430f7b3a1c9bd88a7d11","seed":"baaeb3a06b419a7a9c49a99e712c11e87a7a4bb34b26700b1d57e95177dc9b6b2d590878111e14f6050e73e5c72239a1562062d1b8e4c8ce9ac158aac282c2ad","priv":"d1dc95b42024dd0c10e8b5f0aed5e5f7c9ad0d56636da91bfa910d6af2124969","pub":"02e1f4ba20c8383bf512073e335400e1a1b1a103cce9450864b9087203dbc0e027","addr":"3de51323a7d40ab752f2b0cda1c17d51cc477369"},{"mnemonic":"legal sword liquid clarify utility depend romance cement trash whisper endless parent","master":"7c61e0c0e85873e8bdf532ec5906b8be283a002114b8dd4b8d0154054b6f40b2","seed":"21ca62d84191c141f6b9890627d6d216d5373ee0819e7c618e4027e70395c2a4ea5702aeee5b844a99eee4fedb85bce72f7d5f57c3d670308e1fa484108c4862","priv":"d6ad713c9dc2cff3e55243729c56485fa34ce8a75c4e011f40762ee000dfdcf4","pub":"026c7a44022f2892f2b2b091bc1488e547b8b52c82c2a780dd6603f40261930d3b","addr":"c6c4dcf4763d9908a46ddde925afd86bbffd4719"},{"mnemonic":"tragic inform salon lamp tree deliver sugar robot torch collect choose nurse","master":"77e88aef57f8be3507ce43c1e47dfb86ce0fded4a6d9a5ed6a2c6711a0a83216","seed":"6670f6815a2865591e6f9ff5c1cb775eed9fd45d53d1ff3f65937425c6bb79403862a398b28c7aca032fdfb14f96b238174cf6353776321631bfe338029ac148","priv":"7907a31525b26f89eace8cc0b988a08f8feff4914dd8f692e24199c4134c6fa9","pub":"031af666b3e8d5da1684fe5d585b8638fe46cff1b1fa01bfde3b2b8e2ef2aa3a58","addr":"792001d0cd191121043ef1434855b85b583ecb09"},{"mnemonic":"common oxygen toward security mixture swim elite issue suit welcome ripple online","master":"f4b85ed364ae42dd7453f56df2731c194a203cc06a8bbf71a2498424d7687631","seed":"9f2217e5ef1a8691aa51e914411a5ef5bf70727cfc7d0a932e1a9f7d298a657db8f2f6eeabe881e8f4f4580a2bf1834ae888cf7b3bd32820448007769b310724","priv":"2f98bb40d987f7e50966b15d2bfc89befc72bb6934aaaa2293dbd9bb33923268","pub":"03b89c51d6a32cdc56e334997a0bbd57deb010778d62024f5012ced0ae184e2464","addr":"2ecc6f88d71e3b1344a7fdbbbbe4fa60b5e539eb"},{"mnemonic":"kite warrior idea engine trouble swing route main like burden divide drive","master":"8317ec95801550a748f5215d6e83cb12424635d5b2f6635a78a4a0311cacc56c","seed":"f406f2ef34c3a4bb64622dfc4496a0b6183f1b7c1f58bd28d3ad863ccaffe171bd6164044ff5e940650a6bef6c290279b41d80336cbd9592c1a3b326314d44f9","priv":"4fc699bea9f32362f74b1cb6e445b1a8f3df81dbf1d5333dabcc84305c355e9a","pub":"02f8b8958f9edce19f8c5a50371dd079ec4b4ad6f6a9746451d4024ccd266829c2","addr":"8fc3062dd0b1063eecaccb75e14faf5b06cbb939"},{"mnemonic":"toast health connect merry resemble slim address pioneer crop orphan keep dune","master":"07ff519f3c3fd08b9de16a26197914867d4e42b67222c9ce863ac6b176bb5909","seed":"5e80b7b4b8b388522fc283784f368f5f7875ff7b412af6c3e526ec1426ad4164e0f4921494ff28a258787beade935d472cbad9f48386c2d7e16f8ca76fce769a","priv":"1158d4b986fa7e05db824694ce3379b63f473161c965a39ca997a8e3f3e7664e","pub":"02a3a7b75a8532df2afd58bd2dd434603c21a0aa4081f8ef9798db401372e32bbd","addr":"24c8f405da27ad41be7b0c62db63f80226fd6b58"},{"mnemonic":"cube shaft clever hard fuel review enhance short nose again banana profit","master":"30f3fe7efee7a0c7eea064bdb63f509182f0dba45780dcbebc5f3374d1b878f1","seed":"93774eb188a6ef898e534aaf67c2ec9aba02f716eabc0d193bd5a035ed8e0eebb2e82fd3ae30bcc24c44d697d46296e5d307060420350a4294f3cb639a48e6e3","priv":"857bcd096012a98022b2d30cb926757f0afa9465058c103b70fc931554f2d360","pub":"02ccbe787178d64d347a4f146facea95d2d01cf353ba04cf7cf7325fba6fad3824","addr":"d3dc220b0c09ac018fffe2cfffb220410af0c0b1"},{"mnemonic":"weather surface use rotate entire foil female carbon once kit seek athlete","master":"68614cd2df975347ef5c7efce4e416821a1f1916ac54ba994f6d69f8f2860576","seed":"478f798d52999208d3c8c0feffa78c6d56406d59800a701c996b8c8a9b193494aef1881e2d1f8aee0a5973b722fc3bb3ba007187a377a64b13a81d0560cb090c","priv":"6671cf2b354b61f6410500e26cbc94afe78392d3feecefbecd6e60c6b1a33a31","pub":"032afb4d170e89e8c89c544ebb404678bc6470d26bf68dfaa1c034edaa85a9bb5d","addr":"2bf3d54106897da2427b1c4c85de761e4546564e"},{"mnemonic":"car rubber ocean miracle vault brave goat eager dolphin various infant receive","master":"fa86484b17c9b62008647587f406f4daa107c6b95e708487778865c76a31e330","seed":"ff824d733d160e50a156021b256e4663f9ebebea1530358d70c205da5e7703d64ca4f3d941043787a68fdade5143d993376b1ddc9fd6037a13520e8cfedb790f","priv":"bad6b6ee0a3aa898466552b2e5df05bccd7d0861e3368f206d8cbfd2ec8e47ad","pub":"02ae2706cc6a96f31da9cd46d544ab142a26ebc6259e5e807065fccc251b26c603","addr":"a6ddada02b29a165a86a8bf4a01e783640e5638f"},{"mnemonic":"segment nothing burden boss obvious find kiss join science dinner clip wrong","master":"64a4c932d3cf62f9bcfe86c3b709ead38ada505e944322b93e14022c3ed26e18","seed":"71966dfe2434f4dcb2cd1bec9090ebd20bbeac2ed54dd8d081a548ce7eb57f1b17cee242581cc893292ff9ae4e5526bf9e11034688299753a6d0bab024ae9126","priv":"44ddd6571ce3582ae17ca9c74ed41811a760c7059dfa7ee88f9ef76960e30328","pub":"0288341429320e6e7cc35df266cf3929e93e843e911f8ae0ebb2634132de1a6f49","addr":"4f32c063b84f9895d4411ece5ba0c9d2e94631ed"},{"mnemonic":"cake volume physical initial phrase false pear poverty bonus steak rebel ketchup","master":"8200ce644e28680726ffeaa7d949e23feef136634b58d504e34cf8b2bbaea439","seed":"8f6577cfd936a64de1c2be553f66b8e5991e2cf30c42181c0f7eb527105c19221268e3268aa243f740733748dea3c0ac16320305c401aef7cd0986f3dc6ed978","priv":"ae37947a92ab4e9ab9b4e24b5f26f710725ecf848f0412b583b8701dce4b7730","pub":"02ba33804bdd8733fb5ae1ce1758ca55c8bd9e15245d646e8f737da2d61758ebf2","addr":"1f3833c0eefb3d46c693b0476470d97abf02a792"},{"mnemonic":"outer meadow velvet fetch claim forget token fee gadget alert post pelican","master":"a991420cafd20f348c847780fcc2128888771f4771cc6ea137099616c617b1e7","seed":"35cd93e8d9c4651799471d4cdf2a2fbf083088b93f1c1bce6ba4394ab6239d05c0bfbf8d7f8976be68042e1c8267dfa7ab3008c967f8d1ae0793190c77077fa0","priv":"e4fb166f29590fb4a5c5484729f038a62aba50fef189f1e3769fa290e1800790","pub":"02e123798016f5eb1f79f633588051def8b59c27fd3973a7f2012db1a8fa508ad1","addr":"45a62d3353b39439d002c307c8789ac70adb69ba"},{"mnemonic":"flip expect rule wrap cousin fade example ugly crowd monitor cattle cable","master":"d5c2521cf1c8f3dbbf955477a993552cf7f6f0ce452bb789806daa0a4dcf192a","seed":"b08a8f7dde39c9680c07ec31ffe80377ea915de328fd38b81525e4f694ef0ceb630e7ccc19bd28a03b7061b194f2b7758f802945a7e556d526f25bf2b4d5fb90","priv":"21a41b9d3ca21569e3b8638188633a7be8e9b54397964a65bfeabc3425d5e4bb","pub":"03cacee92e7116a6012c2b3002fe67d00dd062e937393895703e010d5ada98b4cd","addr":"b3a4f2cdb4cdcb64f1434f3f1e4c20bb8b952116"},{"mnemonic":"alone absent senior wisdom sheriff siege harvest coast van skull want quick","master":"74109213fcb3350c4ebe081116bc7570d00bf49cc7cbb90cf3b09f5d532a3d97","seed":"7d111179778ce63cc39879ae303814acc25afca8eff930d3ddfdc640d7b3d8c1140429a75c6db52db96564aba0bf0c8d9e4cf78fcfd703c1d219c09a70d8569b","priv":"96c3356e90906a9b3c523a3ba61d66ec63d9bad5ccd23edf923e3c5e4c995774","pub":"021736b932aa1eb90716bd8bcf3cffaae73392a37ec114b34628367f8ecf1b35b7","addr":"e8951735e9840492e0589a885968f12b044067de"},{"mnemonic":"fall any bamboo energy ripple flag rich arctic argue decline auto pottery","master":"4b3fa55e01aec7bc6d41a890d8aae2d69e617bab49f8529beb38aaf835d15a69","seed":"aea9842051221d0eced61932fd18a5f3e1ed8479159c40d16e886699a0f923807b91df0763a5d9869fe9a159ae0453f8d651302a186bea4ffc120c2902012d3e","priv":"ca5c56fd1b4e7e7bf623032e17a186e20b22fdd49a4d29d9bed5edff206bf26f","pub":"03a8fd0ffee636d66a64cdcc6032214efd1c069491085053808d03c1ae83b9fe96","addr":"ced9d32eea230544e0f8095b39b0a4e18b59937f"},{"mnemonic":"over exhibit wait carpet pencil record post duck gossip vocal all wife","master":"6fbad4c20428a892a365ee50dc66f8eca7773dbc5ecc34f85619fbf1a73822b7","seed":"f998a57ed4eab4d8425d4a71bb1fa451d7a79c8dcad33e18f90d6a4506f93b2adffbf3eb887adda7669c0108e444548a3566306264a76dd4b0955af27cb9dfda","priv":"bdfaebff9d0fc673539d8be5e59907647d0050a9241dcc4aa24c5c26eda0fa60","pub":"02d32a22a05926844a6b0f2f677520bda4c54e6b2c9269ac91127b626159a9dde9","addr":"60862548d4e283f62ff8aeabec3f25891808a439"},{"mnemonic":"spell illness engine habit bike able chimney spoil know nice tunnel weekend","master":"ac366b29da09441f12742ab837cab2a4636e1b50f11680c4e1adb7d337dfd8da","seed":"59e69d46ac9f2a9edd9b1909b1e5ad4b9fd2b401d48e95eb43a0f4f2bec0e6c60bd2a263e58bec77dac6f6ba45db1345cf9d74593c6e0b5ebe3fdc7c5f24014b","priv":"05d077b8eb1163a1fe2e5eb3729ffc7c1327435d4ac48db86c6db5238d5af45a","pub":"0364973fff68be7b91de7858fb35869decac0273ccadd7ccb45b057ad7d7e9baa7","addr":"c59c857a493b2b81957f4769dd9b7b5a934acfc4"},{"mnemonic":"thunder fabric basket stumble file sudden effort congress process essay excuse practice","master":"6c3de9715b71139a3a352a1d0b272aa0152402db4b8429c32654755430623ec5","seed":"eb8d579bad88d416336e6ed882bd8a57474cc5ba30d4a20e426c29a78bcb27255f6a6cb50b6430fcf905111f9b9fe4e3d4920d563887dbba69ec74856ce4b79e","priv":"a38f2fdb79ac8a1d64f613dfb3cad99c9f06554cb05f39b6f60c52eb7ad888d4","pub":"03d548248b4afab15ed5e91699d6e13fc4401d6779ce97b3bbc833c690302d0049","addr":"fd60d97532ce397f4ae9accfa99ac5ed9f5a77d7"},{"mnemonic":"twenty fan benefit benefit life orange crystal matter index drip mobile matter","master":"08a9533038e137f0149a965d12c1c90d7f6846107dd626027164146406c86fc1","seed":"d3f6d9f156c814e0f77fb7e9aba06ac2c9c3ee171b2d0759e2d91fb5d383f862aee8b7dff8c62cf61286d8f7f374ce3aeae7ab36d551f802523dbeb80673e0f3","priv":"08bd659717169756d9d66e79aa2b51d2b539f5c453ac8abadcfce3d29df49e7a","pub":"02e3885a7d4343012cc76314876fe67729e434202a28525bf69ce27a9167a46385","addr":"f3181c18f63bd74c4ddb37a4c32d0985e0af010f"},{"mnemonic":"scissors foil oven finish exercise typical catch dentist lens dolphin flag warfare","master":"9db47325d363c87e509aa52701131ad236317ea04515f4e24ba4f87cf99b2327","seed":"0246e8cd14b6b8f01d35aac9c09f8e526bf9f05393c5e1e77ddec53477275dbef74add79ebeeca7d081e58272f4a1bf1fa8621894a8165dbc681b967d84ed10a","priv":"6e7e4b51346f8d1997d81f63dbb7fc7bf4f022bb3b5ccda9e5d84c4a5c97849c","pub":"029edfb5c989c002795c283f445ef4d673101736c25617500f8fe655e043ab55ed","addr":"2a98038648503b442fd77f4d05a338da2062cc69"},{"mnemonic":"monitor vehicle bench chaos stable cereal acquire shock image purchase sadness hundred","master":"bf5d7680d5ad260a89229451e6ebcf3c45988a83df6740fff9b557eb3afec827","seed":"5bec19e9219360a8de56fa85d593f5330ddb158205d25d00d8a2307f6b420f11916311e104dcadacb638f5434e98efc8551d768586a0d8d9baf2ceb0759ffa98","priv":"470256a6d68f8de27b0aba26684cea4c075f384bcdf8a68bf5418dee37f08dbf","pub":"03a1193ff722ba3b4bf7d257aca5c184fc776540fb139dd9a404d3743d31030971","addr":"5b4796167bc701e5182f16e2119d7e9d491881fb"},{"mnemonic":"never dentist blame parent sell income parent bullet eternal random seven urge","master":"665961de4995f001085ce2f1058422bfe5ba0132cfc5725f0c5c9d827020663c","seed":"79a95f522e50cb551c7fa70d54c0aafa5b794512be4e91de2fe1a2e9c17d76bd55087621a606107f3fb19486f15dffec5947cf16405304914f511dc43844ce97","priv":"88db51c0d63c95730fad0c616e4d4fde5a631dc3d315fc74db688ea1a7ceb5b5","pub":"020ebca88011035818999fdf69ccbf691d93cbb6bda65c68c0f2ca10757d23abe2","addr":"9de8cf2beaffcd389ea6dcd264444aae075a1590"},{"mnemonic":"noble shallow label region age proof remind panda useful session poverty open","master":"a8e1a3cf36520d5ae852890951b03cef3902f9ca168cf53c4ec6289dd802ad8f","seed":"0cf4cdddf1605c5c895c1b81fd523ee83239d42feb4a130105c2d5d1fa371e00cf34030cf02ef51aa53596253e264da2c3ec220b97885202dd73a7b5824b982d","priv":"5ddfdf68cf41919145c9c8624c245ce9d6d8c380f5d0153b6155e92b253b1b22","pub":"037943f2b34206bfcfc1fe236c77f6e844d98cef04671431a12883e23846e8e7a7","addr":"559839fa53e5b7408f3dbd00ae5e80f56042417e"},{"mnemonic":"hope inherit quantum text sadness dizzy glimpse cheap expand legend kiss once","master":"c307e0a3f22db3e59a7b28b931c1ba0daa0a8e8d743660c48b6babb4b9563702","seed":"6fa72118b297f2bcefab29f19ad4b701791f72cad287681e2af3e92595ec6b9f7a15b08771917d1754053d1e74aa1a254fc3d6e27deb78b7b55f35a5154964e0","priv":"1a6b9948bf4b717756a11e43847be38ae87b0f42d718dcfbded3bca1a8852aa8","pub":"02dc42929ebaebe447d089cc702bd8e29457a2619047a1d7c80cc4f2639a82246d","addr":"bdd0fc12beaef99e0ee5b07c9c2f41bd90163bf6"},{"mnemonic":"smile odor upgrade deer mistake bomb friend ability then segment orient nerve","master":"17c87ed5d20e5089408ac7fa68024124053d46bfe32fc04ba06801c45b6e19e7","seed":"f620d852a56ab0eb7d55d271034b767eded17ed740ada7f8330fe6d9affd8d88e44489de06d6d3f7b84b294a847334ea051ca63f0be4742667ccffc79031b5d7","priv":"8f90608bd45f866e9fad2a6a316fed6bb6342815ed79c967c3eb1be727ab8aee","pub":"03b6b746569b0ce4b97c3035634a2b30a519ec23a78402137c7ec395d35c4eedeb","addr":"179277829c7cabca8286a52ce3cb591ab22fc72d"},{"mnemonic":"black ghost quit birth dial helmet custom brain diamond rally local season","master":"8a6f8c836e3e83ba6ed94a9de24e1133d4b04fc436827d810c23ee1ec9406fa4","seed":"6488a47cd4123eddce9bd31a0982eb0ce8208ed5e331081dc18256dc8b5a1718807bfa267ae6a75bf1601b99c784542c3d981a9350f7f268d2666af3bb8e3680","priv":"1e7100a43845319b4bad268d111eb3746f09c9a005e023c45fd1da984d37e49f","pub":"035ed8c0324e4956ef2fd2b5141260cb6dbc0943708b0f83c0bca0e7297a27daa4","addr":"d2d9e9b6ea946a61082fe98d9b0a808f5f0879e7"},{"mnemonic":"advice uncle change position drastic leopard praise rack match toward paper faculty","master":"9583a2771931234cdf27fc8a96d06766d4c76b4bd25247596639dd21da4c95f2","seed":"8fa5760f5f2d36734e05cedd78260e9ec7f837bf5b7edeeaa8f4f3ecab9a1f82ca557fa8d75d7d779e47a29eb7c974264d98d12fe7af6a22a87a70bf0031cecf","priv":"3a69d90701054f78204f1d3c959f128dbfaecf4ff0cf6c29fe5ada13c96186eb","pub":"038241211180ec347d2459f2c22c01b50fcafd8ec1ebb51b4ba648fe291bd71104","addr":"f9c6730eeb7a00027b3deb720d6c541bc6b0aa89"},{"mnemonic":"carry enter invite orphan file grain pact glance ahead grace action mistake","master":"b6b8bb3d43f27c84f1e3fb1ea462c9a88d8544b18b22d9b9c13379954a3546bb","seed":"a0078d2fa9187ecae2b8ad3d4121e2567695c1cf26bcd441536ce95a6e04b4feb41c1ceacb86ae9ea26db4eeeefaac7e0477eab711b22d5390be3eb3daaf97b3","priv":"7503c22dd0cad622d4337dbd7e0bea66a2e8b52427cbda01a9c5959ebe8b5a73","pub":"032c577bb5610ae703c54444865932db4edef3b8c84f88c71a25731a85515eb69b","addr":"f268151a05642b378f8738ec00b2e486e60e284e"},{"mnemonic":"taxi betray parent equip margin snack spell agent talk possible portion lunar","master":"5bba6a340254e9803fb2889beb84d4bc63454beaba3f10cb992d5823b23472cd","seed":"a8b970f56b960fb9888f03013542e90b547f7d60aa91218105808e595a561ed37c13f259692d3dea5d324d0c4142b30e39cdc2e60697ddb5f52a5459469fb31d","priv":"ae63f7802417743bb8bca410ec64380a407373900e0af51e6acd65ec9d54a0f4","pub":"027410f719925fc55875ccb78092d5e6c31b8543e115ff39bdfb9a26f97fca8859","addr":"da9b8ea1879e13bb49e7b9d179e5b56cf6de6537"},{"mnemonic":"sheriff marble regret shrug shoot tornado coast that obscure sense duck noise","master":"e97a0a9cfbcc28b909f7a5a617af10289965c6901fb06af76a6fada22e41876c","seed":"7a231c5b3b91408a19de9571bcd820f17451562063ad2daa85a1164a952aeaf8d6a3c703909a76aa1e1a2818f8fc36d8dee3c87184b59d6340201402384fb7d3","priv":"d3fbcac181c592367cc527d8f09b54e1a31d3b2c3fb5c1cf4f2ea897c483f5a7","pub":"02b3e3765ad7c3c020c6a166b0113b87279e66a53859ccbb9d214181e2be30ca01","addr":"517212232acd318b376fcface8544506a8f76c18"},{"mnemonic":"connect drum once first trip dust trigger duty situate burger toilet half","master":"073fb31a2785afedaea95e67ac7a3219f2f910aa01b054022a5185c5ac99c35d","seed":"fe3d1ba2740ca127dfc5bc22ab6fdbcc930b957185a0b16b1919e4fd5e637c053b3d356b12152cda6d07f7088f16195319075d0b3533e5082b45f1bbdb7d5a74","priv":"6a19f33e357328d40aeaab5323764bf9e12df8b476100baee9d398a0fdbe3970","pub":"03f639ddf3dae4ec84bdbda49149d2fc3461b2309d043c89eea46bd99762b54a0d","addr":"c8a8a454a5aad713670e936b63c519c843874b3f"},{"mnemonic":"shock later journey twelve any ripple soup climb globe impact poem auto","master":"382a7bfaaf7df9ac5cf8ad1f574bcfdb98e185847a92cc36d272b74a14228259","seed":"aa3bbf8521133a0fba514e54147daa2c6fe294b1af8bee3a6fe46ecd480983d72635520db97bc3631d9bdd55787b07e45d81b052522fb7330f4e0f6aa24fca8c","priv":"dabfdd6c702d104e4c17dfea719ed870c783dfbcc66e8987bccee888658bff76","pub":"02efcce52d6c7ae70900d892e1b24ed5af6012c38c15864f2d15067457a2c55f2d","addr":"fb3af390f0137dcf7d98e2630021061d0fbc9e06"},{"mnemonic":"news book language depend fine fabric idle curious depend plate fold sustain","master":"4c28a9f9d854290f4655fde6a91500dacb684417d8dcaa69435e1ab4b8f04e3c","seed":"2839463d79148eacc1d367f9ed0a2ab8ad939643f439c276bb47f0fbdb4cfe8795001ea2e5c24a6a6da9d35cc6759c37e50ce49f34498ea61a74dd11b14a6421","priv":"d6ec69e742e0146c9811de01cfcb07b3de56594fd4e374722ccf81dd143e9a12","pub":"020f5c54b785c5ca65547b2ba32138a47b8b5b462b304e0cd3ef981b407ee73b87","addr":"2850f467f64992626b23e03d366f34f4e6760807"},{"mnemonic":"equal energy inquiry frequent aim wide exotic tail vintage toy marble spice","master":"0fae6d570fbeb343eaad5bcd272d8554fe27a9cde389685263ca1020e65d4a1c","seed":"62aa467a7dd73249fcad8432d188e64a1d0f1591c66912f906eed133ca0c1e99eb068dbcc8ec37947cc846b1ad4f439821324c61bbb385fd91b2e440d6a86e41","priv":"1a254e7f18b0836975e187a72d0cf1d1b69225067167f44dad6aaed6065e60ea","pub":"02ce2f7840d3f69580538517852dfcb2932285caaab4d11adb98ccf335430fa50c","addr":"53117f2a5d41d6e727db2975c9dabb1d28708d19"},{"mnemonic":"recipe prize resource define enact basic glimpse chalk box prison approve fossil","master":"ee8a619974bcf5cfa95af842bb003ce4f5236abac96eacd51ec8f797bed520a8","seed":"b2d4c119da7c72c24542998b036b2e1c501b0fb990154d1b5abba4c5ab9233c4caf1a427948faa62aa862002f43d115f2e4d715b8c9ea3eb662b2514ea06390e","priv":"0d896d53aeb3f2fbe634ed280225bdbfd10116e18651b3c801a3cbebb0f75ed8","pub":"0320fd7d4c9c548c28d08e587f45836902f14c7380cfc9f8119e0b6e36089369d6","addr":"949025151f752888794030aa47854ff5ee407e09"},{"mnemonic":"hunt carbon lady smile luxury old empower pretty memory gentle public pottery","master":"e9542dc3733e40f7c1e5f540e241dde57a09f76d28e889f69dba48d63f0b6445","seed":"ee0dcfd61e0fe95e1e0428f29c78076f302cc5a55db61c13f9e6d84811bb0d57ba3dc109d4d98fc30c1d2e5b25bab1c646623fbb00e5b3719e4bfc58005fcea9","priv":"e846c35be2eb1e3781e8078d8433a9816d8f8701131e69873290689940617de9","pub":"03aed0cae3a1054d184c820d9dcd5118630febfc450d4972b4963e56de2b1005ca","addr":"af41527e26ef2ed7e1692f2897fc48bbf792c8e6"},{"mnemonic":"captain disagree filter crane chef cousin one cherry able scout tip magic","master":"bf4a3d4839793f7d502e24a4ef4e99bb39fb2aaebc53149eb004ffaca0256af7","seed":"3fbd2b4e5c614a29cfe82ff906e94be976849cfffc6831d67fc47bf2dea68ca06fea30de70ea546adebad96d3fa106950545350e0925425f22a0ba1a0abfa3d7","priv":"046eff73ff79adecbc208e64dd7bfdca16c4593a1780261377ee48e44ea06d57","pub":"0374f44a020872df00e0101f61fb61e76038f6fa8a7d50a89757db14b2c95b76f1","addr":"130a585f378df286341fa93925eb5d630adda295"},{"mnemonic":"inform measure recipe evoke make recall volcano girl obtain flash soap prison","master":"3bcbc5c191d8f5fd59988894fb749ec333a07e909b3c22108500fe08cf7edb53","seed":"cedd1141a4c9a1e349435e247349994c909811dee5770ba3642768518cdebbe7d7e5ab0776af835bcee0913fa1bb4b72205e9d38b637196a624f031238bd2bf6","priv":"9c070a30d5ad6301d73ece1e6e71790327c6922521f93d6e8b7c69391a12d37c","pub":"036ebf4e4d5349613dd3c7375703a1025896ec4377a9635e9ddea2a2dc1e7bef22","addr":"74a413291b799fc2866fc7c7ed2d2becee9f15be"},{"mnemonic":"carpet poem piece silent boost trim famous coin fish rule leader oil","master":"ab7b210126590431eb1c09ead09bef99b689a429cd86be65681debd5deeb1ef4","seed":"133b317aa1f56e79697425b4c94aa52d5b7a95c3fa5ab6d437bb1b310bae6baafdc91ebd812c76b721fb45835f3ef0f61730320a8ca6e7cc18291b84af5ed68c","priv":"1863a0b1d15847102e3198549a59921488a67002e38af1cce7ab2c0e055eb498","pub":"03dfd8ee8642ccb78642d0e373ce9b15ce9384d12b36086d2c64601ae8d18325d5","addr":"b70aef2f2dd6e42f909a5840a6cc7e08fffff26a"},{"mnemonic":"liar hold orphan include gravity nothing erosion offer average now ability purity","master":"71b19fdcc0d8e082eea3d92a5e6d36512273095251da9177b7cbd0bc2e5843d9","seed":"e58ade95c1063890ab5296e5d8a07e20ac80a159afeb88c74dcc6bfa8fcff6c85a2f19af8404d3e457492c560e4f04becb6446e290ec1a376564be64ce1c7ec4","priv":"2bdde1157be2917e98549af370aedc6a98fc5d6df99db71650ef29407512912f","pub":"020a188651de8022da9d74bd298d324c54c88e35268eca0907a5f6366f9ceb3287","addr":"9c4c3c19a81d424ffd69bd29802ff155f52e219a"},{"mnemonic":"crisp security increase topple put engine wheel apology north tent front minimum","master":"77288b3b65bd31029a3791d357521172af895f1085c1996668a1a689f4473a93","seed":"af74884da27f1ce251a75244ac945052c4df5fbb59e3b12eaea5e28c8fc26b8ec95bdccbdf5481eba4b74680e642e5e7ab2b0f6a4d0eb41db3c08c01162520ca","priv":"4d1df90eb70f94aede9dc63cd951a30730364379bf9a0f339d59d5970095eb65","pub":"023f2f6cf79a65e2d25fbff8c422ff519603c2e400c5d3b6523a6db06b969c071e","addr":"42bc49b12a7eaf46695fb1ed32db0d32e8e661b9"},{"mnemonic":"switch shy kid child occur salt cage local top blade cheese width","master":"5755daab29ff030dc4b255171f77523530a659fdd70bb5fddb69d150d4e7e1f3","seed":"dab58ef3ea14f3041588a5411f22cd426ead10057616df799cf53907536819056a21faced7e56aacd120181734640821c082daa86fa8ea4b39ddc40b5bc02aad","priv":"e5c1ebc0e3428c9ca42dfe809495dcf7ce2abf2b149664031b5f5a9d5d2f8b4c","pub":"03fc64577364f254c6f919e1a9262740987217fa2c66ea490ee6d3dca1787114f5","addr":"1b83078e35972e3ce3b1bb062b3924665a6e5c5d"},{"mnemonic":"rival notable exhaust climb disorder enemy desk owner again twelve mystery devote","master":"5daf52423aaf7b7ac4d8ff4bad65d81f7e3b15021222d3d9ec788a2d35d074aa","seed":"709afe1cde759d12cdf4fc3a68793b35490cf0261397754a62dd5d40fe528424e8deef620f89337dbab01bf57cf241a6664bb3696bd76c886c57a405170a7b74","priv":"b171a7ea63d6e1b8aeffbb63ce5179edc656e17eaf85609ab0d2680e35a3d64b","pub":"02cffc5dff2f9896d995c9f9b6d11c1cab3e0d40a25dfb9da5aa010b703c80be0d","addr":"cc673e6d2578bda7d7054d2d53b841c26e15dec4"},{"mnemonic":"defy prison walk thrive enforce match turtle venture margin quote must cute","master":"9d747975a6889f2bab69fecae39db2a10df1545ae418596d97152de0e7cce077","seed":"183b5f3d963036b0e22eca9717769422bc515977c0a7fab66d716318de12d41a01f5ce101bb47ce44501f0908f8c1255f8c3078fd2c2084aac32624c20647806","priv":"a871082f9cd061e39987c76e516a7086f82eedc06a20081161e13dcada541f61","pub":"02726bfeeefc2d5ef521c3800ebc7700e11aba3cec88f8be5c9cf3275f4ab254ab","addr":"6d793f4478d2e4980a140b724cc8012b44097446"},{"mnemonic":"lyrics goose draw review manage recall snow lucky mirror swear fish rhythm","master":"b69e9a8960d5cf2b8f457e6a037654bcc72ec1d26e4753ad34512a877cc329af","seed":"47054d3ca54f6038ae500dd6a7f8b5fa3265e87b384c16a4e68560f56dc9f7945d599d6a71b2020618c9f7bab46bc6817062751f19b46c2e05eab7831fda1cb8","priv":"5c0efe877506f2f46bf345c71c8dc31239f9e23a543193d5ac894faf0aea9ddb","pub":"022b90c4806ce022e81c706555ba3cf9597861a3d7e28b9aef6bdf36211eba916f","addr":"a3ebb9a579f22150fd9b7cf62a5f52369fce28f1"},{"mnemonic":"coach silk assist potato gesture hire bullet piece document outdoor husband panda","master":"541e3f3e4e4e9803da42f2264efdce5b9338d410b16b0e7b66611e5dec5bf896","seed":"4368a638c45b7ba4d2f1953eac650631f1a1e3c23c72b545dafe466fcda597a0b97dc3302072e50a298989f94ea255290d3963ada9e42e064ae300173531f273","priv":"b9462f51e3c20b3d805b54adc6b27c669ba07d5a5c97edb0a8cc6199d772097f","pub":"02dc7826d790d013e76765b03447d2dc92a945268e42611c51080b7ae207906bcd","addr":"e59101c16f77cdba771eaac3ecf416232f6dd1cd"},{"mnemonic":"wet problem raven barrel explain long call civil pact swear luxury expire","master":"1e2704a2365215a83dda9aefb1093e095c0c06623f060c2741e8bcb8480c4165","seed":"fd81b59cb8a4abf789c2fd55e2d9366051f8f64f54a3e08d117d344b633f2ffd63c1a6bce7a4bcbb01261b6e41f6330ac5d0b151c36649ad59c0cca7e4b3a820","priv":"bf9f0440cd63148ea0771d0f892efd3cc0638330c428a50436fd048aeedd7ee3","pub":"03d807ec07f4f6eb00f9e3ec69dadafb3201cdca3e878367ce4245af65b8e4490a","addr":"e43aabb2d20275ff60d591dae8d83b938a0138c7"},{"mnemonic":"unique mobile gospel cost genius symbol online rack round canyon front again","master":"ff441298736365bf07856cae35a9dfc2612a9d015592d5326980225c4d4e4e21","seed":"e05899b5a5a94c860cca584b6065284e961625486b1ce1c80340721fe4f89fac7afb7b665464de68b5c5813e48896210a90d44eaf013ec4fa90ace43e3153d3e","priv":"45513cc23e8ad7f7b5932988637cd6aa85f19a481cdd20c220f0407afc69c688","pub":"036080589a5268143509bba4c4f26ae8a3ad7b12ef7295c9ef416cff53b66b39a7","addr":"68456ee838f224959e5c29649f41eed02b56c3a3"},{"mnemonic":"street bleak prison artefact pupil armed blouse pipe eye brother man aim","master":"6e0891146585834da8d83d0e221c88d53770f3c56f68429565d011ac697238aa","seed":"8af79a74ad501d308be613981a1a25342791288f14f05b7cf3b81131ba2146ea63e01ccfd150c4d2bfc42d64adc899158383d82f3bed0eb772851fdab4f901c7","priv":"86c09e2544c86b883e8de233ee297fa704c39bba463e5a8742c4fefc9ebc109c","pub":"03d8cd38cd2311a0360c84cecc58787fa3916c6c2adb5b2baf12a880549a572f7a","addr":"68c1770edaf76cabcf93c6d94f4510162fd36924"},{"mnemonic":"love wear kidney math magnet share mango also dial fabric near destroy","master":"e500e6d3a103eb11414e5ebc9e27eb96456c48e9567155c6250aeb83920df860","seed":"704e740c6f437a9e8b7e8d7e2321ce81d9132c9a6df7a45fdda99cc66a09c9d73350305aceabc0fcbb589bf44911917be71e9f399c401f86246d0aebd4b467f3","priv":"07c906988f937dc841918a7c3092f5df0cc0a6ce4487631774cf3f703e9c2713","pub":"02d131982bdf285fe3a37370ae0175438094cfe3d6fda273bf24320008fbdeb5cd","addr":"df31d832d2d23502cd0198c5947e8297e6f73eff"},{"mnemonic":"nominee connect useless dutch double vehicle rocket exist mango floor educate absurd","master":"0a66acfa6ac891a588255bef6fb1a845f2756ff0a7dee8d2ff33a19a7b22f18f","seed":"4c4e362fbf0dee5928b21652552815edf27a4ba5a11a09dfd83f3b53a44cdcb6acff4c39b16d2cb9ea3250af3743baddbf6ce90ce1e492fc6bb53f79d646a4ea","priv":"e81668360f562929af7e40c5970bc685ef5aaa7d390c1bbe005b028460c79ff9","pub":"020a16c5a1098493bf1f7242de71bed03779c4eab8f35a1c6859035111514284d7","addr":"c8a841f39aced64bbdebf2f8f834ee02ca33a8a1"},{"mnemonic":"sweet leopard loyal problem pupil perfect power flock thumb wage person secret","master":"6fb555e482a1987c2c0f129ffc040fab9c4eeaa3c23a3370db7b4a5ebfd2cdd1","seed":"b20837f8580aebb15a7a4b035639bc04e27bf33e1f600069ba1378a5dfdeff3e95545e6828f339dfc30eaa449c78b046c21fd99b24d819c735e050f6992f898e","priv":"9d06cb0fa2cd01675e038897a14e6b7719ae84ca6002ed6620a557877ec373ee","pub":"03f49f50e673851d74da1fe24aaaeb75c2cedd25116c003fb4a810025192c3186c","addr":"7f61e30a20df85042cfcda5163867bea46b98702"},{"mnemonic":"slender tilt tell faint dumb seminar cycle tongue bundle case swamp author","master":"444b57e7f846dadf73a0bf77fe918e8716454416501c84a48bd78dacfa87b885","seed":"4345b114d1f3a78c5582ec5469430a8cde3a1a866e64b3c3606b84f62ff48bbff48826cee928374a01aac080b79269f89751a11aa086fc1fcfe74cf05674ee04","priv":"7c6d51ee5199457807c66f22e8d9b7a703a4e61a84cc791efc3cdf5f7038d28a","pub":"028b09c16923224208b6ea2ed777a2e4aa2bca5674eb8f0021e9bfc4e9d3fa0a69","addr":"2486b9fb36e8849e09b147749e445fb515591197"},{"mnemonic":"alone oak satoshi diary artefact virus muffin quarter identify car whisper topic","master":"b4c37472c7fec6dc3f3452d4aaa7c306cb65ff940052b0aed224c12104296648","seed":"4dca6ca310d5028c4cff946edda516d55c7de81309109e6e3586927a8fc2c4095215ce471774df2795f04fa01cc2cc528c44a5968320ede4016d68c24e4bbacd","priv":"fde405fb9a8f0e98feed3f4e996b3fb90193800c571a89a2c681c0fb4917afc0","pub":"034bbb553a8525daf361bf0c831c756a56ec476c0c9a52b0c74dd9eef35177a776","addr":"c890e1e83daa169e0295ff2844edc5ca2a7ff346"},{"mnemonic":"noodle hour inquiry know sort review oxygen observe exotic script mimic march","master":"3be52af1a8430ba7c4610dd4bb1ad67d978d40ff7530d712cb5728bc961edd3c","seed":"e803e685c85a1a0a4a382d1358f5fecdb8821564545d8573f3708a01f0f0bc1da54544ca2338cb988e7d6239d18c32bedd38e1cb9bdf1bbb6dc8cbb323055510","priv":"defabd99910867339a4af3a425caaffad76ccd47a43b05a13ad86f3d23887b03","pub":"02609b9ff36c966dff6399576fec7efa83cf0fdb66bade72334ce2ba69161768b7","addr":"abef04d453ccc6d443cd60d6f964d008eb5f08e4"},{"mnemonic":"crumble loan economy dragon vague library slush ticket flip mixed accuse switch","master":"f085484747a4bf869f38da6e6f56b9ed2be60b137536a2333f2c6818d76fcc68","seed":"b0ed9b4d75a17a53b33a73223fb158d79999548d13919599ae7eb71cfe2fcfc06cedc8f94cdcdfb05ea043069c426d2b78e2f67260644109c42a6d9b3f7d5134","priv":"a64c537c561fc49e504e870eb3608e69afdb2cee4c6f177c63fd1ce170a67192","pub":"034f7f99f2699604d3f9869dacf1e6ddb387bce4e0d13fce3f4aa85713c7976048","addr":"4b51a7f925c0e1b428b1ec75dafcb0e4d9852620"},{"mnemonic":"rifle swing confirm response name void scan shoulder lake oxygen uncle south","master":"3560f172b5c2ad665da648cf0809604522eeff5fbb2b1e0ec50e7197bf711dac","seed":"85386f49048f371171ac3ed2bb4f358b7e22ae406a7f2c9b3f494f2f7eade96f2b6f96fe48bff1754894b8b2586013393f0b9f0365c6996cd251e668ee90071b","priv":"c79860b8ae43fa4dfc570b2d20549b457ebc6e18d38865ec9cb1ba571409bf12","pub":"0253d92439ae131722981eb16924b26fe01421e4222152cfd0505744278f963dec","addr":"ace153f8d13e8cee51a2c08fba9f445f50e818c2"},{"mnemonic":"air floor random smile mechanic exile run auction avoid truck expect old","master":"a7cf0d4043dccdf5cdc835419f5bf2665c8c10e7affeaa2d8cb42e3787bcec00","seed":"e4d315f6daa11eeaea17d513f8d6df6ff2dc13dbd2e09158af03f847ee6cdcac2d6b88906ae62e84355d9a0c0956ed465b3f8081837d45eb01cf785223404306","priv":"5f1f737625360db311accae8b8ceca9d4f2aecf15d6e4b91db4c407bf75345bd","pub":"02f467c86cba2d8d6fa258d16e9b4543006b81c61bd357a2b1d79b9010fa30437a","addr":"458f265c275940d726dd9714413a56efb7f8c4e9"},{"mnemonic":"assist right street define hurry section tide museum faculty glance power aunt","master":"49eeea0b9687360576a3f93cb31eaf0edd3521d2cfcfaa37434d6d51a2f3b5f6","seed":"9371c5276808cbae376bf529372c88e6c5c6178a9b469ef25a7558ad68fd6200a8fcfb2c117b7d99e9c7db907bdb8c69632e7ec058f2b8a4ea16518fed9dab82","priv":"936dff8ec25f22522bec8ddf52535a4320327697a581e9304e62240e5d2f4922","pub":"029c518dc7e8261f2a64104ac846ca90439959f4467e69dddc7c902dfd41fc2177","addr":"5a6600220c96af511e6c89dd9c8c80f1a1b0a893"},{"mnemonic":"glare earth tuition dish elevator mom remind arctic enlist excuse vacuum little","master":"a251df0c9b6925fa78489dc803a34839d90aa10dd35216360fef92173e0bea80","seed":"4a543a76deb55a8df2a58d0fdca3ef32e3f3ca74be97789cf004d1b69608763f8d311c6cccfa76bb6c7b04ff8d7ce20ee064d78ce4e2c05d894053e8a5309349","priv":"0aba88dc12cda2d2f267dbd19ebf0eb390483c7384895b6b7669ba821b73953e","pub":"033ca852e0b43e2ed4c7258c43bcc5be47e621bbe6e0bd570176940aa9b371adce","addr":"983a92fccb0350a8371cb5d5effae7125615316b"},{"mnemonic":"tornado group bring crack need pigeon scene quarter affair purse three mule","master":"b4d54df22150e28595aa5e1f6717ec764ffd8d2cc6338e264dbbb46e9155dbc3","seed":"85c281d21f25c14304aeb5402e717b52bcc0e5dbeaf2d155e11913717c545baf79d4d965670d7645bf093ff79f4793d136d794616905c2e24a8c72ba1af44ba8","priv":"c45a9afa0dcbfabbec916a9fba6bbd9cabc1a65b4ae3358e29943dee9d19ef9f","pub":"0272882ee11e688d04b89252ca1000456fa743b5931ae03e1d29934f79980baa41","addr":"860b69d255bf12d5f725e286203f91bdbdd29bfc"},{"mnemonic":"toddler bamboo tornado season total battle urban mule oval steel field case","master":"af9ea8f11f6fa83dbbd4ef32dedeb88070b3fa9fd98d27e1d9b43e66da7d3df7","seed":"4b95b55884e008f340660a6c9ed4f2b23f45a5e45535fb263e880ad8842e845a62e66720b75d94fad7f47fb494bd32ee70b7a339de5b07bb13c7f0533e8cec57","priv":"643eb65f5c87407a18be41f6c660d4d1ae610c9305833c570d785006b92ae354","pub":"03d1c423839d02f40abf0632a36f9739c6ba59622ea56e1085d2ed54504762b43b","addr":"05625426a47e8c11f27fc55a53121bf748c2d05b"},{"mnemonic":"meat endorse bike truth avoid measure injury polar rely water rocket zero","master":"23b56abfa50026840bf19105ea9a02569d1881e2cc447a582b08a6bf6304a33b","seed":"d8de461e4f04d4657de6b5adf8730bdbb85fd175326671886017c09d8081ddb7dac0b8262fb01f2dde477b3e2bd97653a700d373fa29ec7db2161dcbe418627d","priv":"f409c92079cbcbd9f96b2bf0d84f86d495bd8e6bb4859fff2d62c29558a551c1","pub":"0247908ec215a561a41e2da6ce05e0ad08158bffbef9fdf7bae729592e4d17b45f","addr":"e4cb61da62a6176483f967aad232c0fe89a9f16b"},{"mnemonic":"few transfer upon helmet property draw strategy talent awful goose index lesson","master":"c0e538e1e0b819660c63ff668869a81595107458fdad44459f6ec22b251d46e0","seed":"fad56235bc5f3a7dfa666c85e5782871e7c202bc4363da62fe3771d71b36a9a1502d550d668db69264daedefd7375862b891d4193cf958b6d8af9b39a9fb0e3f","priv":"51c8264448b81467c2c86c003765322f7c763e0854903230a4ff3557fb7afc31","pub":"03bd00d092d311add8fbf191abccf181bb5fbf83e26d6e29fb6f4d70055ad5e7fd","addr":"270429d79b582d835fff0b15b0eb21ba1c98b2fb"},{"mnemonic":"can warm add shell obscure ability mushroom discover destroy useless split blush","master":"611e2b107ee76d6f7b415776c7b0c6f03859366c342a56618850c6e3cdcf46c5","seed":"c9f4b2663f8abc8c8872842c41fe06b5911b412fdaa875ba59366d7a18734aa795092d220793867ed43afd1d79882ffefde417ca68c9ed61a9f52437d7e45a53","priv":"af975acc3008d742a37bd6917f4a5c6e9a5e0fcacdf1e74ec489e675905dd9c5","pub":"021152804b2ac5099446aa5e8cf1fff850cab08e225922e3865ae5b280a230ddf0","addr":"d4baf915a1108fabeaee47ba0b03cb241a12e1bb"},{"mnemonic":"critic length shine mimic gorilla rebuild bike security price differ spice average","master":"418d3fa386032d0a22a3b4553ec662d52ca416af47d0963e288a1bd08ad50d20","seed":"c44a2f7e56ffc9850454a03c40be79555c340b8bb2a7559a664a8e295fb34fe1a38074101b431038c207baa219181046805a67977022d61bff2270c1e27b80b9","priv":"117d57d4f3dd6db8a718e025f4fe5009949139f2a41aebd682ab49f96ed152dc","pub":"034af1a0205014cf22dcf328aa9308e255355dfff65a7185aeb180061aeece5084","addr":"f7af8cdd0592983c065c322efc64bf7c25769e2a"},{"mnemonic":"vast resist ticket hedgehog around fatigue rocket rack carry run protect icon","master":"c434c6e478fbf7edaf97e2c90c38369de3033a98696b1ffc793aa349849c629a","seed":"720f1afc198446db8a107105c7398d3bba7675fe0d01de12f933e2eef7d12effea0e9d93099e0256b9e494607bf45d855fefd68543d9beb4b92f3d7779a8616e","priv":"497b2409c651a41ed36e58e977611292bd665e273847d4d413291c386d0d65c4","pub":"03ba0869f55efde74895a6905dd149bfe140fb2ee4e3eb19c959195d93adaed2f7","addr":"2242ceef764c76680a768594f804e218154ae3e0"},{"mnemonic":"neither bunker use enrich liquid borrow time feed mixed clock submit scorpion","master":"a9c4646a10078a9ca6b218b7da25745a76cd7dd9e38d803d8e840863c9b97449","seed":"22cc85d4e408d0a751b854f16e00fd16b018fc26f95aa7d82323084ebd7d7bf3fc2370c1a5e38f88584e8a17977f17987d75e447f704603c2d71b3ccf806afd0","priv":"9801ad0243910e04b7322f493540801628da575ab5eb18a5e0b20b0ffa498e5f","pub":"02c3f726202db7040a250647799f5791d4013b38da6053e44f502d0c8a064124f7","addr":"fb0ef77563764b393003c137da2dd1ee21d92904"},{"mnemonic":"letter violin disagree arch crumble amount car inherit wasp vintage disease orchard","master":"a24fad07da3e4a04fecb2674abf8b4260ae5dd71f003622bbc4a00292dec3cf2","seed":"890b94a33cb176c697b9ca49281c053f88a8e8bb6f52af5f0fab57ce621145ea59624fd9f17bc4d7ff820bd2998cd1d4a2dcf8f89738c150aabe7af5f87a6b1a","priv":"499b6d6e741483ddccb35f917752e51970c5999900b48e18b2d1edb85927b7e6","pub":"03354167051ad5a01e056f7bb655de9af430fb0b3756e1cbbe6dd0cca65d43ff18","addr":"efbe8995bfb51a94b21826bb93937616c5807d94"},{"mnemonic":"elephant shoe quality dutch pepper math between lemon wood below strong grace","master":"7890fde1f36829461985465e7a7ba26ef80bc9908e5cd849517a999f04b02ef9","seed":"077fbcc3c57bca394c393e9852c3b837ab555cfcc5dd0097c058136bf088fea569d18fe0d447a8bbe53b5f22961de7c5cd0000274930db60ef18f049aaba4741","priv":"0af39cbaff322b7b7298b2605fc762bcfa69ff84a50dbb121502ed1e8db963ca","pub":"0221dd6d3d3c597b982093f5ddc4b8403b3d16d0e084aef37db3526f050c9b66d7","addr":"81ee7b181a5d1902b6aaf42ad0225edfbf669498"},{"mnemonic":"powder marine skate good skull correct catalog parade car length fold clown","master":"dca44cfd6a67d213ff365e5dd6bfab6fe63ffbc999c9d38e48b9c8d32d32f914","seed":"91dda0ed96be1b82432b76bb7dac1e80ed0a1c5413096d4a22437081834cc29f6355dc3e79d7ee00cb6bbe50a83fdd3b652259937beccdf11b844ff023269e76","priv":"25ef3009323160687cc6651338320311894b8260596834e6cd05c1b921c7254d","pub":"024b805e8c768c8914ad8c55d8e1898490b9c71fa68ef43d07f3db496f03db11e7","addr":"57c28bc9cb2f4fea177c34e581c95832256090eb"},{"mnemonic":"client wagon legal favorite donor tag describe object camp network tornado immense","master":"4b916d7a10502f4e2ecf295d826a3248fe9bc45a13f1332a46586833b2f1dc05","seed":"e2726352ef940a7cfccbe95172c1fb07c8c25ddfd7ebf5ed532f27abfd33e81041e816e34aff02530525596654111ab3186fd71bf65dd3dddcbc6efa7944c347","priv":"131de6e55bf3b614153557b35c839f0c869cb10d62b8c34c15fa2cf7c32bf97e","pub":"026a3afcb9ce79972ef910d6272613580b199f90a00035ecca637b09397f0624bc","addr":"b2ac8314ecf16da855c5d7b9ae3aa12854ae4a05"},{"mnemonic":"someone tip green vague sudden element beach people route lawn vehicle female","master":"2f7b9ecb854a851e308e944e6a8b39811a286e718b4ebb9a36e8c8570cfa7890","seed":"7653cad23c600649423fd68b0c7d002feb0327551521059362b3914a63f6ca6adcb1409f7f7f1b01f5c489237b25d0dd9b0aa121a60b1af33cccf739d05e32b8","priv":"4b3d50735f027be5ce5a85a739227b4e86590765e34b3608338497fe318cdfc8","pub":"03b47e6036447632c8ee3d2d1e3b177b51ea73bddd30893818c81059cfd3ec6c5e","addr":"10d976ebd58061a7c6ebe2ccbfc85adc617db2ee"},{"mnemonic":"version borrow decade family away zebra one course paper promote man gravity","master":"ca2995d4590ccdfa716b0f27a3e5e93d084df7039116b06ce5b4c5f2bdb18ef1","seed":"97a3f0fd0c7150526375d5cd1ea192dc0f04ed096e5c4895e0a15a6d491b206b59d52800c2c31ac6b512664788ac79663135f450b5198f358dcfdf1e9cc26e12","priv":"cbf04fb7c5c97ab9980cf82625a612919a85e72c0524cd49c0a237c25940b563","pub":"031f04b34f157a07b6bf50fd54ff972b8441a72d6a5d4fe1e54a1867d07fb61cac","addr":"57488105d27e808a39fdd571c895dd06264d3357"},{"mnemonic":"truck zebra tobacco hair monkey pool label produce leader hope misery cost","master":"b42e61efff413779403a9d5ddfad5230412788de3c0c7da4b020c73a72a77569","seed":"1b9c99349d6388e5f7dcbb8d5b87951a614ae7f803b69b30783035ed016cbcab3c42714246d05039bc6121dba51fbb722c13d2f6ca0cda79a0d816bf7e568cb0","priv":"52dad4ba927ba056a1f0a07515f044c3c9dc712c2019879029ee0b37c7f51b64","pub":"020e6af559d2e1115d8ab76e908e3ae778451dfca6250b996c42d4f3044f0f1a27","addr":"1a3e87568d2f20d4480c153cdd82af21382fdf9b"},{"mnemonic":"dizzy capable mutual cage uncover frozen exhibit awake teach grocery juice reveal","master":"54d15b84b003dd74581cc49909d3bd7ad07e00e745f4113aba6facfdb305aa2e","seed":"c4ae35b24c55af14bf590df97843ce1c9bbb324b845f9d2a08f0ead0d0292f6092e261711aae504feeae862bedd7558a092271455d89a5d1629be8ca43710e84","priv":"d5d476790ed6e46ce12e1573a9fedddada0413d5750d1d18e408c125e43c7923","pub":"02f3b58f6cf3533f3731e5ccc6cf094815d52467e39151d517b9f6a425f8743601","addr":"249ffe5709370cbe54520c162a4a7c8db2b28bba"},{"mnemonic":"menu damage flee oven blame vanish olympic scale pretty valid toy write","master":"91c79127f19318ce4594f4f1045f0f2efc8ecb6a3ee9177ea2cbfcc890a781b8","seed":"fc4b72ba3587fc4b35637186959e3f02460262bbb330c3b18e561faf4cb2ea29ae9f92f011d9d78231746dfae33f57d75ed85f96680a6a3f309a3f81cf59831a","priv":"cc7b3e962031f93079b4d6a9152a85bf927ddd2fdb9f84465220e2cc3ccf9ab7","pub":"03eb09eb7f21c9e411e3660fb49907bc9a23e04bbe75151ec732e066e4e0487118","addr":"20bbafa15fe38bfda08c18ed7a65c52daad01614"},{"mnemonic":"remember hamster power document detail pave inspire tongue rookie monkey board tourist","master":"dd1970c96e30be347b4ec8fe789b4cfc29ee073162d4a2e5dbe5c78c80944af2","seed":"561682af8f69fc045f09d43db4f71a3c7706615ac142078d6aaea287bff00b0bc3213537dd50b783d7f5293b4c2d2a1f6f9bfcd5fdf17f19cb10ecc05f854b1e","priv":"79c341d4178a7a8e1fd364d8a847d97b06ee94d9906a269499fafa63730d04bf","pub":"020540cda9e4957f9480aaedcb38379f2ba60648ae487b741c629a45a5b34870a3","addr":"cef7f07d4ae1da5fe3cdbb37d95bed5bbe53e838"},{"mnemonic":"endorse rescue traffic vapor chef movie symbol scene slide eagle youth tide","master":"8e54dbce9b2fba91209dcbbf6bd272d524762ba3ef2ed05297b01f440e6ed597","seed":"2a0ff0a70d82f948b866090a4e77ddc360a2f52b6abded17f13dd66e79e845bccd2c55ada4d4ed3dfb33d5d10700628bee551ea775c7f3342f6d7a0c3005194f","priv":"c58ed547be839e99eefae49479b3b6345fd7c6ddf390104a544b79f5f677016c","pub":"02d795bd4c26b14dd2aa3c04633f5e0ef787533b3ada72e7c83bffdfd4cbdbbc5e","addr":"ee25d8e4187f6a6214662cc4872b7f7cf7204c45"},{"mnemonic":"humble glove resemble slide rib focus naive false snow north strong attitude","master":"e8b826c5d90453d1af3082a0d5f6a625207bef96bf7e168ddc4091d7f865d51e","seed":"b9bc139c6e97339489cab328b3a362546cc19d0cc060e5c5b969206024aff86f1579d230b4b8b3983b33cba32a58d6dbab5f078704f0efc65d6476062c1d41bf","priv":"4085b496b9a18f4ee5a1d79974be1b1729f51d3c63ce347420d08833d2c793a2","pub":"0251ff80d2e90a37efec614d9fe65b6192179941b772a9468440a2380845996846","addr":"4fc115087277fd7dfcea23e089f5a3a6d7e3bcbd"},{"mnemonic":"fiscal truly seat deal crash train labor trigger kangaroo angry today minimum","master":"1770627ca13a66d0fcfdb474a3eef708abbf9d23d211970395308dd6758bf8e7","seed":"a19680de56046e31637ce714778881f1ec6bc08abe9357804062cb881838c2f8387b52f714377b89b6faa07c4e5b6294324081b7dc521190cd43f75f91029c22","priv":"131dc8ce3551842aebd863eb61e07e6d2de40d548dcd28ab0ed6380e469b5d92","pub":"039ac0eeaf7600231c75fc72dac0b2f58418e1f187aefb3491934120b4fc779d18","addr":"fce14c8cded6d2711301a780a58297c68761dd52"},{"mnemonic":"good dust code sell element tilt host valley climb genre asthma bench","master":"106ae0e9582e9db67ff88c1098d3ef651efeef30d44ff60de30bc0c447217ff6","seed":"1b307d8ffce13f7944bfeee6d6b97de257cd31608ef9059bcbe2cef8bdfded91722fcbf325788d48a5072b9f915670d345211006102e5535f7e2a1dd86bfdfd2","priv":"a78bb63f0cf56b81e228b801cfab1706afb073bc2deb8ce1c8c56f2ab564f1a7","pub":"03fb2144ca5e9dc753c2aa46f94806b35f201d942286571a44bbbb879d2e9e3adf","addr":"5d68a2c8fd5486ba93dc18cfb6a04698250a424e"},{"mnemonic":"buzz prevent cover list flock meat that slab crumble melt prison treat","master":"d620abf2e72b47f061594137194e41c33bd6789799d67b712179c5c9e0dccf4f","seed":"331fe2ce10eb19e2ea13c0ff7abac9b49d43de8d937963e8498da172a46e0c4dcf3e9d276d1e4c7dff5926609936f253e59c814bd4c061429cf1408c45d6e5a4","priv":"8e3b30ec2427f34c463f83a500842d4fb73575e261022720276b3fdeeb20f075","pub":"039ed714c28facded3af8fbd8497b17818cee93d26732aa7258ea61c6f8cf542d6","addr":"74b44edf7f993c72dfa53fbcbcc836c99578769f"},{"mnemonic":"domain tone insane visa much reason tip truck travel head finish grow","master":"3b00a9417e07cbca1d0b80b108cce99089c726e49c267b2e5a2a1d3965c7c99d","seed":"3e2c842cb5d267a2ca3fda4c20d674d048873ca2cfe89e02558a0b585475796979e4bef6e835b17593c53a75f5a4b37dacad0977a6b6fd6589d26502db47a048","priv":"cba9d951fdead64920a36afac46d82241c6084b46681902ad37eed1928135db3","pub":"0321db6f62dd27416d94cc22ebd3abe7ccb66d5e5f57641f79de3d9a1c49f8d0e7","addr":"17d65bc69345ab94e3817738981ea5f9289b81a8"},{"mnemonic":"bone earth country lemon great ridge glue neutral vibrant age doctor income","master":"ddaa76dc4405bdd779045a0b113133f51af43c14ac12281260ea2281a21d4704","seed":"c7edb1f4572aaf510b4b79f18cb68a7464d20babe170b3bcebfa7902f2df2a47d404baf1489922bbe2edb46a2a8ab798a99cb5dfc162b315e4e0a83ddcc5614f","priv":"cae3b56916c64b7303c038294cb1a9c15719e3cb8ac0cb2476e5688b6bbdbf50","pub":"03c9565910b4120ab6a62c275ca0127b717116e773f57eb93d1852ba3d0f2b431c","addr":"81b61de28566c226e0153b1e3afd53697c6591e4"},{"mnemonic":"rotate agree figure style cereal best corn box corn actress toy deposit","master":"ddb3592dc43e595f968e906c72be97c03beb78325f00969311f167e7748bfaec","seed":"cebd7cfb74b2ac03a29e6f4d3dba84d6b47730b478d0ec92f90c9a0ca575d17c581e1f3959b4e0ef5d5f51d43a0fa186ea54420cccc8c2fec8a25f36af549e6f","priv":"b3a7e3147640f66d7be8028a23dceeade18f23bead07774fa5d176014627dbec","pub":"020e2c9e9484acdf5f8a574e9fe912cbf6bf9198579107a48b976da5e4dca2ca0f","addr":"eba352793c5a7ed663a5eb33ef9c44ceb0388677"},{"mnemonic":"kit age click judge decade enable trash noble first grit crop decline","master":"bb39f1d6570a42b31a6b1093d6c1d3d469df3d565ceb2064863e50c540cfd986","seed":"9c8471f0ada1f4e4c4b863811b36036e72818432b8e441ef8234ea29446d2978195da3d63aea71aa5d1a7c4e71e131a90e2db598bc4ca2bad1dfccebeacf963e","priv":"83a532c37858e36cbbb325481e7be10beb2166ddb16b7ea19328e8dd712ac178","pub":"0215f7cac31b44b05f1fac2742ed8a0d6353fbecd06a3abe7946e2dad1feb089c2","addr":"a10254f23fb959df76231ea3061cdde854aee99c"},{"mnemonic":"jeans broom faith border sign decline choose black depend camp nest song","master":"01dc6326bc635da075e100217be8553c30be5c3ee66bd4cb8dc0768777b5826e","seed":"5e7d44489c45338978dcb69035addb83625389d15a5a2284ac888682e7499e8b07aca6ccba965201512ecf7da5a5ef6e22d561583e15f4507eb79ca60e525da4","priv":"07e07f2a2d9eaae6ec9ea7f676124dd14e2f29e43095cc8574b67fe5a8de1fc1","pub":"0295a431168b265c62a8885186b7719298c5791a0d73cb5b6e55cdd7200b5dda38","addr":"9328f2fcffe4db6cc6c8c2a5b0e7f78cac1854d5"},{"mnemonic":"narrow federal feature ignore damp sun brave cram blood crash glory cargo","master":"7e5ad0d0325b2bfc0ac8a2d32b13d758b308fad36c5aa4c497ee3fad4c999fa0","seed":"e680df5400ad6c1f8b097a39a4ce9d9c3c48ea4c21b71795fa499ed641137b50b58f78603bcb2bddae78ff5f96079d48fadd175050ff95784092bc93557d0c13","priv":"eb443a6e96330c1d3c2213e9e345b4cd0e4b2562d6bf13bdf9366f0974d0a98a","pub":"02843de6f3e02767908c2692c091df22867fa783f858a39aa7f6dc786ad5b5d2d0","addr":"5a53f850027b3f303ade321198c74d108e24f699"},{"mnemonic":"fringe fault blind lock wreck one kite ozone system come spring amazing","master":"dc2916fd303a02d0d7ce5d5e0ca55b8c504063c3b54d006f0926a89c52e413c9","seed":"ce52cb29528f78b85c003f5bee65b2d3145ba93963fc4ebc023183618cede1c0add4fbeda85df76e8887004fa526769752808977726bfcc838fe9fcbf4019df0","priv":"5b6302f3548c8a8ca594bf67bbfd44ca98ca84b2df134b0d1edf4b28ccac4340","pub":"03846f7ead64dacb85b25d5279681074dfb9a8c363fc48acc6565c6e142380ae3b","addr":"b32324b0f48ace5119e6d6616b9e613438d92184"},{"mnemonic":"rapid donkey deliver soccer between antique pipe youth science angle erupt leave","master":"3ba5a3b9f7badb433f4235e89359801dbc87b6948e74a61e8555b11dd2f6b491","seed":"eae34a8427228c93f754a3a5ead6241684af42b34047f98b12cb7339f3b7390ca9ebd4373a89ef512e75126de78cb72501d2deb575d356d6ba9d64a8d50951a7","priv":"61a6843aba8ade001ff479a2b768008ff5ef996a5a8576956328815755008c06","pub":"020bb75350f98f845d5ae99ad8720b025d7176c00b6a92a9ea7ac14818a7ae6a73","addr":"2cfb35c09a2a5a458519e036d21555571b88fde1"},{"mnemonic":"juice riot brand example type sign crucial warm bread describe rain slab","master":"9de3651516a0c991dac2dcfa0f95265a6100b6ca605a0d577bc9221151306b18","seed":"5ad029a5964c27c295502b40fba611bafb9b9e626cc8f8df5a98394060d16e53ce41ea46421a615c5a3b5b61c20138466dad1a0b9541d57e8ccf7813ef6d9327","priv":"a54d64cedd5e3b3cfddb182a513a13bfa1cd64627db1fcf5c91f398330010741","pub":"03840dfc1f9d210a632dd38f45fec096c9dad11de2a8523adcc79f4f520faab8a4","addr":"1151a84a341b5b24b687abd2083e7fd150ae937c"},{"mnemonic":"air ill huge miss empty force indoor inside young ball wear blind","master":"76dd3f042a76e88b7d63422086fe0b5242a80775c92ba4dc31b31333c6cf367a","seed":"0df5fefa4beba8bcbdc1e6d4b906c91ca66c14261b543280b31be5e1a37b7a91baf9f34e17143a3e3451d3da18534996a4edcfadeec0971b5b7db225d6056fc5","priv":"90ad41d7cdd253fb10da90c1eb6f9c75120553db484c6e1e2d61aa4ca679d5a3","pub":"0229419c442507c123f161277de5a9beb43fd91556f6cbbf194e26bcf4bcbbd4a3","addr":"68ca6d2e8330de386a3dff8acc4f9be6aed6facd"},{"mnemonic":"electric grape tomato average idea shrug slim certain caught know rather poem","master":"4770c9846aaef6f78e326f3aa72fe236564251b0187e3d8cf2dc95187fe348ce","seed":"d054638cfeac9ab3a2150a49d6854c9fad983e7fc91ccba17d6bc210c976b20336c33fb5f8eaa6e54bd6480487491a1f8150d074b29ece6164c2c99c5427d7c1","priv":"0bbedbc6807a1c2b81f7c1f8b9a8380e27d19a0905eb505630156639d0ea4097","pub":"02be715af6a8583fcbc51f4cfed7e78d93313d7fdd047b198abcdb6d0d2271bca8","addr":"0535e0d51a9f99ed22fbb713b2812e4f2fbc680f"},{"mnemonic":"boat tourist proof point giant horse error trash abandon transfer poet legal","master":"5c366956c526671c4e6f9011872b24d76adcd95de54187d81e3c7c2edc749023","seed":"7455f7f31ee2c7729f7a05b4223bb2b335a0ba5b8ca1ee3f632e04e752294a1f0081e94cbb6763391132562a8f8323b0b05cf00961a2d9a4993ef5ff69d52e2d","priv":"ea1f442448650bf1445c5aa13107210280293e9cbe1b1e432327339db7b68624","pub":"03a80a35d7d599be28524a427dc9b3fb593bd12c7cbef3982bc67523ae6c202455","addr":"c12318aa7559ef40d3b56856a2cfcf89d5f5def8"},{"mnemonic":"number oval section onion aspect surprise romance paddle oval reveal business pudding","master":"2b2fb49728bef8d8301af63af35716b2375071a75b1e2e8d4162afe068e6a7b4","seed":"384e57c3ddb0691d55be1d667dac88873719ba4260fb3d26c263d75d8f5cd12b444255daba423821916bd188df5007ad31c6388b0730de258f543c23fcf74923","priv":"26c77883d1bd7a257d55ff87b562a41408544fb727dd98a7aac093b4a70f75a2","pub":"020ee3bed4cfcfcd28ff8d41c96a1b7851ea3ec4f81fee00ef8ed05def21d37e51","addr":"e8447d8d97950c9a15d3d181a3cb00b0541941b4"},{"mnemonic":"shell lunar fragile unveil dinosaur napkin mountain fresh annual jealous check jump","master":"0bc353301fc1edfb08d3ac53efcfcd96699ffae3174bdc83876df3f9a5fb1a90","seed":"4c8a46510fff2ac0d666176cf77fdde3f2dcfee550260e43bef7f9e6127ad807ed335fccbeb49426aefa8c0f1268e5f602124c2487653160f575cad5ad68a571","priv":"2e783a6c7e1e74645f99752d342aa3b6de689af33c5a80e3abf28f7e1ac0c6e4","pub":"03fead7454b48e2bb68c8fbeb1c807dd4a7d05c6c4c9153d4c516b05967ec56853","addr":"0ff9f27bd866673fb10bf741a221cc8cb4a4f95c"},{"mnemonic":"sniff rule decorate expand siege boat people choose resource topple produce coconut","master":"03c9712b2dc0ed358c17478acf1b3b9c8ea9106c01f0e52056856ed212d4b9d2","seed":"a689100267375fcea1ea18ca798c803fbb6e4b9d82f9f4fc96b3a0873f41b7553589c605b021b4dd4a2db9d3dc5b239053ea5a48ed227fd6db264299fc8d0e96","priv":"8eb04249c00506425b0e414b131ee80dbd8db4f5a873be04a0b1d293203544dc","pub":"031e448ffa6e72016fbcdaa4c2790c8e57145ff051de1d99b69cac4df1f8ccfd0e","addr":"edff4f402b7525e5707a9ebb5b13b2bd03d12ee8"},{"mnemonic":"crumble coach clock opinion net churn cinnamon seminar slot upgrade always nose","master":"8af370254a2887d6d8d00364fc824b6565ef750d3b19fca98078281b040f9244","seed":"1c6241635fcbabb70bdd30d827f602169ddd82e36333aa50a7f7f2de4bbc9a581d6f7718cc94c0d63779f38363a8c45042b76b89610f9b3c2e785de234ba5818","priv":"23dc380f4557ecb1cb779d128309012c409c544c906865b06244e49be877db3d","pub":"03261b2261da80af3a33ca8252aeb21edc608b337761a6aa8160721dc202e65b29","addr":"fe0cb66348437ea5dbf8ca79de9db63f0ff51528"},{"mnemonic":"mind fat sort buddy gap glimpse hunt ready library invite mammal repair","master":"01979edaa3aacf38e619e05cd78ac50eb2729d6ca2d8ca5b476677d30a4414f1","seed":"7fe831aaaacfd5895fd3746b45c0cff02d52923fc3ef55842fdabd02de07bb6bbd07dab7f1db1318f97fdb6141e5ab0142d7d06ae92c020d2be760e08f99661c","priv":"10d3729902b4a8c26b88c84ddfd6201048250294f18a2ff0ab4248a5b4085992","pub":"026cc54074748e623153f3bd4b735d0c7df21cd21fc59cac3ba43292cf0ec3230e","addr":"0b7932471403f4769cfaafe834488587349525e0"},{"mnemonic":"area switch resource vibrant prepare write genius danger extra alcohol section company","master":"dc841ed2cf4ceadffcc8f8f6fbc50dc3385e2b438ba5f985f33dc5c68190c69b","seed":"cc2ee2baa8b309ef7e76fbc14a343a2435d6ce0f7da46d1f9a84782c77e84fd7cc40c503db71f75380cd7e2236c9dd0579b528d84b7deb89b0d4a4926c66a360","priv":"b2fb735d798aec932964121a2a00cfee6184f03bc0d7885a84507ffb1a8f97c7","pub":"024cd279a8812efb672200639f718ef89d9996a6bcd6ae9d50c1548da744bdee7a","addr":"4c56a50381b8edb7e02124e205e170979879ac05"},{"mnemonic":"twenty shift viable behind victory napkin cry gasp own dance primary glow","master":"4519e4b46f8279cefb8b261568638b514f8591a60617fd9ef4c0f03c193b345b","seed":"393b214e7d24adf4912b8b6dab2c779c2896816b1f001d80a702a7dd2c44b5a1efbc85e2554e2586eac150a1a2bf1fe12e08735dbab0ca65a746259bf953846a","priv":"a187f775899244b9a57da9a173614ef2992ce1bd2ad6333eea6e796f04ca446e","pub":"02735247ce372948d922ef85da71f424580a46fcb453cc889411722f8984f301e1","addr":"c055c01a09dfa7b360a99d784d05e715dfb1eb37"},{"mnemonic":"jump end chest decline act capital text puppy empty input possible goose","master":"5e8250d4fb78cdfa191efa589fccb98d2a635d091df8352a0aab57fa13be007d","seed":"fe6e62ac192f7f101fca767a1a24421acda2c23d1c232ccc19221eaae7697d9eb0cdf7350272d93ca37d7e10b3deb739ff0b05ee723a4acc754bb6994d2a5b78","priv":"f400703afc057875c9dd11e046fa53c0edee27c78e2905425a74139f3329c1be","pub":"02c98ed539a5905393750276488e60d851163ea5dbccd25e6fbeccf119b22f88e3","addr":"81473d441525a6374665b98ff30f75b43157b29f"},{"mnemonic":"spend course nephew spot nothing girl wink flight wine hotel harsh better","master":"6d62643bea35847c1ec3b6a7273c42a24832d28092402c2dab4df1004df249cb","seed":"5cca26006b3c22da1622ffd07f0478988c9c97c5f128f78b89fe6b89314ad8c37627f02eb630f376574a38c243a3069c5a34dc59a709d5264f42cb1f80740adb","priv":"dce7ae54553f89302b0aa63a500cee7472a4a33967aa8a1ee18e16aa0e78d2af","pub":"036052be2df30dd8ad7bbc35055a4e60bf520fe962d9c7158d1c5e2b45c4c4f841","addr":"1ac0320f22683aa7d67416e24bf59098933a7e4d"},{"mnemonic":"coast grass horn front broccoli artefact also history screen bleak thunder example","master":"c49a459ec914359418504d3d471fde7fb1a82257347a4bd95997df53da47b2ee","seed":"2f528e97791aad4a82a7af1a68007871a2b4917fa238d69137fb93f64ef1f7af2dc036079ec220b8be11365d62ca11be66e83ba0d829671a55a319c441f6c8c9","priv":"06fea4c71f85b7b161ec6edf5ea0b90cb95a410fda9fee0a603fa350f289ef43","pub":"022756af9a6df41e36de4300027a8a6a6a8f6bc7c2b31252153f3d915299a8129e","addr":"6203a9699c5d1b6bb64d1dae86cc741896792266"},{"mnemonic":"shield liberty wash park absurd inherit suit resist garlic cycle ecology mass","master":"a35a147cfb59e738ea4eaf9e6bcf1102c7d4c15e3e59458aaac528a0635d5316","seed":"fdf1adaddf7f8bec833c3054d079be7a240f98fbf08d051892a02c4b1e1392ffabf84422606d7ef333f99773bb8d51f01175c568a94f5317cf8b225991d7a528","priv":"581e1227a6f32dd51a3bf36e7c4f1504b00a528312f3025f3f7fbecb37b88b7c","pub":"03c0e2eb1d83e266c1c25cabbc6a9d46b0d955f70ee83b78ef0348e44fd6e8162e","addr":"18573866de437d48c044002b20fc5b886cd1dff0"},{"mnemonic":"spider cake process model elder electric mosquito rather choice insect crunch pizza","master":"1c95e3db98b4194020be93e3d4791b9aaa2c7eb1c83b02d7f3bdb07183f4c3fa","seed":"d25f0954443b2c18507a0c71923aaa31857d03187b08a649156ab634c20f29a444ae505cc80515e30feb69c05cd4e133f38b18659ae6189ea27b442705b9089b","priv":"5b9cff23b6a19a67864ec0973e3004da548b5b97400f9fdf2dde3db2469b776c","pub":"03829d931e59a87c6ffb4f8d512374ae7981ccf2c08a30acd787b77c628b727d8f","addr":"aa95e7e0c4fc203ea639873f05503a2d5e98b70e"},{"mnemonic":"include yellow off random knife video person monitor height virtual oven derive","master":"92cc90784cb9a58deb578aafd5b6bddf5195bac720c1b27ad575bddb1fe19487","seed":"7e090c19e128ee76d95f7334361fe7eef356bec53a06902c6c5bde0cfbbc7a7adc540eab3fbaf7d1e4c6ef38f4c29054767c115e6160e6825868a91297e2d5d9","priv":"076608b84151c535a295ccafdd1301e8eb82f779fb4aacad5bc2a1f0a699364e","pub":"03581ea3f2b7ec38ad8ad9717b22cf43192a637eb4d4db0b051f2085ccb43d9e5e","addr":"a68d0470048127c2234f1ce4a70f9f04c72c4dc6"},{"mnemonic":"chuckle hybrid seed portion dress move settle pool erupt segment annual demand","master":"fbad7924603e902337c9f58086a9334562d6f3866c798dece4c1761af9914d3c","seed":"ed3ee02d4b90299b11fbdf6fc7698613aca89749352bb2ecdbd5cf0e0436e0ef702a615ad041bd97bddd4e892582ed9037028002e2bd5c58ae7730c47a44e20f","priv":"77c0167a4fbcf6dc7105af046e2978eddf6366e945d8456c28e13c8f3ae4de57","pub":"039a672d56a39e6aa1bf2d51aa0c3525692117ef33a92ff903dc9611f86550b96b","addr":"d4fcea5b95282e1286e412122701e9bf49bab344"},{"mnemonic":"portion upper maid dash where control nuclear post run manual mushroom bleak","master":"66c9b9ac9c75057c18fa94eeb0f75cc73b90c08eaa3aecb1a83577062be3f6fb","seed":"06d6d3e53986a879befffbf87dcfd6b7570321a071e22092e1c88de34bd44d7ec72c76323fa0a7ca040a7ed90ccd686d13ea027ebb06f8c66154a838de229f2e","priv":"f5141661ead9339621deb48ffa15c4569cb2da05467de78a2eb631a327f5a68c","pub":"029a18777158d04ba09a941ac8ae89366a50dc8253319b71647fc1c6e93dab01c2","addr":"f1fa2abc32e5e9aaa843cb07c37dcd549b76485e"},{"mnemonic":"fatal lend tortoise urge topic sweet spend antenna stock nothing doll face","master":"2d03a7cd457dc67949321ed16a2893792e5210cd4bc0f5ac86af83897094507f","seed":"f48146154da92dab72fc0fbe1f6c7524178301502d72ae7c404b67f8b7e102306bc03f339424b011eb22d15977a0f12ad0b25e7adef5661d65b06dd0b5184dcf","priv":"d5908635bebc92518047b79599b90b1048fc2bf2d3eb36a2bfa5a894927675e2","pub":"02309e322a1c103c44ed7195044842250cd757b061430c55bf1fc8f7f10d660bb6","addr":"946728094cdfcc601a6a496ef5dcafd3de9a6488"},{"mnemonic":"blame margin glass dinner worth right require unknown wine settle make aware","master":"7297101c31d8168aee1fcb025bf1ebcd747ca6d5ba19d2bd28514fe3b0e0be18","seed":"e97413449360a70d3d202dc63ca0670a98aafecbec1de44d8c11f1ae90099bca926813685a429d4cefb6f0e29e207732f29e962aef7b6ae82ea3cf2d7617acd0","priv":"b144f77a520ba1ecd94b1fed5f362cc1fdd7ba9bdc355e9d520c2f39c0a20f7a","pub":"021c6773d45e549503e3bd6983655510a46a873e793c6cdc989356f657f3e5bf20","addr":"f259947fedfbb0ac039a44936e901f3622b9323b"},{"mnemonic":"gate make bird oak brave hole elevator tuna gauge type school disease","master":"1c1407749a31dca67aff767e4b78eca5351ab6792dca8aaa3b31a766147207bc","seed":"e079a04be32619bb57910662e11a006f27b02743e4440136ba02d7915502d0fe1590667a555fa76313452747a1384596950affa367c4a3e6f5b179e750018a7a","priv":"4319abffdaef48761ea2bcac50eaf80551baa1404b27b48fa379172f2fe8e1f4","pub":"0229358636cc2b80f63c7256eeb51b9e0bd3e1df0cb5e69ce87f15d71e16fa4a8a","addr":"d0134881f0c1f11cf9938920472f3d37e9365565"},{"mnemonic":"crumble danger tell frozen define mixture sadness strategy village mass junior kiwi","master":"0dc426f3c99fc31a73cd91f5c261fad7b70e2a7738e6312325686c95dd9df2b2","seed":"773955324075bed8d11f971096456a8557f8cf76750e48fa4423bf5e604943b5ad17788fda1afb47f03cbe208c79c8b6c38105538d6028b1ff4359e7f5a122e7","priv":"86f1207640ee12c8175e9b34cdc6fbdf2c200be9e03697fa82f8cf43dd8a6cc6","pub":"022ff8d5a67f1235242e9e143736bb950d391bfebc29173cdee50fd6826ca895f5","addr":"49fb80faca4a0537aab1d0b7ce5674d4490ff8b7"},{"mnemonic":"reflect mass fall habit mountain winner logic box cook between drift donor","master":"350db5a525a544ff7d82978817ce35f33ebb6c148b9ff6a9bdbd357a16373e97","seed":"4511bc8cd2b64472dbd108250e8d0efd825e763790bdbd44f4ab700c5038ab129e417ee574716e1b895cd660c72f9bc4f1a6a2846e7b09c635db2a51c22356c1","priv":"f2e5782037ff1ae1678ca2baebce674b973aec58caf7aa1aff830b372a6d6436","pub":"035d54ecb4a48285dc13346fe46cadd907e443c03e91339363b81c3d1988b09a38","addr":"6e8114f26eb00d95ea09ddc7d4d5cc104bd3ec41"},{"mnemonic":"enrich corn rose chest can figure canoe used pattern margin usage increase","master":"d38a5d82ce728c441f707cbced8d7b08d896ef9f37d0b563476d5500ca0008ef","seed":"ea926f98f2efb3af7bcc514969bdae01680e237424554b732cb37257e0b9f0ca1303af09dad82b0c967ce189ac8173901937ff42d0163310e5fcadfac1710c56","priv":"880b645884e27fd9205d82ad44c18fbfef02f205455ef818fd3beec79ab08e5c","pub":"0229eb380ec659c8964ca2d19196eb59804855b0d4226fbfc48f2373466380e1ad","addr":"ba2ea36646e0806378faea7ae0d1a691d91b54e4"},{"mnemonic":"coffee labor involve dragon upgrade route south guitar uncover enable soup sustain","master":"0dd39ec2f51c819042ad3fed701d1f982f599383049b38ca36da842bf5d3663e","seed":"f81aca2d700fedcc07990f1b9ecbaf194c0df5dbfd240437c06728bebf0022aac77b8b44f7863b13613b4bc5752f0f19e2a21617e5e0578e53f9198c2ae853cc","priv":"12c7b8c875fa9d0117b53e2e539584c9c524fe1519414a13062edb33eb712408","pub":"029b8bea854aa1d99e6564e5f4c9627a95d1fbda000a59ad3049baba92a474a5ee","addr":"eea20101f17d14b6bef65b393a49b9c558f5b87f"},{"mnemonic":"dash clutch smoke chapter lobster quote fat negative desert labor rent basket","master":"a6dae26374b6e165be90ae4f1759fff4dc4da104493a21c4e062d42a50ce1b48","seed":"2c4d251fa5b3a634ddafccb16393730cbdf1a1f20b44ddfa0a25ba2e5b6a48e8338e5e5a8a0b65bafe30ae629126789264c98a4b02ba96da5eb3b15fe5a296a0","priv":"5f7246020bfb4ab5146674df950ccadb3b014cb8956e4bcc3b575f710b4cc4f5","pub":"03f2712cae90744dfdec3a37990221e86063620b7298778ef4cbac6f438764acaa","addr":"7d8dbcba23c0e04ae21d250c585f511ebb825ff1"},{"mnemonic":"toddler juice raise depth club rebel weird portion void minimum game typical","master":"d56bc0aa70e0e583c13ea0edd4df5dd6f3b02a9a0434b0614f5fd9c2ec029b58","seed":"373286db33542c525710b01bb881158a7a1c723512596414370f1547edc08a11738d855569109b2249f927839c53361c8e0c8c468a62421c998b97fee5dab6e6","priv":"3db2ff05ae17ae227e78096b9803281f9332857f555dec941153805377f38520","pub":"031a9ef5c0a80f32c99f8c3af49b8fc51b3902ed13832ffcbd0f9527e057c0d56f","addr":"e5b70525b5b3c325b9a2a044ef05452ea0dd6821"},{"mnemonic":"legal lizard easily dream push business village network bread solve predict surprise","master":"4495fed7ff0239ac3a3ce75f1ec1e81fd3c8f7ac2c3a2a9d94f0f82a31042796","seed":"a709e3741759029624f534c66e8d8e56bb03fd8df960fa4776daee1c61810b96c495bbc3dcff634ebf140dcec9f7da9151e09856ee16ba5106cd7c1088032ebb","priv":"5e3e0925e33311aacc94b1d29f359f449d443cbe618e0a689d0c40cab692af21","pub":"03e2b6a2f99cf742f7c1fd356a6948df231a75fafb3cc471f9ca4ad00ddfad8c2f","addr":"c0980871c3f7b15830fa514167c90999279d496f"},{"mnemonic":"draw boat debris humble cactus method duck ask author soul busy assist","master":"8bbae4af997d4735d14c988cba637bc041b4b0907c5c53ecccc1456b43ea79b3","seed":"f05a91da4ef94c81e0bdd30ed6d9cd09cbff7013c693d6e8261bf2eb3cec9568fd3934551344ca8c768bdfdc44fd1b30a082bffa2c1611654320948883785e05","priv":"659c3413372935b99cc972629253f37305d258459c1a92b7fa81883ceb6dbb54","pub":"025a5af583aa8bf4459c72c9665cac772cad9fd49518b9080f635a4de283542588","addr":"36d01ca7b9f3c37ccd529033c15b1c089b877d8d"},{"mnemonic":"between equal crush suggest spoon material poverty diagram forget click company call","master":"3f2d83ceff7b98467d9cb2523820f55d22abd1700651f4b71ad6856c029ada7f","seed":"34e2764bed365dc73de440475c23b18cd69750977a4197a2efe374ef552a9c56eadd6ccad970c422730cd51e5ab4e051e4c86ef4db2284256186fdfa0ba92434","priv":"62febeb0325ae75eb0c71c4a3ae889a4a274f4ccc361cf0829743d5add3b084f","pub":"026e528216c24173250fb71c73019ac45e6171dd4f9d8fd97b0933fa964b966ac8","addr":"22aeb188b3a21507a27b35d860b583d9d844cb91"},{"mnemonic":"cram palace round input disorder armed wool cram over abuse order grow","master":"5c040bed4bfa8520ccdeaae710403b3ee7b77e069536bd87babd93c09177f9c8","seed":"df3911a2a01087b8826327ae368abf4dfac62258a1a7a91cd4ac64067d926b3ab89deda5a0e5539d8c0071d14815e2aebbb913e2e506c6574ad973f950049d91","priv":"87a97c3f977b1ce0b9dea5f2ca8671ab6830f9dd4b3da8195e603b7549f529cf","pub":"029722cdb8ceb0be8456ce4dcb24a4fafb1028ebb4d35b4af757bf22e8539de367","addr":"eff0f2517523745b0b404f688dc048fee89815de"},{"mnemonic":"donate view volume faculty anxiety degree brother cheap film eternal hurry debris","master":"762647d305701dbcce0a5bb079077eb514ad72981fc8489c6cdbd71991d24179","seed":"566c1fbaf6ce9a0c7352e903069b332aafb438ff086eaeccd1207b6fb8a9f0a0a4279307fa987a905ece60a04a52a59b3db45ec15892ba76b2308cf9db8e36ac","priv":"c0092fbde92e9ad29a52c825b8187f40fc5e4ca7a586f4b5b4a8805f0554a0b7","pub":"0340718652a6d3d2b791e79fa91e96f60eef740d10e3db8c8b206457f31b1a0aee","addr":"315ac67c85646a6ff00192c6752301f11e19e409"},{"mnemonic":"pattern much pilot choose prosper spot shaft camera unknown target wing movie","master":"1d04a744f4e0ca2b180f5f20ed34bfc800d0c874d232b5eee1018142fa612b15","seed":"2e1bed0a31e13e8f13a85a35ec1531a93ef433c96338f3e6533dd13d5bdae15bacdbeb954f9613fd4dfb6a941357fbcb5908520096502ab4f6edbf0c93e6f559","priv":"ec42f7fcebafba29c6d692ba732e8060d7050d7c57ef67c0c9d8ea152494a804","pub":"0295575d1d162b7599175bbb5b213ec3e79d6b632f5e50b6ba84e6a2ca15d70939","addr":"ddaffeebad79dfb4df2e2e35d9b6928900d38179"},{"mnemonic":"cruel tooth rescue step entry shock uncle crash possible inform inmate such","master":"f02e38437185794196a7822f0e4badce8644354fcb5d03e337ecee7ca0241df6","seed":"6dc6d27c01e91879638ef2281c904f2b3b0df18b0231c16f1518b63b39ce53c59335cb858b692f50decbe6fce2617434c927cc09d428a98820563438cda13c50","priv":"339120a922594b577d1f64af46c9dddbe0239a1ebe0187569c4302c035df4996","pub":"023e91521223a9a95c1df315c36ae543e606f426e1dc0b4938b374af5fa4967fff","addr":"c5711e1ffa2cca8f18b9be910c4c31330b8d60d6"},{"mnemonic":"evil height seek edge session require obscure begin skin outer foster able","master":"71495c08143478276d1107b9a496ca0befb1663524e46ae824b65e979b14b22a","seed":"2d209c72dd757b948bae9ac1d69014bda27b76dc890be357f542d994ee79329ea51114a1f721d17751152a1bbdd5c5e836771902ec6113c716fa016e30309a31","priv":"862d6335c9d39a65655c3fb644d71f9e4a902f085741ea4df75cd36afb94b0f5","pub":"03004f2c4133b0ffd92bdb3fef5eedd75bf04b6e7e18c0dea3204989476ad3762c","addr":"5d422b55f2091fa9e350655b2e550d209489318c"},{"mnemonic":"gravity sustain speed quit clock cage cupboard radar injury unlock sheriff alone","master":"44e4470967f781784b98f1e33d8fdd16568d1d43b1de044541a8e0821715060e","seed":"6c58333728b07bcf95ec884cb2ccdae5ec12dd67c3442044f7680a87c47da325429bb280727efbd848ee7f8c5fcdd433da0e9de39b21acb66938427ef6ac47df","priv":"37a9522e106495f859db94f5b6efd4e98d49e352b4e82cb3fd6ccf03bbec4b90","pub":"024b03123748ed0b4fdd8f6a351d1ab6a7167396fdd583aafc15233f5e79e3134e","addr":"62994a9de9dc8b9c9269287b63d847e90f519d59"},{"mnemonic":"fetch uncover sibling unfair brass explain sorry wheat talk web news exotic","master":"1ef8d0946b982a3233328040bb94e8e8cd0d5fc24b345f55535a8e7a92c22b67","seed":"f5b3db4d9c5686aff4eef0b0eee3cf88c4ffecde0e9b1c6772d9071fa433d5ccc9173f2f9e95114b27a37a1d91869227f8cb46b3ba26323e237bdc7a2365761e","priv":"cbb0527d80293daa1ccbf26c5e8f117123a63c0adf772bb80700e2334690ae61","pub":"0271bce67767a922d141970501f7341e7ef0f5d877df908c0c06e66000b94810da","addr":"368f8cd8319772499a4f2f109d440c2e1ea55038"},{"mnemonic":"follow actor noise creek afraid normal exchange universe swap draft cake forward","master":"7a443b3ca6069d981559e8cb1db37aded7d3e25d06f2f5ad35867c2086ae4cbd","seed":"3189fb459fb30288ea67a8cb2a46eecd8854db40b7f5b828254997301dae372d05b3eef58b0c670b510abe11ef7fa506b74a4280be94ebc55dc891776599fa3f","priv":"17ea39b63689ae32dbddaa2bae52e8fbd79d725a6a2ec0b56c432a90a1036bbf","pub":"02c3460e957acd5e228400055e9e1b22fc5fba87b16212382ec78b6131d05060b3","addr":"4e981e57f9e23760cadf381d28eb56d225f8b785"},{"mnemonic":"pulp fire pulp salmon finish question aim unusual casino super label soul","master":"3041f6724fc8fd54913ceac5487cf0b2a1c95e1d2cc65272f99d1d0918d73c20","seed":"424b5c69d42e95405b4d78c60f8c4541fdfe0600214623631154e144cd2ffcb3d6996fdf8838a07947a6b08d9792e6e883820399429d2427eaf4ca3cf2311e89","priv":"19026cc4be5629f8580b7cc5f01e36cea0cdb35a933d9871324b53eb9e4d62cb","pub":"0355a17ad503b793fd459e58e7cd85e13724e155ad487d9bbca7e49f939a89d514","addr":"e26908acb2f197f61f0036aef79f9c2b8e67cbd7"},{"mnemonic":"draft clap afraid census image debate pizza display sweet square today floor","master":"146c029ef74c9c9d00538cb03e70ffded59641ff8cd695e44abcbd71dca0aea0","seed":"a000df2590dc0b74a6b1bdc868079ff3172fcb9f758f7f61e9963aa49bb9ef1715985f3b88b0d1b22fbe5d30b2fa0dc489c19ab2fa42c5e62734585b6b35f212","priv":"4e39817ee6a106cd3b58666b9bd419c246caacd755c302c5440f7ff8b59a3e20","pub":"03532d53d02bdc71b0ffab4f5dd3222bdd8b49117ea8c10eed11882a21d604c72f","addr":"4ca53567a3b12f8bdc8cd66b1338c3760cd9def6"},{"mnemonic":"virtual search upset mushroom bundle vicious soul fine decade reflect basic nurse","master":"1e7e15314e1cac1584fc5d6fc5609db315a3a63c1baa96afa57475c7e05b77c7","seed":"183399406bee3c1b8c11ec94a8528e0c26a7c22926f286e320461809f84976cf31900b436022acf4635066c55bb793659254c75d4f18d692a07e20026d409986","priv":"8a07be43ff390d981394dfb29638f2464bded05d5daeb3bb54a93ee949f2da36","pub":"0336378e1b67b1588c6d5e279fc3fe58115cc24dee0cabb5f728acecc8ac6be8cc","addr":"e12910be135809fb5a6314212975564422d98445"},{"mnemonic":"venture wrong wheat oyster buzz cluster abandon rescue alter frequent way scheme","master":"15d4683cb037b61ab1fc64adbff7bea44f515683352cdc3b7e8c6d97700d66c1","seed":"0ea9eba247cce6f936ca4958c64cd6f8f19c3f68914018ad61ef9042a4fcea4058f32017ecd0f672cc8ace9af4d06b59bf2064983fb4615edf912f73343a734c","priv":"47006c978ed707415ac9da1eba861546e6a6150170db9699b585648dda4c863c","pub":"02dc09d31bdae4560008e82db56cd81fe95b6a6dbb87020117a98ea071753659d6","addr":"4a5c5ff9661ef26136b09a8e6af9d6aae0188e2b"},{"mnemonic":"consider sorry keep source session simple solar acoustic crater model hurdle champion","master":"2c3331a974819d6f38071aa2c790c42ad7e97111f5092b00f972859867cfbc5a","seed":"e4f33149ee0eda7a52f5f64d1c8ea945058b2f3b2cd0a0d8a85fdfaa2aa0b559bec8bdcbdb5703dcf2ac54ba7066f4d6c95b03140680b1f1d30a6305e4cd0b7f","priv":"3030acea65637e530cc39df608f467b4df6a47aba4e241c7579a608d8d53f12f","pub":"0340b77aae056f3e3e7e7bcd670c05a3c8975efed4e7efa0c0932a48031a242778","addr":"5dce4e49e053ec6443fdc36f11f1f9f233644cb4"},{"mnemonic":"salmon allow rebel eyebrow siren remind mango round task ritual exist course","master":"7393e3b637917023a724ff52b1f651f39da8a0d860bf20cb810eb635ca348eff","seed":"657dd9b458793c826944ce50c00f6cb97877543ed7dd6b113cafaa7971704a8ca5896fdb5118aa09c52cfd6b28bced9446a86258cf432339549e31b3abe0e279","priv":"46c0e6f6d527a46ca2b44d0d6892dc6c816bc0f1240b10ab2ec9f33050e35666","pub":"02cc668b114070164065c79990db45a64e4bcc5052ab0ca65a68f0dd3c107e6937","addr":"0da2a43e892435f79c2af7d62cc823adfce0355d"},{"mnemonic":"camera casino cigar harvest prepare satoshi close ill suffer chest parent urban","master":"1f6eeefc59b6600a739364a6606ac2c3a151b4234f1edb6efb97da193865402a","seed":"44388f05937f5cb3b47893b75aaac78ae919e4aba29f0a6934ef15d6c7d1df6e5afe36743320856181b5f0a8bc02e731ca83fec8dd501c9c845a1f0325d74a20","priv":"e6492972ca82c2cd62006bafe541c0ad5c6bbb01257600e8168702de496f3e37","pub":"0219ea8444509e7894ca706edc46a522244acdd643bb09d3856db3d9fb1c9821f2","addr":"593e42b50fa2f4491c831039dc1b4489333531c8"},{"mnemonic":"staff myth increase tornado student scare awesome fever promote vault write head","master":"5ce65c1772d4ee171fc0e843ee7b6124868d25c2cee48eddc73e92b805ea2239","seed":"88c5df5805a91765a045019ad39767a4aae836e8c0f53542c661934c3791f94b9d35cb9b1fdc865deaa6f749e583176ef9f114774fb0b59c0637d1e66dd6694c","priv":"066f7c65cb33bac2ef5229764c316ed587710752d456881dab54bae2b1ae55f5","pub":"0263f5acf96f7e6c02dcf040fa765db8fef8ff317400344cc92fa3f5d58f19755a","addr":"fc00f9a09aa3316fb67dba9e08c66d8569f055e9"},{"mnemonic":"during smooth snow please surprise winter measure weapon bench possible write night","master":"0af6eee6b3acb361f5743fec61f7377ca5db5e90a303484e7f877ade8da1e0ab","seed":"104ab4eb787b2da19876c47e1372bef860de1535ed30deec9887075d8f2c56213647f0e8d6b472b23f5ab6dcdc1f97cc32ed2842a0745589c196883967f2fbc4","priv":"0eab899fad8229fc681fb7c86d8102d4074c68e6503c644790125bee07669d76","pub":"02d13bfe147b234f2a81e3e2ae0e630f6be4bd56fe44dbf59b2336c689024b771a","addr":"86a7e52857c14411ec4bbb6c850822b7bfc8b7bb"},{"mnemonic":"equip clarify march rhythm supply attract dress sell clean galaxy index river","master":"aaa85635e77e16d5393f4ff5c73b5556b36ddea446f41c5cc3fd4cf6da2f324b","seed":"519f319e5c87b49923ef60a172b731c50da1da2eca2dc130ec732beaed5dcf161c2c4c98ec20b539259862456a7ab2c5f63d7789da98dbcf01ed23a3be7c00a7","priv":"b42830645c0a8c5fb59994bb7588e8fa80b6a3b95ec223d459a6652a9f3bd641","pub":"030b9ba15ca8ae95d10eeabb8b203b6253c0d08489c02dbe255221c42b16ecd043","addr":"5ac5bec20480d7b9007c9bd184d064ab6b1c9c75"},{"mnemonic":"session hint oppose damage illness metal combine bomb cargo unaware gun artwork","master":"d6322887157ca3852f75204cb3eb60ff3eec39450913387b03ac973f5ff09ab5","seed":"09900b51d5c10504fe63272bebdec8c2fde49190039916839b106af4b7340595cd5ce7a6be9866df28d0a40618b23d09a6f04bb963b05ff1b7e272bd0f0beced","priv":"3f012cc4faabdba2abbb64b9313d0a574b8b31c1d22f403f1d344d87ba3246c6","pub":"03b4a66483e09364f2fe2d905fe5d0d897ca32752df20ddbed0206e383bbd68810","addr":"0bc20be767a401a01d697c5afbf331fd7b3f4acb"},{"mnemonic":"gate credit cage whale razor come opera net speed dinosaur fold witness","master":"8e48eb7d42fbc6c30601ab45da446ae6c0ac2e9b709ac428fe1f98b5c8adcd28","seed":"be8b77e358eefcb5610dae1b36380d25983f1aa458c208e75a9117b507fed28975787d4531cf87edf366c29798a4a6d8b44d6dbd090da8eefbf6d97477b64ae7","priv":"24ef322d8877b9f5f352f8063498527685de6b7d056ca7776dfb1ee34c0696fa","pub":"03389070a550617f89cf46c1df8269a154bd4811ea7d519445ac1e7e3e3f9ecbf9","addr":"45d1a0a5f79d849577106135f7065782e972ade8"},{"mnemonic":"belt girl tribe accident machine library verb link host wire hurt elbow","master":"d604893e69b68ec73d7abee4d15303863ae766b867400eb6cc0c771e8eaa4a16","seed":"ed3677dc17838f9720d5c574a6c70e80c185a5df1faebf07c63bd64a3cbb43818f7337469d48142df4e6d0254fa73e8a8105c6306568bd8e3a1fffd2c9d85885","priv":"cc6d78f6b72176d96a3425cab46866499fc57a8de3a49d5b30030378982911b2","pub":"02926ca73be56e04b363daa330ad51514595250d48d8983ddf29f74749c1a81797","addr":"00cc426c8061740249ff1219b322f104f548449c"},{"mnemonic":"kitten monster sugar game word lion census purpose defy rich either distance","master":"d697b6319c74c77415f784aaa6b341a84ec08eaac0a3bbe094d5cef9be94f673","seed":"f6bcaac87b81723ee589e635ff4e5a5606cd28113eab6846f1e7d5bcad758c1af1c8c77c111ba1cb502f33418f1436220a0a080ee81c5dfd012be5dfb0bec360","priv":"cdc283846e3c5be0b327e48a83fc72d85521bf51321697f281333b6eb7fa83cf","pub":"03711ad3d292efc08729a820344bdd1efb9cd87b083d0ffd65b49f998d1808e520","addr":"71f678f7808db66273dcaf51fe4875fb4c47c80f"},{"mnemonic":"fury tackle glory welcome gauge rely spice profit east science nominee expose","master":"b04bb080a9192b41dd7ee5f9bbfca1396970ba10c54faa1b7a511950b2ac85f0","seed":"5c6ecf5aec8669d62d5db9e39a5c94167bdb21e9380f8efbfc967420a71e0be1d72553a2b84bac9b8fedcbfaca522b82b7b80b531615b9658379c236cc4bc5bc","priv":"05fd2f8cd2ea1cd0ddfe2acd25e498ebd81b902d51935ad3a094a2f2c9c62ca0","pub":"02c4730d47f1976f2a6412681ae6cceb97b899c4fc514b67b9070bf236e906bdde","addr":"bf3e06c5713080e1eb287d2eadf49de120aae6a6"},{"mnemonic":"young chaos must mom ginger hard symptom ethics father rain join time","master":"d9e68439465f5375de6e132498239c9d0f67f7caf16cede036da3fd1c3905522","seed":"4101de8d7cb1dc3176ac0781e94594a37b894ebccdb9d934bac104d7b22bf68d863fae68df1734ab10302025e53357b33ceec095e59505a1461aa751ca77e5b6","priv":"e8512f2fdfbf6bc1e125323de28f9f35931ab760bfbb2a736f750e3bf116bba1","pub":"032f51ba96193a6e24dffa85d748ed2b86e3677112b22da1d6dd5e2d98f987f0c5","addr":"7adb4deb8d4ee9aeca2dcc4dfcd5d1dffd3a2cf6"},{"mnemonic":"dash ridge ten when erode certain game rural canal race surface envelope","master":"fa20b9bbbaf883069a6a282b30870bbb02c8aeed3c611dd3c931bc217326c210","seed":"276e9b97f203454480976e1d86d4abca6072d05e4bd5b1eb972fba03cd6698afb7212e5fd77ff84bb8e68d45c641063550bc8ca208c00604f609a5770fd69b15","priv":"1d2ddfd078682c4d3950ec841b8555fb37981313d0ef69a7bff16c110171f71e","pub":"03f0d1613f82a900455d6834f6a02e037e3d6d7fbe08b1f3a278b2a5958bd13490","addr":"b190466866cfab3ed499547c88af1372f84ab61a"},{"mnemonic":"spend echo addict brave reason tell valve emotion gaze seminar entire game","master":"3d139abc58b8022d8fb2f0c622531874064a80fb4ad795b024226420f30f8ff5","seed":"d9d04d4207827877636a1a077468d2396dcba6ecd3398cdda7d4c15c1365518a5131fa12caef14a2b23702957b282903dfd96df19419e4ecdccf7c38487a0c9d","priv":"cd5f726ece1eb6653950ae42c9fecb053274b692ce6a58a5f630716fc9cc172b","pub":"03e79f46caaa31bca56700d91cb366428839fb09d027d13001ae723461e8575bb9","addr":"35c04d25b3205e9cdb5283b94f328792466ecbd8"},{"mnemonic":"moon argue laugh point unhappy long bridge water naive suffer curve duty","master":"72c22a1d7ffb152045afab5ab7831efd0910c0a4796b20fe9b741e2a06a0562b","seed":"c77d143d6a040b08fdd3a085c9fa097508137cd801e480752dfc55f776179dddf01199050893ca833af63f6595fd60b4d14944e31cdea626ee30777b681ebb66","priv":"af0e3a2476271d7a31943b44dbe9affb5c04690c2f9e1a559674f028a8cdb9ee","pub":"038beb9938f2f7bd600f8b0b48d85ddb9a09054534ccab4e5a3cfc36523dfbdf74","addr":"a7799a4603c1cad8209f6de4cff709ffb5ad240d"},{"mnemonic":"ceiling mother twice mask pelican glue such giggle session absent sauce copy","master":"1ab59e2748679caf59d4646f51b8cd7cf27c9e62160bce71a2da081d57e90a53","seed":"f46d771930a5a1f69674aa4459b0120ffc52f961d7f05a4f0629e580e3027e9112b81c582a74f92a63a0235d275be17a3ea24e8f3d86d2f460142cc3c075f352","priv":"2dbe6c2f1f3389a29271ed7ddb5d5b6aeb44cd3d762b9c5949f981f130c096d6","pub":"03da1b7e3745edb58ea53dda791d7dabd4945343d471f41b706ef2159f4895b234","addr":"14a8aeb393e7a99b53cc3661717b6a550f4ca30e"},{"mnemonic":"siege welcome clarify bread decline educate off snap canal north glance flash","master":"fd57e9d99aae7bddc7bf2218267db21683280d1c1fcbf1d0713d35c872dab359","seed":"d1771068274d476b8e3953ae1dbbac392157fe72dc01d9c1cb66936f26b07fe9de52c257f1f8a89ad5677a786a32b231bd4415a7fd6dc18ebc70d53c16d91f9d","priv":"8d0c094475b505e3c32bba7ad6817460ac20c5e75e4d5d0899d96fb2dbd8f43d","pub":"02bb4a1051ab8df516ba2b5bf42a99dc1a153127312a81f93b16121d2c60dbba1d","addr":"43b7281f4f0495f6ffcc129e1fe90cf772cdbb00"},{"mnemonic":"total wood brief sail top stomach phone silk soon flag beauty equip","master":"2d3e2c155708e47a76ee013fd8bd3d62b17b467fda08869fa5b474cd622c7e87","seed":"98cb2c832f8a2e59601b5dd85c1321251fa576f5e8b9ac250d18e45dfea7a492c80918d864f32d1fe0f3dc24fa1b8eec3cda8bfc526d4826e94a7ac352edc705","priv":"5de85e11fa81b39f6cbd36182259fa33ecbdcf309e2256a1ce91500a1c28fe91","pub":"02dc14302285378aa1783d6395e45b37aeec4456845bb90dd2436a15c601abf050","addr":"bfac65e04a1d9f0905e0d0cf87ba1531bb49bbf2"},{"mnemonic":"junior side human tomato army twin tired mammal sing evoke tape fall","master":"0a491a1d250b31b44ecf38584c65a733e785d65082d693847ebff6f7b749aadd","seed":"65c7faabd749b66f9f16b234142acf734fdeb1fe7c9170355471c008a3224c40c5c2b77aaf516f91fcf17e73f2905f021354561e56ccf08a9eedbe51ce8e8fc2","priv":"40dc50171a806155da73f7c5cab57f7db270e225c33eaf0665c0067e1d2f7743","pub":"037325819201f9eea88ab9e6856d2e60f02c41d3a07c09fb7161c42e05b9db824a","addr":"9acab1c1329b243a5959cf716dc5f29ff1a9bf33"},{"mnemonic":"fitness wire sun minimum novel scare response ten profit breeze equal wealth","master":"0292d1ccab93ad054ee3ff95f3fde715cbfb9b896894b56193003861f4403763","seed":"ab34f068d14286ef45af4f3339ac19d8704d84a3f4af2c00092f431f919252487759c7aa09511271336b3a40f446087e7a63d1cd5603244124fb746160ffe872","priv":"39ef24672e90e29f268369bdab5aaf09786efd7360b535bb4846035b12d1aa27","pub":"03db46d9a6c338affda7db18355bf17ddeb8519a59e193bfaeab4fa522b4124288","addr":"c3cad6c638d4f7d0a75dbbf9fb2d170f79f1cbf5"},{"mnemonic":"quit present half acoustic uphold buyer measure matrix uniform black play vacant","master":"6f8c86f53dab7d379e621daa00a25f6123d43ef2452ee6b7c20e43dff1379409","seed":"bee800b88e86d04b9e755c63669dd4d324c0640e1c121427cd08d1bff6897fe622320644844fd06bc16fd9bd7b981e473cca7cadebf7f50ebe3f917c0721b988","priv":"6070835567461840e0b216338b4a08313cbc3d8e805cd694f379fa0112975523","pub":"0296271e75096d7bfb7393b449318613c522774e7b2d4e0eed6161e80a9376bb91","addr":"3885ad9e25c274d8e461f4b685ec921aeea25b80"},{"mnemonic":"endless blade swallow bird faculty group rookie betray crucial amused gesture pupil","master":"f62cc9bd1a5d26309ff51867edac4548f63e30630afce94a59d94d77f6df34ee","seed":"f4100b5b36d63b0a87ffc828277c8eb2f0055d2ef500b402572d30cc23418960b831c84566153155d33eeb8ce65ac191882810a1281e87c7748bfb592103582d","priv":"14125462458c4e981d9dd963e67965ee70eaf50af376daefbd7f89a3d0cafffe","pub":"03b64c625b503104cb0f9e8de837c741c4952140348cc5d7d1ff379e35ae37df6c","addr":"64d529a1cc4a11c305c8ccbe24217f52be17a69e"},{"mnemonic":"evil lend heart deposit index prosper mammal vendor expose sun arrow school","master":"d3402de3b79b24291822c2737da8e7d760267adcbcff5af52fa7c33ecf199acf","seed":"5062aebf0c68ec4ae51b8f9bebe4cdca4a07989ed9a96888205a84d749ca90f8d9f2c992862f7fdb4bfc3fb2c590431c5fec415abd9a2d4ad04f7504b90a9081","priv":"ff7fa17496fad3c29afa98d427186cd43fa9aee71e2a81d2640fec87ebca2ffa","pub":"037eb47194d9fb1e61a65e399d06bc7044d02097a0e5939581fa9b15346eea38ea","addr":"8e9b1eef983e035d41aa63ec276454a075c52db7"},{"mnemonic":"various cruel sunny human sponsor seminar stumble romance hire cabin blast rich","master":"25f93ffcc752c263058f195fa4b2f80c46aaa057b399de9241c0fa8cc2d3ec8d","seed":"89ee6d4b8a328ec819556eb043c769007e332ec4ae0309c6b6f82ed70b725e9ac8d64cf1309ce0ebb0053ba515f6e42d1273ac4d0d1b9008b9375844a9e1ed24","priv":"4aa30facb3367721c7e39c3052e7221f0a926a00d00898699c483cbeff39e407","pub":"0312c6e2800eb33da7459a510d02e0fc5c91778c115c535eb429c2c5797675e2a4","addr":"9178f5d44bc450a7a1fc5746d17440670fa0eda8"},{"mnemonic":"kitten rabbit warrior replace dolphin banana aerobic arena elbow leisure slogan panel","master":"28b0f611c4fa230cb47936546853fb9f0e13bd6a4417b5bdfba9c85eb80313a5","seed":"88a78a4f882820e729d42557ec5db0984aad2aa40f535ea33416b0b89d25511fe4b6e37cefd23acf1ab65eed77b0c6ed2e453a2c7e8d509311cd802eb267200f","priv":"3af577c50bf57b6f44686af34c65b683c305496d1799c7c0d9febf9dacecade8","pub":"025901819b5c97d505616f3d1b5be0923564d5aa627885851bbef7b4efbac4f95f","addr":"9898d22edfe40425e714b877a5edf2d9ab5d7172"},{"mnemonic":"shy abstract heavy silly excite response figure math travel use cram dress","master":"558875deb7ade8202aa21350c8a98aa64d383c4b8dc6315a5bc149823398c8f4","seed":"256d310717830704992b0767827ce796310b3f561f5faa152b97c6bd9ca1bd10505049005da5026e64377dfc9b9a23b8f71b2dd8e4ae0644055a04b650a721b0","priv":"80c1b4808495fc23f7fba2bf9ff39a4b084371807c61ffa6f6b60cc863bc8fa8","pub":"02268631554db3ae0b7ac58b2437556d91aee4c2ff2eaac5e4a3fd6ca6d96eb960","addr":"e1b0517748e58df2cde812d45c251492008ae499"},{"mnemonic":"tag aisle unit arrow neck knee border plug order decrease corn hint","master":"67412592e636701931c0b0723451ee325db3b1b7d63938c83ab9b4aa5630be4a","seed":"590e676b0362db643cdac3687e67274fc7f67a2f3a6f274da3e8629893b1f474fc608eb2928fa2be01b9760807055ba11a7ca4b52a28b2f66e05bef7f09845f2","priv":"1cd36df351f7dd9b4746bee1d59c42f12b21ce84b9979e39b3b810ba95d13e56","pub":"0217468adf9b7f74d88b312883787e6baadeacf6436986573371bf19c359ce047c","addr":"a719fcec68779b1f0f92460e511739e3bc704be5"},{"mnemonic":"urge order bomb glance dream diamond cute quit napkin swarm oil taxi","master":"e7c99156c46a51a308bb59a9be9cec9d45a55a8f10908f2294b4a35734c24cdf","seed":"a31e29edd9da883053ab020e2058d482cf2a63b39a7d99f47a5972820820d5558f24bd4d86470f1b8f6d1707c059e2353c65ee69e0e2924376f84f36e77571e0","priv":"e204a5c8377829edb3a8866e028294d6fa34c6dcd76d10cbd857afe41f9f6852","pub":"03de7949f7a90aa8f21731e2979b684c6424537283dd15881f31541f14a0837042","addr":"fa9f6d11bf1fe75282dc336ac24f790086794ca7"},{"mnemonic":"drink combine way human stamp code chaos honey decline reopen candy stumble","master":"902a5423ff40734c67ef9ef008e63a232d1c0e30a8b8b75d911a5e5c31be5725","seed":"c5ee4ef92fab9bdfab9e859bd603a9b293509ae3b99427a3db2b3eccbeca2b2d717ff5d5ce010db0cafcf261e6addc949bc3c0187a121e303a0246125ffc249a","priv":"59e235dd2d86967f6690fe2171eee062c5e786ea6a0060069fab9dcdea5bdeb7","pub":"039c4adb01d0bffdd50a34a458ee58e19ed81d3f22f740af2414594e42447c9de8","addr":"3ae7c41fe8a65e527a850a44a5124597f5e43f6a"},{"mnemonic":"will confirm boy glare draft hospital grit marriage hen radio coach cram","master":"cd54fa9f850f2e90ead19946218c1c03ba1491d1273f6e2e59816e50ad80137c","seed":"1ac5cdf381522c28ff90b993d3a3612e0f91c08b89b11c83315ed78b7d89e7a342621344ed75a7bb1d996487da8b60ffaa75ba3ef504814636471fa017f76b06","priv":"c63babfa6c2e301910bb8cb846259aa0062e25ac8523dee9449354e9f44ab49f","pub":"0272029d11d7a1998e79230a4e82aceadfbe29925639f6ca6dffd237b7c12a6867","addr":"eba6a2907bdcd422c68a04093fc5127ef2945cc8"},{"mnemonic":"sister mouse nose morning remain bike wreck reject flee depend foam oil","master":"480c68e256ac710a18ff386a76b2a3ca50ab4214a23d2e162fd473f40e48ef88","seed":"267c7df08090f9d95d26c130af19c37adeffeb28644cb449a39fdc2038a5a87341fc9fb78a91c9d19b8a4843146e79e57cae43b9d1d65042cdbdc8f97c22f02b","priv":"d6d76df9474b038eb47c93ce8bdee2163ed5906475bfe0d40b31bc19a501a2a8","pub":"02a70a232ec5b59daa30873a4c11a65848d6d90b5775e488b87d8829a368fcd2e5","addr":"dfdf9f283fb3e21240437a994ccf124089782718"},{"mnemonic":"mule parent ritual earn swallow visit jelly give sun family scatter lend","master":"946aee32749e7c2527a9d7066df275f6a58b4d979778f565e87db434a4d82ec0","seed":"919d5d8ecbf7c9ee555aec51c4079aa8a97ba7c6207be27a119b307ecf5433e0e44856f21808b1a7c65ccd7efff25eaccb445cdd3d45c682aaea9d8358fd398b","priv":"1ff4a74557f15dc78cbe8c3fe3b760c23c19c2ffa12e6fcb0c452fac97a8c1c7","pub":"02b880cd243da4622fd4084c0779a34c117cac73c193de6691cfb9783c23a13751","addr":"5157180c3b43d1127614fcee3c772b45f438a73c"},{"mnemonic":"modify puppy army pull trust icon suit submit fade game near machine","master":"5b3dd4912f293341f8e62b55d25a7f01debaafa1a8ae6d7d9e34afce8d534c7b","seed":"e73259b5532099bfdcf2196ba80baa86886343ed2a5a7dc081128e5d94232b52d3914a8fb9ee17fcbbdd0d2199b2febc3ee1fb430729a376f8106439d45718e5","priv":"5a502a6484aa0eb1f7d963d950574d1cc348f3f64b1064f0d6ae8526293b9f89","pub":"0279d6b5231ca7729c450b055d51f350ef370544b83d10e80501ff5063961ec425","addr":"54a6fb03ba980c6efeb0e4e6eefa8d5c06f68dcb"},{"mnemonic":"beauty fetch title weird machine section remove better kind unfold candy risk","master":"b9c854671b0922cd1c27f876e2bb2748e74d7e5c56f71b7bb24e0f121c312c51","seed":"223ad6102e7f9e49ae732fd584519ebb6c139fd5cba630b78d2e5872be280c5c68eb6ed3b5b09fedfde8cbf6dcc1624f3380ae464f1d30c2abcd8d8ff5157e32","priv":"9c0c7cb874257ee95038077d5fb1be111685c5a54c7eae74da353fc2d476766f","pub":"02be94467d1120e497f16254d1840c431ef8254eb6a0b1f8b6e63b9f482ae37981","addr":"1c3965d6dce5a86ed7e176420079ebd2f475871d"},{"mnemonic":"broccoli ring road spell bubble slush cable column boil wisdom glide again","master":"dfe7a6221acf8d8f8b29530792efa9ac33b94e352f64ed3244062651596b0b1b","seed":"518f8503f16e8e5810486d1ea5b70951fe6f17427cec5e7f68584d7c7f101d6670ca755f81501146f3969f1869faf5efc6aa639ce47cf1d337367ff2d5336358","priv":"b7c6e7af8ffb55f9282d13c51736270a9b488191d8e9a4999a2735d5dc27ae5b","pub":"02ad6e0ed23179b9a12019db3afda6555fb3e088f2cb91eaf53db823bb284e7681","addr":"cc65b77303a5d3d42de2ef404a05ffd8b0fb73aa"},{"mnemonic":"settle jar tag talent bridge onion jazz vote certain job high lounge","master":"fd3df0c73c84b19831fb4fef9b6e8dc4eec01c845c38276f369ae73805cd5bbc","seed":"6944f80e097b237b7eb501d2d6d735c644c7d9fe0de4a1d12665b27a1567d3d619d41a9a469622c57f2e7998af4f8784dc1bf30b715b6c867d61902103ffefff","priv":"93d91fee61fa1f6704da23dbd1ee4b5513399d1d7ad52c3a632d5e3ad5884895","pub":"0331248b1a2b3ac8919c5654220fd21a10d2f700b2bca6a16d94ab25cbf60631e6","addr":"8219e185c9dc66aa8ecef927a93e884494251762"},{"mnemonic":"say unhappy visit follow rocket bind capable lunar age erupt depart leisure","master":"bb776f6f57d90a587b76509d6788c1afc54b7a35a06ace60d7d627605e462d9f","seed":"e20ebb6b86a37149a20e0f07a637de61af6d37f76d9bd84c210c8c06f92d23e167acd0098be525e943e2c4e7378903f8b4572190ba1c6b37ed40fc023b355e93","priv":"0bb90cdd4f552b15991e6e9c1546d78b4445af65e60d6cc850b7d4f64a6406d5","pub":"0342b5a2ce673cbf8610f049dba20a0c7d92091b7df857951aca402e56acda8a8b","addr":"1af59207b0004314be04dd208cc2154e06476ed4"},{"mnemonic":"next broccoli cluster someone just you crouch monitor crack tribe slim cloth","master":"87d2484fa935339252c8b0db3b4604f42e12a48ea00d22abccfc8a4ae9afd60d","seed":"abe12329f69d107732e3a3eb4ca9bd693b1ad465a042530031d0cf79e4d32a42185677250418809d0cf7fe7e47e0deeb76c321a8b82060666d36f8a79d68d2b1","priv":"9fe6b21141e8035d253dd8fb9e6009ef14f1680f58629dc880b50fec649bc00e","pub":"03af8824d512a243566015275cc2a8af24fae7acc538fc292806c2c95688797e9b","addr":"02f4e6e52415b7e25431c0af1f43f7dce05b08b7"},{"mnemonic":"scorpion artist craft enough whale maze copy ring search sugar rhythm few","master":"8700b2c3bc7b441f6600850cdfa90caa3fa8e4aa6c3091d9850c42644187c053","seed":"cecd5fef8caf60fdbab007cdcfa920867c0057d0c65b55ee569577427914e0e3227ab8cea26f50c1596fcf79a88a521721257f43dd84ef1d81e2ae4a8b73ebae","priv":"8dbc85572bf9b0f91c5e4f1516f3056c6a3608fd78e6b37e7dad0a0a5e4f6c2b","pub":"02947910def2d55c81ae2fc03727c62440713b0cfbaa854f3c7e9cc5b8f245a2fa","addr":"a77f593385c2e978d99f0a6a3d06e427f01f1c7a"},{"mnemonic":"improve help region hamster then raven eyebrow account sleep cliff copy pull","master":"e479782ba4b1b4f605fe2e892c6449a91a03aa8438668e22df211275a5644c92","seed":"bd788f3b47b98d37521fb5d51e35d42489fb83e21dc4f0fcf55dde6c2e1b561b63ef22f51cff2c190ef8b18cfab7af33df8e83d14d066c6b114404ba809869c5","priv":"a2deecc348654217762f8e5a422b3ab8aeb07738a75c49de9a1aea6ec767f4a6","pub":"025ee0f9bd4bfb85e42f918e91294fd9023831385e73ed06aabbbb7234d1707def","addr":"b80dcc0683ebdefb2a30398b0ba1478de6742050"},{"mnemonic":"bronze fix prison velvet sponsor woman vessel crunch forward sunset similar wedding","master":"608887c856e38875ce02b2bb7e6899698cd395db9ca1e19ebdaa0dea5dbdc1c9","seed":"66a0fc313ac72cc89a85bd4144b69061ca1e65f7d1968824f0cffe10b10380278428af5b6a114d6ce2a88e3626dfae38133acb02096d0b6ba7b9761a8c4a0eac","priv":"47de7838c74b2b1ceb138fdf96d455deaf8fc2550246a479ff98aa706b1d0211","pub":"02202887af1c72f72abe2754b6022a163b2abe5ee9f288126dfd1756067b03b5d7","addr":"8756dc9521ce9ad5e22d2612657e552ced185071"},{"mnemonic":"fame answer typical zoo key rail state chest snap stove urge collect","master":"377482e11aac4f724c3a1f94c8abef488f1807e3ad1a92821d7dc3f6377a2c3d","seed":"ffb372372dce3d525e923ba290828f0b5d12f65b241d5e3c36d431c1e1b3ef737f666abffc9d7e60aac3645a8f385262f2295b05c42a4c2f8bcbc3aba9edf5a7","priv":"bad40853765d64cdc729c94aa5e114fae54ee014517dc5231be8321bf7d93266","pub":"025d64a940c5b4dabfe233b552e43239b69dba164eac66b48a36f4e06915539575","addr":"f67fd1e04384628a47a01b88c399b30df8e5b226"},{"mnemonic":"expand machine nice damage roast slam example resemble tonight enforce salon benefit","master":"2e9614bf212cb179d91a224f1cc36fd4dc0a5be13eb5ef3ec614cd3f5db5be18","seed":"97c59f53a69f280fcf28110dd05e7510fad1d00e26d30847bd1dda99324ea2efa8550e5504f2f2648fef7f9c03ec58b2666b94269b3b5bbef1577f17af22ad1a","priv":"bf9962586c0636a20519a0eac17870ed0fd09862d4ebb563b3f445a179873551","pub":"027eb40d841c1028b75f21d593300ef57c3defdc258d17511ab086988240619261","addr":"d107cca0ed49d72efdde4b9369855d188f37a65c"},{"mnemonic":"debris scatter erosion dad quantum almost zone off bless tuition garden phone","master":"706940b567f1ab966a5f2db1d3e5eb832cb827a89c5bf2d17e9f3628ac6f88ba","seed":"b5caeb5e19c5c3e1e7a1074c3e4f366431d57f5ee5208aad341020fd33b2be38c2a228201949b6812513b28523cd82594a2db67177bbee6472bc5528a0fc01eb","priv":"671bab5dd3060bc813898cbc63828aacf50819c35981793fa9dcbe26c3427dc4","pub":"0283689f70b17659b51e2a5f345ae95e3a23fcc69941a5a842e992167dd958ab7f","addr":"aabde1e66f358e648444fa2a10be7404f1d6094d"},{"mnemonic":"expand fence want silk inhale web seed slide pitch fever online puppy","master":"2f3f69643bf40d05ff4be223ad7f05f0942166b629b6bddfe022df650b52a235","seed":"025608f609aa5f6662cea4323e4a4fdb4115f68d8cfd903886fbd561bf9bea74ec1e0c5d871ba46a1821efc769b2447c6b8d8f242fa0dfec8546c814f97cd120","priv":"26b51c99c8bbd84af26776dfb9a244114a66929f24fb782f195267fa7b35bf89","pub":"028d38aafd513f554facaf66eca4907f01ca8c48807898b6e142b609e93c3521cd","addr":"f5d92901099f9516401d963a0693f4d173cc2138"},{"mnemonic":"pudding mean volcano leader grain general because hockey mask solve frozen canoe","master":"a7a2aa088f904b0c44d1a307a17be86554cd9862f47b08f58205a7f73f93a011","seed":"d4e9852e81f9162b8fd6d1ce152e96a52b70d59289cbb8382cdb7bcbea5e5c5b6649aa6a2d138343092886474816c8e9c9f8c198d77986d2d6f7e1476f1499a1","priv":"31535d53290a02faa05f04894d6381b6edddcb7a374b19f8940d4581f9582cbd","pub":"03f89337767bf64bdbbca6a53184c126fca28f7613f2668a77119f62124f52a0b4","addr":"bd54d3175097fc470fefd66c7e5e63e7aa28cb70"},{"mnemonic":"make protect hungry coach tail female capable swamp alley one nerve nothing","master":"f171811d3c1b278279379244f480bdc165f5b645521749b2bf7b5bccb91e64a6","seed":"f8ebb80407da43b794542cca52f76b053175290dbc00751dfcb4539101bcf34369f76f686642c46728aef4b93f91f5ed2896b2a102aa3cd45e54591fcd0dd919","priv":"ea4ce4340c0eb740a33fec8198c22ec0064d72dcd74f85405f6d7efd1b1d0538","pub":"03e06202e127c7996f8367bcd0b28f779207cf222ec3d5d4190abae78fee5ed57f","addr":"54ef6f20caf4216e10a99ed446c842e3e9d90ed8"},{"mnemonic":"royal behave retreat force stable law cabbage home episode valid similar amused","master":"b2d8324833e37ae4f1a9a70dc33d070223b6313fe60e31a0c240b03f644ab78d","seed":"2448c418181d981fa42c83da24dab9d73b6a89dc0f86f624992ec9a982ab04e84989ff541364f4a289969d458364eabb08d51249c55ea16c29c6b65b5b95d7c7","priv":"473b6c4e1192b52fda7e64be4c34ee0197604c0e4c918d2a61e98f35fbd3f9e0","pub":"023bdc3332835493ed0258dad839d90c8503cd7a2a7097893170c6498dfaa2d534","addr":"d77a39d95f6204755a78c3b996c7bd84d1dc6a42"},{"mnemonic":"major dentist hurt task dinner exhibit soccer disease bullet knife hair nest","master":"9202dd767a3b88e0162803d54fb1e251ae14be8337829efc06770dc83aefa0b6","seed":"4c2d56edca18105e69c59b683d76034ad69006170a595c5648c84237ef0568862d5f95873334769be9937b83c5c96881569f232dec873e3947bdeca6831b1952","priv":"4db6777136a67a8279bfca36d0531a93bdc9e6eac4496fc20acbf78268e35d69","pub":"02d35a568677e4be8cfa051c190e54af69f8124daf5f39a288bd7a0baf1b1b4b13","addr":"6b8223d76a499b98d5bed2b146768569eaa7ab64"},{"mnemonic":"ketchup urban occur rain cheese bean need august autumn clarify kite chuckle","master":"8aa0b8b32ccae13b15ea9c808fe3b1185026c52a9f3b39546b355aab66d7f9a3","seed":"c910c33e6e009667a3d64ef0d10ce9738ff80aef32326d27b8f82bee0abf523e2940fc9ac6dcc27d10ed602fb60a99409688142fc18a9fab36fdadb6d76f1693","priv":"4541e2bafa8a4b3fcd1c9b49f646b3950292e0e18c2f1accda6d53197aca0d02","pub":"0336ad51e9c8d24af44291449aa86d4cb798181b2bdc9a2a6ae6a7c857a5d72c4e","addr":"9a37a2e3c1b6763a580a3b2aea95cf237bddbc68"},{"mnemonic":"shift anger harbor behave icon boring zebra sketch kid human nature learn","master":"139db45e5f8cbe86f23952b1558df3924dc55126119abcab216158285a645f61","seed":"1cea92117d8c90c554ae3ff517be704caa5c0d16369f68eb061154d59fb42ab9a6ea7ddcc62325df2c63ba0349e73a50c291edc1ceb0184012b71f2f5892a4c2","priv":"638fc2fa201498e1d76356acb3f4c5b42984c2c4b8619b0138426183daffb725","pub":"02272782c09fd51800d483c408ade4509c5cb83573293b873663a8492c1bf6711a","addr":"020ca2c2be203a95c0f7eade606d9c27bb572835"},{"mnemonic":"chat grain wisdom yellow rough swap notice range collect maple actor genre","master":"57363529ed9e9ae59ed408390581f344a7b974d130b23fc1da952983604e2cc1","seed":"d4b51a786cceb10f907941092f90be911c3ae2eca9924dade05aec85218baadc6b8137e86f4723b7500189529bc1da0b4cc95d1a8553cada6beceb71b12acaae","priv":"6245ecb65a10ed313dfc02843ac8e848a17aa37f6c3aa64007ff0b54b591e37f","pub":"032c33f1bc81371f8e599fa64736879a9fab286469e271d2fcff6f97b1b4829e46","addr":"4e076a5900d2016f08628257ae798a102c007e94"},{"mnemonic":"feed good spring pulse avocado smile surface conduct copper chaos dizzy describe","master":"003488e5bb876fb831b5ced5126e5c85ff6f98203dce52820acb139e31859ad0","seed":"e71271c88e445005f5bab28a4ed6c9d46f41adc6b646870c4097252e6f01d51ff9720d2960c61b9839cf29b559232b086ee5694252bd1fd73d601a27d78f8787","priv":"7702987362194e4b70c66b9d0d330a383e2710cdf863e5bb472c31815b6d9fef","pub":"02b790b42543e16b9c30a23baa39da3ed1d48402e51920187eaaa6796767ebe49b","addr":"778d3554fd4323ae321b6fdd0d907d28a4f0a886"},{"mnemonic":"brick wool tired another milk slight owner year electric later because response","master":"473c6a0dade946ed832babc01cac18b33ed7ea2303a362dfe6671202448a1f2c","seed":"ef22617d9f1ed62a89eb986d9addcb33c98d3da5e205c4cdca8c9b99f6267e0122d86be0b5f60c46d8c9f4c569c3ebade2376b04901bf8bfee5de83f6f818a21","priv":"7df1f72c7a5cf60268e760c29246e6e43f8168ab56b9c83d23df9923a3e51380","pub":"03de70b3833b9be36c88018dc6296feed7ae17d995af5b6942a67bd39689129498","addr":"27f48112f2be720f42706681bf2e97de964a009b"},{"mnemonic":"poem rifle october destroy castle scrub yellow brown soon this share radio","master":"bd39615405d3b2c25d023095975e07405228878f004b48be0a32fba278394020","seed":"578f2a69d418ed6bbe4a7639c6094396821dff23d1c26ef1a5452e91164e142fdcea44d63ec2eaa8d491f7b3757147f371ddb624fe10d6f7bae502e062671100","priv":"7cb45a918ecb28afef642f002cb9627381e1986ad90cbbe54aebb118724f1417","pub":"02ad197d4780b28d57ca50799d59fcc6956b2bdb24c8e2c2a221d5cf65007d2536","addr":"09c81b6b7dc3d57d239ca18573720e063144916a"},{"mnemonic":"hedgehog october thunder frown game aware reflect art favorite elite urge pluck","master":"0f2082a1d92a2d2ebdd605f33eb470568c7d82d0edf73e2be8a766d060dd61ad","seed":"9ecc3fc4516a37cafa09405c306bf19f53b085088a1d1cb0c54bacab3f21d4edf4adcabfa616137753a427c2269d3b3334a952cc5f4531980034433e4bbeeb9b","priv":"d3e3e9ee84d32091f08d7fed384fe3ec0465ec460f90a2749c69883dde03ec65","pub":"03b5af12849876b7c9c0e64833ea79c5b58f4450e4d67a99a90b3c9ab4ec3c8155","addr":"c5a46d31f9e363e348dc4ce803d44a676ce811de"},{"mnemonic":"goddess wear mail poverty exist pole advice blouse famous inform wrist pelican","master":"8c09d67d7e8691a66d2271093d7f74f5eb37729df23bf98525874b6d600158b5","seed":"093b6596b4986195e484e2d8977c8bdc20529c58527d9181c4d4e993495bba922fad305d8d4f13d9b5ba20c5e375dde147fda5aea8accf634d522e488d163c88","priv":"b028bdd6652a16380c61134fcbb095d372e63a117421fbedc46754266edaf916","pub":"03bb1f45e672d983a8856631fa8193422820747e3f8706e55d761d94bf091d7d6b","addr":"528f7468425b08f67e90058778cfb1efc46182ee"},{"mnemonic":"increase debate symbol swap raccoon crucial noble benefit kingdom prosper proud medal","master":"eb8bfa1409b9b28fb7c826f884d7eebaa6203e7bccecbe133e55df59db2ab8f7","seed":"5521921a26a36b06e62a681e2accb9a1577b6342085e9c9498f5693ce6b79fae98b9addd2da01df263445b5e45d2b4db45621517f96b86cd43b0ed00f7797fe6","priv":"e1927e2b0769daec6f1e7af012f1a14d82d52b89bc83a2fb9d007be1a51be4bc","pub":"02d41fc73e6624af22813b072d72a1d31fd628a66ae61e5d191c374be419c4a586","addr":"cc942c7413a8ea0db73c6cd3e2bd4c5e46ceb395"},{"mnemonic":"upset dutch damage thing maple ramp marine leave audit ugly walnut cricket","master":"012beaf52cd1e042c96753770315d25444e18cc63446a4207d57c2287d6ae028","seed":"dccb359dc9c2c2000e0fc23e100ad2ffcaaa0ea9bc1cf036b14c9c1f1542a4f9747097994ec5dc4071ea6863c01b2a5bfd6f747faea05dae4c3fa03eb2716b14","priv":"391710f6f67f54bb50abc86e349b889d0163a4c91dd1727dd3a6ae0912defc72","pub":"02bdbcdee705f81a4764a8e62de4bf6cd26f748be843fa36acad975980c5ab1b58","addr":"888ac8af30c1372d6c243363f6a8d97d3874eb31"},{"mnemonic":"truck stairs excite range van electric alarm sing provide mesh jazz cloth","master":"ef39accf9d3261de50dc985194a30b1cea9a861e2e48bcb47b8ba4542f855259","seed":"088e1bc0f701ada0c35c77f0d17ac9cdc3fee9747410407a1748b2c7e72bb37f2a9382e1108bcbaac1fa2db5aba2bf34574f47fe46450aaffa7712e5fefdd40b","priv":"e2e2d2973b52c1da6098e31018dd238b02ecc1d22236e631ff9d3009572ab1e7","pub":"03bd54aaf28542c6d155ebd24c032dde7341005e69a5ef67c3de5138b546d9f462","addr":"246b883c299597436993fcc8b22d9154db9d8f1b"},{"mnemonic":"admit penalty clarify isolate decrease draw virtual rhythm trim brief vocal box","master":"4df1d8bb85983df8abb7af56086dd76becdde81861462889c5a0809a470125cd","seed":"4340047ec19d4f318596cbe510ec11f233193b72214487cf3e8dd90c11f1466004810ba433261962b9c412b22c98655b06421b3bfe73ecfb1bd95aae30142cef","priv":"965f07d8304bab4719f071d1e3b656165a70eb31fb57d5cbc27e03780416d304","pub":"02e3a67f5d360f10b1786406cd2f1dab2abbf606fa014502ac9a7bb56616597776","addr":"90c64758c772184848b10adb3f841f14c86096da"},{"mnemonic":"citizen fire fetch luxury tumble analyst pitch van sketch measure effort danger","master":"e3469c68ff7e9f4e68af468ae8be59df246ae039ab8ecbfafc9677d6fa0b3d5e","seed":"bcd37194bce09d9704926235b5c83323ca7a71ca1b3b257c5436267a1e14b7b37fb44ad7fae1b818189240e9006cbd920b36aeb204ac00f98faf9e1b1c2b7034","priv":"d3f4ebbfa161b543e250ef0b52c027e49548d5a36a8bcbd8cecfddf0f1ecf92d","pub":"038f2c2418d2a68827be4807f06bc9c59ca291b34ee5284e860abdeff90197d40a","addr":"a44c929bb81a0dffc76e8659a44f85873578c005"},{"mnemonic":"claw stage toy keep crisp memory donor surround bullet ball innocent faint","master":"1025d24a465ea26b933c44575b283057daa066d0f5f0e12c9411ebaaec29d26d","seed":"effa6fca939b041aeb89550f138159090189a0ab3c96fb9151bd3ef69d29b457946695331804e437353d134f0d069b28092f122f35e74eda8a2d643c3d1a0f31","priv":"a81c4bc682ef7609d7ea9bd370703eef25006557166b9e04e589083bd7cd65c9","pub":"03b4d5e3abb4a6eff0409b20d8a1a88088e591a6ac3e6e25fb66f172303f55e590","addr":"09e4b6c1a32ed0e0b671e0f241708806a46fcd71"},{"mnemonic":"rigid neither track gesture effort venue vital bike spend unlock special swallow","master":"33fb6294ade198c457bb6d318b2eae4d2757977af36b988e042f1c3bb42afb7b","seed":"58b191573da33c6a4d94b8589fb32f8c5af326f5f40ced92973c352295e71d7a07251c8b42355b0360fe3ee2cc42b3217fedb914ebc61faae8a0f8cfe579fa98","priv":"db272ba1dc7e8aef500e29a4acf750dcc6fd92e4ee2f2e4235e7f82034a1857a","pub":"039d506e2c16bffda4127fc073a6e1b43b2c0ec68cd6d86bcffe0f0c4663b5033d","addr":"5485fe5a806040bf059c1e0d90822b49d14a51f2"},{"mnemonic":"sun ankle door drift sustain task home retreat light say wash pretty","master":"b0a3d174b40c1f2a723e3a62f878c1d4d19673c632a19fbea460d4d0c35d14a1","seed":"63e84de6c5f71a4b9dd5fe8998f00d0f8d0f2bf6da159d82bc8fe30475d0e909a939d7498936ac183e8220acdf104aa5dd0f721e65eb06e99baa27e81314a2b2","priv":"7e2d6c88823a8effdb5266c8fe605968ce231150169e0174e140643780bbbfa8","pub":"0280cf1699ed3cd91a57b8520c1173c8e8ff036cf759d4e076df031115c67e62f7","addr":"c31630d1643d32f652d89791c5de3a4b671773a8"},{"mnemonic":"ball symptom nephew dwarf mango crowd radio shift degree envelope science job","master":"449cdf41d10e6dc749aa52839a9c23a74c41cc7be85bd76f7ef0ea8347a76db1","seed":"303c978ed8b692e5e334bd1dfd0ece8615af24457129e7127e2ddc69f783628cc48d0d31ab522ffb6e70761dafb755f5878b45579911d52157c37c1b14b900f5","priv":"f6d3c4eaf86ce6c5c8d640edd4a67ff7dc852b6fcf36918f2b9e36df710b2049","pub":"03b3e239dc04042dc6c83a8ee1973917cacbe375786c73aae74a6b46cddba54773","addr":"f0eabf6d01285343afba4b7005268ed3af052d90"},{"mnemonic":"cactus trend empower board street stick animal replace media unveil recall proud","master":"17b6f0a996810ab534ac366a8890f7618f372ce0168b00655740f9698cb8595e","seed":"6ecace1a5b927d3058a08f1a59bb8943d214ce5e48e3627be8995814640782de30243f5a552e5600a3e1c62b3a46edb558434ac56bd105e4fe23aef8a1c0e4f5","priv":"69bbc1e6bf17262180141a0b00e6c410c3ae5b10b69b20d6321aa3893250cd6b","pub":"03bdb7edf4aa8f5e6bcc5bfd6a898671b0fd687bdfd9f8101f4ca840a183ffb226","addr":"c5fbfa7d4e0356d88cbb5e5bf47a67e877c1b1a6"},{"mnemonic":"source note bundle laptop pistol business only dust bright govern illegal melt","master":"9e7f939a19be0a48a3d9a740d8082b968fbd41065b1f5d425cd20d73d327097a","seed":"22b6512400907bd050684ea2ef220c4bcfd35d59de2c4c5dc3527436c417b68cec186640ea1be40dd00ff27b13884cfe7146c84ee3d568b8f74272f0edd91574","priv":"3f378db3f2004722591ed742f0d802e6c4eb51f357c1d77180a777d083b2ce35","pub":"034c05a98ebddfc54812ccfb797a99f3cc09e525759b7f40746513d58ce8577177","addr":"d920c5b1bd40b6a0c3835e5d32a8c8d5897a18ee"},{"mnemonic":"pride mobile flock dash second emerge seminar theme lift motor pave grant","master":"786638e9248b3b0ed4196533a1a437e1db7c2a83908c71823e9a8cf720b71975","seed":"59bf3e8f03faf407d8427e9b53093cb3708192de0c979c2e0a572a905af89d5ac43c2d1c2480cad58c63e3dcab5b5679a4bc12a4341cc618836d15f27c2ca623","priv":"f7ca55ff74a0f55f08cd8efc515ecc69d9cc6bf2ca389a3116f906d641de1f2b","pub":"03f538159091c45fadcfe4ada5d2a1a3827206bb4fcb756b9573ddd381b39621fc","addr":"14a320df092aafa1fd0a5207b6408daf532072c5"},{"mnemonic":"obvious man chaos alarm symbol novel accident label engine noodle inject empty","master":"df206751043497e26c74fde7e068376bdc0771e3e06a1e8bf17209bb9e1880b5","seed":"2178b8972916ccef4040e2c50cc9dc039a6ef7f799f2287d8d16aae3edb6ec0a20bcc4798299d2569cf6183d7aedcb426dbfca1971aaa31dc4c202f40c906a55","priv":"ab864f86be6e1970df2fa336835986e60fb7040a2edf05a196eed2ea9ff42627","pub":"02c8db2bfc3c7377ba3ec38f9aa7bb1be7d70ed6b15d76d3d5980f983552ef6fdb","addr":"c595c4572aa4b833719c935db03afefc56c0edc2"},{"mnemonic":"client increase remember size asthma source evil venture column truly risk clerk","master":"a0f072fd237c6f30dfa920940d04657e19ebe30e3fee5b0ad8e63cfbb6256d86","seed":"0ecdd247615ecba50ea404632b4f8e2a6babe067cf7d395b038935bcab013f0581c69f2d07ad330cb6c7660feafe8b21af062b474dba193f1121a65f83b71b99","priv":"4b54d2f02c43241d7a45efacbd48616f6293629fc0b539487865dbef626c6789","pub":"0336182aab2751a5399b14e0ac2a856143cc679405fa55141606ec3b2a09c3b1dc","addr":"48d6d2441e609507ca554f8f79e4340f257565b6"},{"mnemonic":"latin scrub oval capable drink common hundred ghost candy avocado stool dial","master":"3c8762364ca16a70f174584f1f276df1c432e0b315e08cffb0d5874760e8c587","seed":"40991c77f0fe52213ce2ccf4844ee6587b3595aee4e79f34cb00ccd0813f78f0955ab8e40a5f369522f7ae3ba0290db31fa1b224baa6ec5a91b57da8ad2b479c","priv":"5242eb4e71fc9715ce4ebf1ce08fd81d362fec9dad2be045ee0d6687e1662df3","pub":"02344bbc8ab1313883fee563a175cf98ba192e8570963fb7c99bd0dbf6368fb656","addr":"3db9be587f22ebc28ae33b4cfa2c86124f450440"},{"mnemonic":"envelope van become minimum electric inflict denial thrive congress visa jelly play","master":"e94c4ca894e31aa091dfb2ef9d7733fbc67f1dd45e5db389a037816e4ae9ebef","seed":"01a5a19c5f75ec7ebc2cf0d96b7665c4c79efa0cd0b7dd5e21c2cf8954f5dc5b1d23daae831a6e18e5157c200a603fb2ffc87a068d1dbfae1d4443eee76a1f53","priv":"7ed896005729b7de5c6c56a19d37f5352ad6329e948c256f11eeefbe8c0c7dd3","pub":"02025c5b38b96fa00b506cb0360cadcfade6aebc6eddddb71dd6efad382b0f6b3f","addr":"1b7ef9f1184a0da787b1231a0f44eaf4035c3ab7"},{"mnemonic":"grocery embody emotion wisdom picnic modify opera lounge impose junk scare ocean","master":"8091cf08fd5f50de4ef91fbd4b9eaaafe8f1c17624fec94cd47de656ce0444ab","seed":"ced20dfaf3a902a7b71ae459781e5013d215567a617a2300b49dac4d3473e624885ba0ca8df6f13c91dfaa9829aaf06c4ffa9ea22f6f17826a1629a597519507","priv":"f0ace0c797c7f3a93bf1f9ae64dae516fad77d18b11c0e32b5d0781d7a231f02","pub":"023c38bcace9489242f81a74168475ec29531c58523f476bd068195d18044f80ce","addr":"859850c7548250084438b5829b4255ebf5fdbe6f"},{"mnemonic":"oil inch eight notice okay gravity dynamic trend neglect bag earth predict","master":"b235b5a4e01f0e64d68b063f09a878c8b0785b84c5106431f4bf9250874e9d38","seed":"96096619deaf5792701545255d539f120ebc2ab8c23ee72de058874b6413e51774b7c2b61be1b1197784fb63fa7e509374449d4c812e7c8f8bccc711c73ba703","priv":"7d05f98b2cfedcb506c68d426b298b3450445a1ac89a3407f4ccef1ddff8def2","pub":"02274745f11a0de371600f1ab8b5ddfab91372f044ceda14c968b7e5bd953dad37","addr":"098fced832e9cc1c962630fdd2dbfe262728f018"},{"mnemonic":"oyster ceiling cupboard quit today neutral repair genius pretty gospel dress rent","master":"e669becb784c8ef38698f778cd27cf0b55ebebb5828531b65330d51ea2b1acc4","seed":"af8030276cfdf70d129e66467a09321eccd9505f662865a4776e1f5a05ba1ff6614b37b54583333e3ce931c9d44378f636efddf5189284f5fa566d8db01801b8","priv":"c0ddfbada817464834555e46ed3eb3d50c1023454f42826463e71754b9e6051d","pub":"039f5c467338b3cf8ac16e6677c8242a67caf89f1201f0f22d99ca1e7beb9f1a32","addr":"53ff0701507c25f97dd1e6721b218184dea2e3d7"},{"mnemonic":"utility angle dynamic fire canal current level trash chase praise witness mix","master":"54ef0de540f88777efd1f3c37929789620eff87bbf98e61f9b2e0783d75450cd","seed":"8701d5ac962b68ab8c34092b44210cb9c11c2332515815223537fcab99909b44a0394436074e60285c7b306917c1165a2f281bca911798b23832723abaf18971","priv":"bb5602644b1af5bfa019f2f81ed0d2475c1492661e55c8e65d8d5e94ddb33e52","pub":"0314f5e5d817f2235e3a6fdc0e86f231825165777c69314de63bd88738e7e7ab46","addr":"6d596a5fa6b1818895ee6fac51915a489da283a0"},{"mnemonic":"cabbage sauce filter identify potato coil bicycle river observe candy maid monster","master":"4e834379e58e480e0cde698f9f8e47b3b6e698b4c1325a995504980e43689706","seed":"a441b8fed73bf3bf06a27aaac9355a79d645f0c7d5d47ec216a8d42d6edf97e6a00dc48de9d9ad9d52279ef26f34990581caaba9d15342935ffe857c10456382","priv":"40e878ef025dc6424f2822e38c7a906b3bc39940e8db21262e6bb99ef3de98a2","pub":"030e41c103c49d2e54e5ba6e40b1dbf04245dca7da0738ce9048d0391da872365c","addr":"9d4e8dd66b5e16369be39000c11b03fd5054e0f8"},{"mnemonic":"method surge demand ginger pigeon chunk because wisdom stadium salad excite stool","master":"b8f4a0a87e42871e927b2d5775fd212dbf911351c525b92f5742ba15650aba63","seed":"3844f4bc75163d8dc39c53cdd0e9ff31182a87ad2d630286897b35b39a14afc5e5ecd3be988c9754ef31f14452290ff04c84faddfd195a3eaea076e48bde47c5","priv":"db0bbe779583c012d78f9b60d6648b72d699c2e6b5e9eb90d293852553649a91","pub":"02bb40395d5649363ec19874f2fdc122bddd8748234c1c1ccb37e38468c6e9da4b","addr":"bf52f59b2e4f01f23b32f502acddf96bda564682"},{"mnemonic":"stuff extra hair depth angry jar drastic jazz diet olympic choose legal","master":"5e09c2cd0aa6504c4a2e8bea31e0dcb7f0b82f040567b681271493e35ca910ec","seed":"ce48715916de04f9c4f9a84e4ca25900ca0292de3a7217a42497c0bab2253693ee8b5425c40ffb2700a65a772e98989a2adf4329a93596a4d6695f6c7f236e64","priv":"7f06d4f3cac1e4b2a7e0951a55f78ba85aa6e6b03872dbc0c930086b8e8e25c4","pub":"02b4ba9df766e58ae8a5164b4be48159901f421b8e8f396593b66dd3a715f268c6","addr":"fb2f7eb9e28187a7b68b02b7f55b5dd46fe9ff49"},{"mnemonic":"leader now arrow loan eternal prosper myself lift limit capital aim twist","master":"8a4e78bbca5c37b40feccb9bf053a24ffd6d0809fc2b89440d467bc903c03244","seed":"25f1e8641b6095446cb3d7f94bdd7d81d92d78ef808b18c48050985564543efcb99f28b94e2e935d31d973a848666b95bd183e05860bd0950cdf0ee8d7e04da7","priv":"a2fdc724702230d79b0c564c34fc4e68e8a10c336ca053278cb3be419313e07e","pub":"02e2206433e526fd4fff47b58ef262eb558e79870c0aad14290d40e912ecde8213","addr":"3389c22a794df27093c11dc80b6096dc3ed0d175"},{"mnemonic":"increase month viable teach spice pause safe mouse allow sound access grace","master":"919d9b6fd918d7f223acf91ea5abd831a1a3568d60fd2e43f0d97e000ec77f47","seed":"f4cec05a2bf6a00a7079213c03c36d765e49914166f497d6e38a522b1cb43fe24260008dbbad00a10d998f7963dc8dc09fd539570f157c9bcff8248987d38626","priv":"f145657458462f994a4e972cbd42ef4de683da47b5b6f95b14ea417b39e702ab","pub":"0289419eb27318299a51fce4f0e65827d0426d72543fa2f05d0c5f21bef86effbe","addr":"cbe298ebb714dd583e7c4d541ec9b38c56710226"},{"mnemonic":"move catch empty dilemma only online ginger rapid enough turtle flee retire","master":"39d365c85d0ae4f31811c665217b718bdb90a4f2d328587bdf430ff622d019e9","seed":"402b62437898f76f87f3e080c3f33f1c6b8ebbb848efd467ee4ae5d3303768c57a15fb1cb03a6befe486b0c02733c5c892ed9878ea7713cefc58b7a616d7b286","priv":"7e54e61877b8413d06251167b239c1a6213ed23e79c1ec8da7408e23928d47a7","pub":"03d25f230b5d12ba142046fa80c23e51198987254bf7f7f8a009b712783d9311aa","addr":"173f71a2ef94e964185c474eb310a363241c4621"},{"mnemonic":"audit energy setup mimic dilemma amateur evoke tornado machine artefact shed artwork","master":"40bd9cc381e632be6f25b822bb13bc7cb5c9697b09d7ec725aa21e13cd3eeff3","seed":"721de71ee0b84620bff8de317edf7c4ddadcc2dfbf19f3cbbbf61bf26157fa07c46119cd2f8387d67fb0cfbb98f62a3e711053a308496a0ccddb944ce517d90b","priv":"825587d79a33405a3c7cbb8a25e89cf1b3975de3763e1928e02c3f4d0cc8d44e","pub":"036ea297692c5bbd85ac06ca8ca238bad6db83d1acdd02fc012325a1369df4447d","addr":"5e45e1683f7c34754771340ecd629014297b72ba"},{"mnemonic":"vast noodle pumpkin sugar time iron screen begin among orphan glimpse deal","master":"cdd2cba6ca23c96a7967d3f3f5739009f2fca93bda0a36b85bf7a1cbe0d8af8b","seed":"6288319e4e2c7471be7088e9b50db78741c1da423892da1bfa289bbc62d4a014a6d9b7cce396cc3471531342a61d92345a3b043224dd271ba46cd716a0952af4","priv":"1a746edca60363f3bb4118e316ac549be3161be28c4151c9fb9cd63728abede8","pub":"03cfc321906acb176564624dbf1855f00188f563b14f07075b1d5c7e4dc25b4419","addr":"5007b4c128af77e8dfcdd85a925044438def1159"},{"mnemonic":"evidence element stereo crunch romance trigger ten ceiling cigar wire first frame","master":"9aa2f09eb1b6094ab52e39873444f04cc682e60305e9fd4f485af27d7c6e85b8","seed":"9adc22bf0cd328df0f54c6da7f5e43e9abb4e9a607aa02c312de24c12d9a18f38945da0188834e149aaa5798c8594fbaa9109d47363deb53e17553f2edfcdd2c","priv":"281e729635633787eb40b08d43d806a5e2ce178abe659b37c91c6c073e720448","pub":"039e0c68668af7289a7ab4c7f9b24347f10d38eca095e991207cd9ee55bf61f0b3","addr":"49b25bd31b9fed1ca7e2c32d663bd414d6c3705c"},{"mnemonic":"labor capable alpha robust suit trial media bottom pig hundred verb hotel","master":"b3e4d6c6bd059bc9548d33f6ce0aa6674160ce38bb231fe354950aab11651403","seed":"e1470e44481471f4c947976fdd4fc9119619571cbcc90d0d419f4a8c4e1102f84246da2c2fd0c02bccb34a23708cb6bfc25b23972c03fb6a70f5018ecc5dd2dd","priv":"9a9501487f7f9844ba521b3ef949b12b30046e927bbd8054c831434a4309131f","pub":"02b25d30e144102b7500d57f3c501093f4dc8708afa3ee2c9d772d5672802bb9fc","addr":"49bc8135a631475412f0b4bb0db7d437ef226243"},{"mnemonic":"resource pencil other subway knee small shield excite forget such annual opera","master":"955fe71377d76742d6bd94d49457e6cb768e57517ed010648edc058f65d6ccd5","seed":"28a7a3080633dd2485cd88b9c1ffe92889eda9d33be7fab5b8aae3448170282decf20587d613cf06f0d3a7da6acaeaf5c9918616b4d22f8f23bb6a17c67bbde8","priv":"ddc57bfd0d27c98a1d088272ab481407ba95f8556f5603245466f4f2d83c3168","pub":"03065ce8033103d6fb42bb382a59053797beb33214c9d16f2b4ec3634cddf857c3","addr":"b0ca9d5f91fa03b1350a40e4ffa84e99167e4115"},{"mnemonic":"dinner tone antique away vivid lesson frame floor rent field monkey race","master":"21cde220eeac2883dbddcc6927f73423af840e675eca3a6cc82bde4a5cfdfa39","seed":"16c220be97967c5fa8ff2176a9e0d748e0aad37c8ad32e590c5a35ba08247e2176369a3561c5eb0cc4ebc9a3d65bd132e31c2640968eea822ae76c6c34d17373","priv":"13366b2855dee63a394c4ba89378a35b75ee07853c78765dd1c5c8927e52d4a6","pub":"03cea336f71a793319bbb298bb3c546046e69b6abdec405302739345047cde8355","addr":"251a5f4b01da75091e938d782ab116e0e4ac37e0"},{"mnemonic":"peanut potato artist define merry brass nose brief dinosaur planet year blame","master":"87c46a1f19cc7d1e59887f445dab57aa835bf116db621e9df97c5f3090517e7a","seed":"f8b6aa2a59e9384933e0a88c76c5fa889ad82238ee7173a41a57638bbc82e51e7d89c97bf3cd2f6031e65edbeafdcad5760cc6d37a527eb0372b03281e7806ad","priv":"a7e43f8b98838fcc06ba6257cc64086fd1b6d0eef12eddf9910181bc6c0ff204","pub":"02db3f433577482b62d057404b61d9d10f25df66b0742c2a3471d2e80380355cda","addr":"571a2abcef5e4f690174e2d81d9ca035742e17af"},{"mnemonic":"orbit have attract dove horn liquid social maximum penalty slight mind mountain","master":"5da625838972cb1684ff4e45326b14bc1d73164f82527934fdf8b7a03b9891c2","seed":"abd2d4cdfc5b8330f58b7757efd4fece7854e461e22c71be5aadd735c144a954594fd8da84df6b8db3ea14c5db03a6952f093346ae94b6495a8635e72e4a38a1","priv":"cfb3afed34d7e53d459cad8623401f0d6071d77f70a96c75baa511179ca59cb3","pub":"02e9e07cdc8d57e321593919431bbb6c0761910d00e4a242ecd85d0b99e9ad3f36","addr":"78099b6cef2d14ad8f3ba7db73bdc9538e382464"},{"mnemonic":"squirrel motion glue best prevent fault goose evolve shoot decrease panic very","master":"2fc7364fc6537a38839ddc9dd41e0e58b2e972072e92ab8ec9fda67360f2a042","seed":"78718bcb53ba532316fc641cbe2027fdf4ea649563b36ae94a95415b5923397585b4d10b1026cfc8a00069cdc02c7ea8c1ebe04364bd68066195c748331104b4","priv":"7d9073ba21f72f91ca39d1f13c05108dc75b56d3b09bd08b7b8843137fba91b2","pub":"027827c957ea1c98f76a076bcb75ab8faf534dbed44beb234ebe9f60086fcee393","addr":"10440fcf67f5b2b6f4e81a0b6fe267941b437811"},{"mnemonic":"pudding tooth market kiss exhaust donor tattoo olympic uncle child bean nominee","master":"34f62b6ae3c01c03d64e0041bd50a9cf7027fbbc0b0fa7d13d08908422f72520","seed":"4f02768404f6da2b7654bef1e4d35a42386bcdbf167d09212194e20a93070030eb0a471945248a36a8d062e80130008cc16a001ecc3c05a27db0aab0f04c6411","priv":"1601556ec13ac16d4b38ee73080065756ef276473e7649c713ea1ce69367c087","pub":"03382cbb99d17b144dec0eaacaa33d1cd2041bd30cb658fb97ef2654e24addbaa4","addr":"e2bdf4c0101d49df4d8aa0782c4a1fc354fdbfaa"},{"mnemonic":"earn shock finish ritual segment post then note dizzy diesel jelly horn","master":"309b4a016a064d4bbbbc220c0fb0727114b0b83b600db73aeb4347a04ce52873","seed":"bee7d3de1274abc8fc05afc839de0b14166b86f1ea0a1f2a6b6484f40654aaa7cc4574a14996812974b905da6eed437576eb7f8fea704afdaca3b146b761f0b8","priv":"a269a409951e783c280a5d8afb0bc232f303618b4d83328ee1196cf86f2d8f04","pub":"03b79d6727f3d6a0c289f2efac4938caa94ee57a36a3ac70e3f8e5f85f7e4f52e3","addr":"8ed4fb10d7b8d66f4244e83d7e6cc89fc75460e3"},{"mnemonic":"venture bitter tongue learn whip palm race pioneer satoshi wait hub genre","master":"e01f7f5ad0a782b56a034b68230df72cc8440f6e4cad89ea0bb9b81a71b430bc","seed":"b6da5129dcad44188c654c9c50ea640543b66c0c98edb29099770eb6d89ff197f5e9fbb7725ada5b3b0191a9cea89ebd8f35698d5ffadcf3ec43f6b92795c1c3","priv":"e3ca3c8028c514ecacde54c73338ef5fc78e0ab05ed8260d4a70553c68390bfd","pub":"03913989f1771a015b6594b60de23017fb31b96a740507873cee53770684fdd5a6","addr":"db8e914a36120702031b4498a27d6bcb8c64da8b"},{"mnemonic":"opera wear actual virus pause topple leave video garden guard obey item","master":"8fa7f1c161b47e625e351c775c662eef0d5cf9d9c229a780ce0adee5fb045ccf","seed":"be4f43f613da6e02ae174310181afc71462ec108601eab58d369f452c4133d14bcbdd05462676d872b7aabae01e7e6e22ad38261ce70a2f107ff9f42ace4411e","priv":"506a98b80534c824f67233bd1840ea968886a57ab500fc0521da20fa4f24fce5","pub":"030a5a585b4db663ea11944e5be0bbb630b6b1f436989c8e7128784f7f59676370","addr":"5ad5c8981762b720bf74b376205f69a91c6f3cfb"},{"mnemonic":"captain tray course secret betray bag disagree boring umbrella liquid door memory","master":"b7974cd18de7e9e6abe2280e567fc51efaf3e80986c98901ae2ab7378eefa08c","seed":"3a3c2b0e7b237e37e7c92c12960ae5b8856a8a5795386d243c6d9eb7dae1b98170489c47b197a794e8f9ed0c323bbd722ca052f76d3cf1ac04db5f7ef6bf5b26","priv":"a13d741052c66e487ee376cd392096d9e56db28d64001cdd807427678b765016","pub":"02fac937135a8b0593c50d06a7b113c372d8c9d02a338673e3e07f267725536417","addr":"e5d9166b331f86253444f3198f707a495055b768"},{"mnemonic":"dizzy guard goddess trouble absorb pupil stove mirror nose couch diamond must","master":"d3bdf420266d0c5824a621cd631ba014a8ea614b85c628cf64bc3a77cd3be3da","seed":"485d06d18708ced0c344c4025d93cc194f7c63e2aaa1d19970a96db8dbd7e2f802d39d319338b0a92faffc2af408f69f1522481fbefdcbd3842ede957c663b0a","priv":"abebb4b15d2d9e3a3dac2afd4423d5da2b2260da49bc45d44d014e8d740ba064","pub":"02e39342b82a9b4bd73b165ea9b309e20b0cf9c8d5ee93756cf82ebad0b00e0cda","addr":"19f6fda807d1a0f99fb730923277d4f36601e2d5"},{"mnemonic":"rescue drink absorb brief unhappy rocket subject receive green echo marriage cactus","master":"a6ce8546f2cb2a62c573b3bb5b1e7437f70a44b7cddd7171a41d2c4c3dccd641","seed":"0605b45920c5894d2d351c091c7c31af1b6f0d77576f73716ac96dd7a22dddbf42155aa19bbc3c2cef3c757ff25c3e7998d0ca536b696a498c9a206bc53e8ee0","priv":"00a6e55ef1853ba31f2b7e76acc7e04649a1a2037a9bc33c74cf82261e956ceb","pub":"03de1a877576f6e77bc06a53e7b2c56afe7b58c460341b74c469e344d2b87f2e62","addr":"a4014c9bd6c662a6d4b20cbfc0524e125a5963a2"},{"mnemonic":"destroy naive mother audit tackle coral crater sponsor viable clump bomb bargain","master":"c0cc3cb63a702200dd06ba3355314b332385c3a0e1ba73bf428243278825a6e5","seed":"fdb9a430d0fce5ee93e6b0ec23506f65e76cae8be1f773605af71687d2f9fc14a9a1bbbb769a5c38f654398024159b48de392cc4a88e29030f4b7699a3ed6824","priv":"8b73cf6e42c216a7978f63a28abf839d0e2174cb10ac2abef6870c9a8b938462","pub":"033257c04174083656be1bee39ddf01b34aaceb538ee86c7df35a9ea4b3a3c282e","addr":"5ced7fca93a8e097cf58cffaf7c89141cc00697c"},{"mnemonic":"paddle image cash sadness barely sport employ slab keen riot solution switch","master":"be10364b52d5cdc0b8eb51215301e8468c82498f0d7b2de44013d382c0441e80","seed":"138194b9dbb5c35fc66755736c385e12ea8783c3208d85c58bc140a5edbbd709779d4b42a2c56b94d82b5edbb9de212f2eb315edeb20a5725f3c24a39ca50f51","priv":"06b0b15085f8af9cb90eb081a7b73d4f8b781467926c2dae68a0d300f2d62a71","pub":"0286afa72dc5ce3416e8996392d0cbd63a0f9b9d60701561d3596a1c9d5fa18499","addr":"bbda492cb736571a6bd62d8f5d8836b0e0c761c9"},{"mnemonic":"gossip choice orbit insane honey hobby split exchange uncle wash tower lyrics","master":"7b39b437bb8d0b66c3989df6debf35846dac9fb69d2f570c4738afe92a57d708","seed":"d0897a14b1958fa31a898e38fc95b6dbb2a9a5019175bf8e503149f9d1ee4958edce3f1f570c3e015b797b475f5eee882ce54f68c7f64e310571e0fc6296da62","priv":"816f5cd94acd51821291561d6aa30951d89221027418ca697aa2b621f733b2ac","pub":"03d4081dc8446919e4a949c323b4c8d6b76282325cc7f35c18791a57200577f082","addr":"fc5a9ef94fc8de5ba7407669ce04d8190864252f"},{"mnemonic":"ceiling shed aim oven emerge year sock achieve ask melt endless lecture","master":"ff1480b11529ec8240e79bd9e35275e1805a3e117a60f9b6b22f66715b4258e7","seed":"1aa288b6bac68936d8d2a89396f5be1659a12fc91a9d7edfbb45446de8bb39327044b6ed7451e820317882f162560fcbb134449e85d517a7f0eace2da2cec272","priv":"216833b820c607646ae504dfa7fe28b364741509047b89eeff48545fee07c11f","pub":"03b3c3ce98ff9d2340849c220a5127d8ebe2bfd320c9db41e94f57b4e067eccf0c","addr":"78e3043b376112452a22ce49f6647a0b1d20180d"},{"mnemonic":"deer defy door jungle sauce summer sea globe crane abstract minimum diet","master":"f7440871bbff95cea261708c1cd06220a5aadae4a86c00f53b6f510a50e8ad56","seed":"a1868d8a30b498e1d397838821bf762c5f448d3d8fb68bf12cb0e2e26cc69f95be698efb101e76ad6ab84447c0c2b2170fb2b201315f5e5023bed35490f43986","priv":"b64d5f61a5503b366e7296a5b060e42d5db420e4bb8c4d0248c07ac25d2a0b60","pub":"02f4e32b1b8f2ed1b75ea26def62a6e69c7cce521788bdc182663ccabe4c1da4e1","addr":"32a90701856a1d942f58f41f6cbad21a64494658"},{"mnemonic":"position course virtual distance fashion oval slice round rely key spawn shy","master":"255409af8fb802395b9433c062310fda250cf8f9df7d79bd16381a7ec7b4d27d","seed":"1dcf6512b003b07fc299098ad2b8d4ab3eb1be11cb8949636ff2dd0baa0081ba78a9fc117ac65666c0854387ce0adbb903b482b85a20b9e591f0ff156a59d30c","priv":"a9157f3dc6ce3889c4d8dd4d2434f0e080090e4a0c0c75cf58bc03b41ea507a8","pub":"021b68e6fc74dbc45d326f9d2c7efe9c718e7c3c1a084e92c1f384c273b2d41513","addr":"21101638d066b561f8c43f6e9061f3959e3f89ef"},{"mnemonic":"model absorb cart athlete helmet next hen indoor involve ladder engine tone","master":"4221074ff1f662276f167017a5d43611b1d6e666c0c5592a35c81d2f5389c93f","seed":"dc9672d8e648fb4da6a5de519d08fb677c0d583a988701f2ac57e1fff273c3c832d31c036fa36d33b029fe0e92e8bbae350c6b96eaec463588f1ee04209add53","priv":"c4662a26101f0dd36e56ab0528a3861547015022b9e8a30ffde845d6207ae8c8","pub":"0285c5ad35fd9063e8cea4d034628244e790261977eb0225d4da90c5a2d11ac25c","addr":"8fc4bfc728a5e5fe2423b8c380aed1f2fcf4d2c4"},{"mnemonic":"armor happy become inner fossil exhaust upon under offer sheriff coach huge","master":"154c74bbf5601f7fd35c183e77ba32c03eadb2fea62563d2221199cc694a5fe2","seed":"db7910b6fb6f406f146f857b5c116033356cda61099165a7b1f782b2201878f9a4104efa15c2bad266db1802f9d15719fdb9953eaf3e245f0aaf9f5b0ff8d296","priv":"ee1d3af46fafe868bc1a89394c068dfe05cfcf7578c10bd57750511276e829db","pub":"03db053e44816be4562be9df13d8ee1853c1336aff0d13cc516b0681521d96a9af","addr":"fa65a0099684906c758eecf10f7a2b6dda7c5767"},{"mnemonic":"long output ketchup question hurt drama bamboo globe manual chest luxury abuse","master":"b180100cbc124ed4a9812ab4ff3c632bd7df77209598d4b26af9d31fdb8bbc28","seed":"61b7b436746323085cda66fb4c0e21079e849bc4d2bcc67cbcfacc97008abeb7ee57c2ce751e5c63fdb676f0cfec68442277d4a0e5db1ecf82236bb2f2c9380c","priv":"1ed983d1024d453e2dfbed2278c3c8ea3abda96836db2462da4738f20ba1d772","pub":"02f9d9ceb9a27e4626d09331f645d40464c99975ab0b7344be3f6cece6cc0de8c9","addr":"d092b8b49065f0698b483e416f4b1b032b416dab"},{"mnemonic":"ecology over output enact system curious want oil denial ivory hamster approve","master":"f304cd809c371db0fc37fca212810e75134773494e5c1d20cd22753399ee6433","seed":"6693bbddb7e758825bc3c2096108aecca0414cd1b523460a14c8dd80c15b27f5f37cf4589e710a39fe663392874a6b17892fbf473da8d00d86af17aa19ab0cb4","priv":"8b13913b6f590abf399aafa87fec44961218fe45ece0f9ee8b22810839c46e5a","pub":"034738f122cf61a102148156d40aeb129bc4c54fc55c5b85462917f4013d7e3024","addr":"1657b328a5f1ddef43968178fd8034c685e9e312"},{"mnemonic":"uncover climb join country march border rack ridge track true master useful","master":"b1f2471d8e6e712e20343f06220f847caef645d9cd9972ed17684b3a44b25de9","seed":"431e56eae671e0f1ae12aeba623fd4ed4c7d3ed102588d3b39b3c0e20c104aa24a435b9ca504799214f95b7639e208dfae17fd866b2f58c0d916cd744b7e5424","priv":"1b0e22bfd60db8880827761411390dec4799efba98348052400deec1838b04d4","pub":"03c6d27aa4dae3b3e5754cb3bf8c4638576f113876cea4da0d915964cdff0cf7c8","addr":"0056ae65805ceceb8c17c3c1246c5f70dde2be6c"},{"mnemonic":"rally cool artwork leopard skate battle shine text ritual rookie sun way","master":"72c5b3c5022b033d71c7abea54feea3d3b37dbeadeea5db4c8847a7cd0e20d3e","seed":"d7fdcb354a8946fc3449107361e4bb3bfc569c0d3617b450484e5a7fcfd5c690cde3a511415e08be23672789d090a3c679a06be36a2a20204172e1d61433268b","priv":"dd57130e658e43c9adde730ca57aa6d43d31efc3697a752075a7cb491a7ff390","pub":"03b7cd7259877064b403af9a65ebce47f210141356a67efee77ce456d46d948db3","addr":"a8db1e5ce299462e4943d0eb05c146591fcc3297"},{"mnemonic":"room vapor anchor forum stage corn credit jelly level cat detail auction","master":"fd531ed5d65637f6031aa02ce031cdb366bc8a07b00fce1104675d1a653e7995","seed":"f42ae529e339d9b204165f2b5556c1637395d9598cf5a59717d048d7d5abf831e60abdd457f3432ed2ced4c13a5a73625f716f235d51bd7892cc16c294925cd4","priv":"c2342924a2792e7c4bb8523045faaac7a669fdd00b2621bd38077f58a32bb0f6","pub":"02df2b027f4597da0a2e8f46932929044dbefbcd5c5ee38c2147dc1ea061dbcf8c","addr":"642b32cbc358915bcb802eb30690951710f597bb"},{"mnemonic":"have offer number egg canvas uphold memory snow know orchard cause wife","master":"8ff4d3e7e6ff972e24682d1f1116c7b83bb94ca8cffed1db9ddb4adf89e2bcb1","seed":"14cc60691b49b9036c0bb64ed24da69478e01deb36184f58049d694ccaabc41d95b1e6734d9d06e7009c394d54d80fbd65cde6ea49165879dc306c0125b44681","priv":"c57093fcc3c593fec4002a9040d90485016346a9f4f7d896a105ac268face5ae","pub":"0252fef0dc82142ec121c4b01275b254d6a78b4600f417dd0f09639fd94a23c0af","addr":"af5cea50c72de4e54216fdcb9334a5f5a8a0393a"},{"mnemonic":"garden nature witness stable over move among pledge woman cotton worry behind","master":"48d57d0dc1abbb7142aad3371d68c41ebf078970c5fdd4bfd7294fb6f8d32b45","seed":"bdca43aa42eb2a34dccfa4fd48202cdc386454683850a12e7eb7eaf9998ebcf57a01a6fb1a6b9cd8aaf2910b160038fa6adb42daaa914c7628e27f912687e52a","priv":"63dfb6b77a4286875868db4877a3d0f3f0ae8c2766b9c5d9225f48071421d832","pub":"031e57ffbf90b85823505710bfe5be2200f1d880171e8480494b50a04462b98795","addr":"a7619c6704a7341472229bb7ace1709b88ddf175"},{"mnemonic":"pizza sting refuse olive final hungry kiss abuse nature junior opera tired","master":"397240e78b72dea36dd17ea2ef3a15f18f8fe64c9e31a30687d2fb013e1ac6ab","seed":"1dfb236c6bbfdaa74b02300a0da7b2d57a2fc2f736a5144186cc89b6f20a23d74ae59338fc04367a27e976e41f1d1bfd4232a3f386cbf74220c9d0c6fc5c7077","priv":"ae5a8c5bfb71adfb89055f61e82a6ef5258f6bae9056313c360ea454bc30c052","pub":"02756acc7cd398fda3d485f6aaa15e7e4e558be8725d9766119e570b2b64486372","addr":"c4c6e359acc30099a524b67223da51dfb6557de3"},{"mnemonic":"deer easily marine thrive author despair puzzle super agent life rebuild soup","master":"7efbef221b4d50acacbd20a10c1197727e9fbef29bf2418f51141fb8a5368618","seed":"2ad829ff702c19a138945f61d1449c32d6b16ebdfa34350dd434bca3899b6eec3f66a3dc8de7243539f7d6d07f85689a66b0e9f6481a4767a5630c2c693c3ec5","priv":"b6321fb4900455eb1986073f5f705d088e795d26ec53c09b6eedadf439fdcb6d","pub":"02e9c7d430122627396412df161a58813327f436bdaba34f3e855263044e1fcc77","addr":"47f0fa963518339112a65e54948c5df8c23daa72"},{"mnemonic":"gate calm appear symbol make can alone wonder cherry couch loan firm","master":"9a727a9574790f29c890079fc9e83b0bfeab84d9e79ae6b273ea8266f4a754e8","seed":"f37c4b52afedefc86a24bf4edadf6a2f151aa9d503fdb3da440d53134fb040f7ed60c29407e4b74a0714f5fde8d650b93d71da52568d0e9b2056412092125c76","priv":"41e13797f2f7c41a44db247f9da73e8d7893c2be4a689fe558145f2bbb88feec","pub":"0242c6981834d9c7a14b96c39c6f902ab0a076e4a7ed29fd7ea559aeba3727da4c","addr":"dad747d0295dfdf151b6267e701f8d889770b4ca"},{"mnemonic":"opinion spare hurt three insane sick place sphere ugly sad mobile icon","master":"e6b6704a86504c2552e7db9928c6333372fa5630983e5a9aff32b0ecf56c8fc8","seed":"bbf2fa3760c82ac61467265053828c9cac4bdfd8aa43ff860ce50a094bdc448468fc6d0e6c53368e42b95aabe4f0098f9af46018595badb4f8cbac787d5c00a5","priv":"496c6fc85e550d78a931b51e6807dbfe843599401dae033db98e308430939d34","pub":"037ed7cca0717526969db9101c62cfa151cf97544ae66408317fd798d705a30138","addr":"a1fc3fc66094cabe3f7edf5b630003a524bdcff7"},{"mnemonic":"include relax onion depend animal stock essence basket local result rocket panic","master":"5830b22230ba22060e22bc4ee3323c8b1e02e5f53caeaf90759f4e846720b3e2","seed":"8fc74e989ab5b4ae04472887a59bf89b501e1813e687cd27a06bbef858c9a63b35531864b177d27841abe4999a7b1901d95303a395f5614a176667abe8aefab4","priv":"99a7444212b0176324718171a318f74fa5721fa46ed18b3677934408b30218b2","pub":"0213e7320395ca9eae0bd4f550f7f5f65a801066c12d95c3f9b443556011b13944","addr":"a4087ec7d05b08362bab9c8fd9406ab3bd88354c"},{"mnemonic":"cushion hover joke lottery gym muscle drop scare purpose share food strike","master":"dcc4792ae42c425fe278db48211f6bf54551f9dc58268282a5a61cd620832d4b","seed":"0bb05d59704318da60a1697d09562a05e4133fbb8f5a4750f378f65a5f0d6b9c0fc668dfe08673d6b10bfc4557250759c9f70aff9df1a5418821756f4017dcd4","priv":"741dcf7d371948cb17723b1b58759d8a0520a341a29d581abd12274014e945cf","pub":"022dd390a8c2d4a826ba8e725f54f5ba65438c97519537701001bd7a68eaef91ff","addr":"931f12464c90ac2bb3b25fc00f13c56ba1c49679"},{"mnemonic":"point action veteran fragile outdoor vote timber cattle cube deer fade razor","master":"ed95f0d3557ecabcc04fa2160560dde68517d4fe7ebf88584d0993a1a861c6ed","seed":"886bd48b9c9e337480538f1119148ac4f0a8d00cc3ba17a34cd7076bfbe85ba2a1a8f410ca44f210d9cbf6751c10bf15b6f52a725979e613f4294813bdf173b8","priv":"c489a82eeab534dac53396b71dfcccdd6880bd441b89386baf9700589d92f169","pub":"03e2e7deb2c03412bb42d4b32cae6591e4e0db745681900436999ee51ef422cd35","addr":"f9f93bbebed5d2859f83fefb58bbfa5f93032837"},{"mnemonic":"ozone pulse whisper cry ordinary benefit enrich cry name bargain muffin case","master":"ddea83ac1fba7d6c79dd073d29c913a767315bbae6c3648617b7fee73a04595f","seed":"ee93e7ea1bfe194ffdf6b0f70c2d5b5759c223620c01647fabdd1e2a94575a61b211b301cd6d4e979761febf15336c9bd1301406e338c9f6c0b8b938863c1cb8","priv":"d344fa49eee22f5cabe1362f36a026bba1b0419c126da13c6cf335759a962d36","pub":"028bb9fefe8418dbf0fca6857526f286d9db3321d12c6a88ffe8e2bab7004b4a29","addr":"b9bbd7d328f0947669fd1c81cf8a842a721206c6"},{"mnemonic":"huge afraid venue bid visit decade hurry put swarm couch gadget book","master":"8755848478c71a1c3345cc855a10962382a6c27e6c639c4a4ed245bf32bbb2d8","seed":"b04392d13e629b759aec3c28ac4cd7eb0b7b846f1e241eb79f862d6c30e79f3a5cf5ed26abcad0dce95ed6d639e8088c169e49bc20df609b5555b0bc3f3e5e6f","priv":"f3ab0ed871c3feb01ee18fd374568aa378651815b6903a2b42eb43dd70edb9d3","pub":"022d2a9a829f992b3d16f9374b6a6946649630bf553c8eb11208a68acd03ec3c7e","addr":"c61f53c2b19de0ef11583048fd19404473065bdf"},{"mnemonic":"update ring situate blade term enough evoke balance absorb pupil wealth era","master":"fc22f89a860ffe871a7a45557fda9f38369f99103e02a2a97066517190d10e0e","seed":"d18f179ae9c4767501a8238182d3fef3f24fa3259d41a07b601179f67fdebb6b47a78ddbb056170c0bddd3e5f5a884a3d4046964c0f4ffbf7b37c3e6debeddbb","priv":"32a6d9270cc30fb5bb11411313af52a3359249c1b5b38b753a83ebf516a1d21c","pub":"03a579f47d1d57202e02e7f445d68d6915a3304b256cc37c5d474e699405deb613","addr":"8501c773ed9240be9fb0f83ac2af1bda6511b1ad"},{"mnemonic":"horn coconut protect box cargo switch ghost among energy easy deposit fly","master":"df4a2a6d35731478a3dfdc0e1595486bcc245f83214a974b31bc20e2c0e637c8","seed":"454ec603e16c8c5c522192885768d941316f0736929046aacda1a93ad1a658e70c21a7e924974583d63567acf26ac15725b1148a75522c6bb26b37d9f92fec22","priv":"447e4c3e530ee519973a63c6ddc63b9e5a474761eae12e8c1fdc6d0cea806604","pub":"0359c72dce4c6c9edd2774af06545c8996e4832ae35cde19fab2f7dde55316de1d","addr":"5a49f88b1672cd9102caa80ce55454030cdaafd7"},{"mnemonic":"price envelope myself under helmet dove uncle below extend gadget limit mammal","master":"abe0fdd5148a6b93ff8b281d084e4bc92277848c964e3698a48e5d50d6503d54","seed":"f8c27b37871dd5aea7f7bf5fef1c561beae9d029b3fd937a961ad39fd09100993efe7b84699f7abadd49b81d16382e0677563d28daeeb08eecbdaed50b27eed2","priv":"8ac79807c2a1bac4cedddb4768fe92b7a51e0cdab5cb79758f5876511a9b09e1","pub":"023277dccb7b0e017b461bf483c2d3a63273e83f3acc4688733776ee3ac0f649ef","addr":"0ad65e63beb8258df8ab0f17ce28afe3bf19a96d"},{"mnemonic":"toy grain guide crisp error then group clock coin civil space paddle","master":"7c02340aafc6a15a7c6accc312960631cb3a92c4a7c6d98c43897a1c4c55e59d","seed":"a08642010ea9779615e7a55b973f014ae8bd492630f9fc134159501e53a12d402842899978c75f553cc78c061b59210ecdb20648a1187ea55d85b7ef1b206c6a","priv":"83ab8e2ebe208b1f32ece9530ddf03e0727d3313903ef13b2d09a3952dded8fc","pub":"028582791e93e6e6b4270353aac091a58922c0067fa440a645dbb4673858e9bf81","addr":"4f37f8c3b16183c245ff4a101bc290c3ea9eafa2"},{"mnemonic":"atom border bubble lift day soft rich rely gather ensure that arrive","master":"e6936ec3f9876ca2c44973ee13fc02a08739655b71a9880b0c7959f9c5c12286","seed":"00fcb87f619a1033adf5c9311bced58ebd5fe56a70b69f65b61228732337ac46cefc48b1e53ed5a6b0ef658b002fc162ce686529120a486230f3845250ca7f70","priv":"4e527b2fbf28914ffc78f84031c462f3b33ad8d2b62357ac816bc4c06c0767d4","pub":"02b77c89d89bc757872025a0933d39ee65f5ae037031359cc1e692dcda3a290c90","addr":"8c8ed73961a3055cbaf4ca0b5ab0b0f56bfbc32f"},{"mnemonic":"require panda tackle valid tenant treat boss oppose where thunder zone rude","master":"fa9c61113d7c7ad38850ebccbdc2301c451ad272d86a7b6ac7b384c4560fbba8","seed":"936d1b0d443630cdbe8c98731761ce80f980728cdb122b95753ca3549670dda6663bd93d03a5cf601edbeb0b835ba3e152f940706aab856682b9de0a772e219b","priv":"9ca97c10d757f03eec5165df506d1809850b1d8f9369a89b0bb118d1ddff91cf","pub":"0368a22ead8cf1ca5b0bd3b6b4a680d47de8342b47d7205f4ed41e85299d2f9260","addr":"f03eaec270d04d368df8a3a5408b9c010f283b8e"},{"mnemonic":"thing gorilla large fog mutual hair gorilla soft venue ahead neck remain","master":"4b3929a08e30aed05400a3a7fcb91fafa085de08402ab546258c10346a21c14b","seed":"af471c7488c0046d2eb29429369a14b2b3bd6de6e89036285dcc9a121389323bdedfd7072ef9bccfc1ea472bf8a9d3f938bce5ff58b303f9c0b24dfe8185d917","priv":"13d5e5fc0f6c184e4dad19c4537603b811186a3a5aaaf272762ee236bc826367","pub":"02ecb5330e932bc89bfaaa8682e044f6a1c64823887aab000b2409b467fa94da4d","addr":"c6d1e41d9fc95706c276d85b5d93d657d59c045b"},{"mnemonic":"ketchup blade myth tackle neck gossip obtain write script grace mountain glass","master":"3d2d55b2b706361eab66a2724609c1ae6e7bde50f3ca78dfa72be5e784798ac4","seed":"ca3ff2b26ce97cdf280654a05e388ba2ce5ff909e3bf253b35c66c4b9f8d630a81c6367537039ad09d05ad7fca337c479db1b34544c26331c5fb860eef84f953","priv":"968bf9c285110ba33def9cfc3f47c82ff8050b854568cee2ac509191885c4c7f","pub":"02d8719b0bf9e5296ff70bd88c8eea612b5161e80be5315a9cbd4ba84eff6dc788","addr":"868855cc81bfbc80fccbe3f1fd2d526db7cfe298"},{"mnemonic":"violin toy phrase advance banana timber viable half nuclear friend bundle injury","master":"494774c8eec7a45b2e54e69d4ca64766ada0b90ab1d2f6913690b7b43f489b52","seed":"d11d7a22d020dd5e4ce9a9c162637f47223a4162d5b1920d7ac83d99d73c40ee6b67fad2c534f8100d2529afbdaedf7d2a8cae2e921e8c6e02e3bb8d7417205c","priv":"57827aa1804ff699ea31602eca3ecdef41b722bc2d321187b48c5780962c0f73","pub":"037fd67f44683a2613f7b049a87f47cdc7710d0a834658091675497600d07b485b","addr":"6b13a26e1a545c77cedafc8592e55363742b55fa"},{"mnemonic":"forest unfold spy harsh pitch alter bottom album renew siren find bomb","master":"f19401a9aea13a1daaec39107b9b860d4159b8c66118bf13bca736937eed4e61","seed":"606f8fd5651b2b7cd9e5d9974ca44c8dbee170e6c60ca3d7a4764bd2a1a31ba79b60d0c32b40f2998a3fbe784edc40f93a917f726d2d0a3a07a3871358bc4f7e","priv":"40bee09d892253ebaaa28579840239123740d952da7bb782e66410998405c2f4","pub":"0310455b5a6e7c5d4d09a3ea71e2dc7aac95e8457e6db3bcd605010e6e8f96fa7b","addr":"5d40749e1f1e8aaf38b91c12907f561668f3c691"},{"mnemonic":"goddess isolate speak arrange tumble ivory give message palm wrist slide drill","master":"424c0dd576d73827d765d558616a5c5abc92ff548c82cd6e5a277a5a316e0245","seed":"36d58066ea3378f1851c1e762f36697248c2799dd98b19d74e69aee16e497e4014244f62f696f34dbca202f78f7b6e21585f91531bfb8c3576f910eaaa64b524","priv":"f0c0691851dc50e5ec0897cb29a8e05032b7d02afd774aad6904ff44088f2850","pub":"031bd47b8bd9a56d24874a1df5c15834ccd5bf553e7858e2cc1df2c045966d5ea6","addr":"eb4f13a437254adfcf46d5cf7fafd4b2a059a99b"},{"mnemonic":"penalty trigger panel ring menu toy behind forget tunnel various giant melody","master":"770d401afbd35db8afb7a1864b794ea5a59f2c65127457d4675128b039638e73","seed":"81256b9fb40b02feaf3228eb300d1b002f9a8c0ef03a2b0db187b265b09baa4fa28ae7992c1ffa893381e572331a5016e6fddcf3871d1d836e92ba94a44d92ab","priv":"380085bbd1a2e2f50eedff2c758fb63f981adfe46a25db54ce7f1d7a68b6b7a5","pub":"0367f233e57390fb166e45ad792a054ba908fdbebf11c20a3c199ddb134244b7d9","addr":"ca1e2a50753d833d16c10ac03551839734b5e3c7"},{"mnemonic":"usage real inform betray ridge call coin warm meadow gossip river predict","master":"8aa38fef2d5a72f6e97cc57244f0baf53b976ab7263373dceef0b46ea52651e7","seed":"9b806b194b9afe0f5f46b4b40c4658198445b53462b6aafb2b1e82e1c98fd29731d193681ee43f3d9d70547a5f512344809e02d15ae441916725da5e63cb3791","priv":"10835079af496655bc2dd80c40c0b10f18788fbb9350a7c3f2abfa3e00ccbb2d","pub":"02a3077b5796d8cab9a90186be1c1456d75b3076760f2720225bf4f38eae7c0e1b","addr":"f7deda6ddbba1cb091c8091d2e43c01408fe0d8a"},{"mnemonic":"mechanic share spawn limit panda quiz glance dinosaur gold skill initial replace","master":"0a84289f0c2aad1de0e750a0312a2a362f99b8f0c7a15b1e11dadab1df18593d","seed":"c45a8faf2b5af3ddf883837378d03bf6566c6369005df0c7995ecc9718e2e1482fd42d3411b58bb4a94a637c41f310a8faa0209117031ffe993c0f04b2878935","priv":"10bb410b31a37b51b19165dba5171d33e826e06f83b8c590a23b9b2c8bf11b45","pub":"0331188abce7c6fc99ddee0d7335e872b7cb2f48a7ba7dcbd9ef093c30fa16a5a6","addr":"d3bd3dd9d928d4bdeaeefedd058ccf7047fe82ef"},{"mnemonic":"velvet renew spread mercy volcano always snap column loyal possible ordinary sock","master":"a2fa675336bc532f8e1c253861eccca1909a195238dd202e45f2f38ff421e721","seed":"89c8378d8a7c2a2ef02bbcbd2da9e39f6ef138db1d02e32cfb492c09a132e726c69268f9743e464a8421fcc0d5a0bbdbd00dad61798736c673df81515330ac17","priv":"ed486dbbabe3def74d052685a75e65d25970d8d134724968941a6b8e94fa2352","pub":"03a06dfdfe1fcdbc8e9ae8d6c55ac974ef4075c8aa0a5783bc87f9d9c2d66fd5b2","addr":"00c4fc7760ae8f7986f35efc66d18401bd352978"},{"mnemonic":"secret weekend fatigue anxiety second ramp tribe employ quality yellow game choice","master":"0f326ef21360ac2929e4f8becc2e8320cb49970ed229f987f15b9f58ad383d96","seed":"a29c1dcb8899cd716ced74d2d81cbfbf81eb8b7ca7ae0214ba270be71e8f4a77d235a607079897f6ba6c5aef44da1005f3ba8195775a562e7d243b2428ea288d","priv":"db24d2fa242ff540009bc15ace40783c1535812bd0c79cb145187e4d648627b3","pub":"02ebf506214798f631572bf5f45321adf084d457de1425c929059bbbc328948c5f","addr":"27b810c5c8307a20b949b3945b82c0ef594bf192"},{"mnemonic":"crouch gentle hip then measure brand enroll camp vibrant lunar still action","master":"f10577e0eeb7b2385b797acad2bb4e4028bf1ae52cd59f0f53ccb6eda0727166","seed":"955eeb623726361c94806c10334bf9b1df08737c2b09fc3bca332d9f8008c5f357dc69e07251fa2cb1330c1099352e76ab445f824361533a8e30175cace06812","priv":"2e0602e9dafe830a4fe783c1b53f9c9b2f7dc0b69a52fe701f0bc6f88beac1ea","pub":"02ca1fad1e6ee189fb124863445fed2a9a923d7ec23348771d3789978d30a275c0","addr":"51cdfbd7d00e618d63a64bc662cacbc183fb2b9a"},{"mnemonic":"cluster slice enlist shift world satoshi mesh disease season ready can strong","master":"74d52d1a33a53a722c7319883ee0f47f2f76f39ff17e26b77ade53d45df83a5e","seed":"cf8c965548281a449796c37a12dfacdbf395e474b5336073985e5d7e794d80ad0ff5059a3df31381d9eade948dbbb898f4fb7ff697d2f398655573170b416329","priv":"5b8824e9f9a0cb0c0fc19f4d06921b32a76e1baf98c249dcf01c77bff2ae59af","pub":"0309e87c2c54481db5cb4f7802d2488872f07fe08dfc3a984b932246155dafb6c8","addr":"dd84fe8fef92aedb045bbf091b93c7abf4f34352"},{"mnemonic":"series element media flight next blur fox impact joke review token emerge","master":"1841af9c8f47747ac1819c178e62673e51e2957292ee608557fa38e2ece61d6c","seed":"02de6354734c96841c8fdff0806fc5a0237d621ac98acb7eabdcfc94e458bd2e7d71a9de2f5107e188e153946798775450aac5c62cc293adda42a03e0f50edb8","priv":"a118a4e3a22a82e48a4847a644c452794946169a39d8919c02f131dc177b4c8c","pub":"037b3f5d214185886313379351ac7e6ed054a7db85b9f5aab74e2bb78abb519a2f","addr":"f70fa3d5dc91e442851e6cbcc827fee336bf267d"},{"mnemonic":"engine surge protect goose warm bottom frozen menu royal fox escape sword","master":"9ed672fb3cc919f26c925be30c6dce07dc101af5baad5b6dc2264f5580819b3e","seed":"21bec398901ec8b5b4bcbae5aa2e261f96190a3e9350c03a0e23da3755a4d36ba0532ac17fb7a41266905e76f2d72e90b577e86bd6b8f7ab62a4b835292a94be","priv":"0c386e0854877e7a34bd8a9c9794f107ac2114e05130861f77353406fe9db555","pub":"03a3740fa2bf35d6248bbb7be20d6c264dc526f382f72696a6c1c28ecd2bf25944","addr":"d59ee54eca22ff7873b68b429be08245b836141d"},{"mnemonic":"dignity almost rebuild habit visit come carry deposit stone page soda room","master":"f4eedac55ceae98a3bb706c442d3ceea7caadde17ea5a2d0c81cefae9af754a0","seed":"5ec26bdfbc0d587473ceea390a99616a9c8c4a03527627983cfc9cca8f7779d1ef7c08abfa0969eab1da7c8128cfe536b6d2d5a07c99cd1afac0052e8a753d7f","priv":"4ecd8b9d596eda21b65ed39c8f53dc6ef2e19726d6eaec60da340095aaa3be91","pub":"0392dd87d441269c56e78939eaef320b6a9c0f0ddf5758e57663f9f268dffccb8b","addr":"eb71c884b8e3c1b215445ca2ab5d5b51a6bc0be5"},{"mnemonic":"input sound bacon tower fun evolve song pear various laugh code sausage","master":"b0cbb2481cc2a131867c6514b194146b937a6e46e497d6b4c329d6146433b13c","seed":"1276370b1081d2b48f45f8df73af1eddececf2076f8425fb0b593557392f3853e5298ab5a55f0e367a578932f8daf640d40d8465ffd33ab4bb6c41fc9a4ec9f4","priv":"c358f0d976f10618d3d0a600c0ae754fb2d0a2a97a385091436178ef4bfa332f","pub":"02b2e45327f09ab88143f72f6bcf5f4fdcab9101d55e015022a5f7b63bc13b1a6c","addr":"ea33c880b7f4cbb849c551f61ba630c4d9b97155"},{"mnemonic":"tool lens message country slim wide fresh front merit science argue cupboard","master":"17e462a6a8c9e854a6a7443f0f903749ab8967d8fb3a42af27ba3c2819d0c750","seed":"506cf27425374254890839b40a5a05218cb5e8d7c143523058f74d2f955c5cfdde30cf034589fb7846b9ba3194bfa9fc1eedbdf2b706b75c9b51719cf7bbc663","priv":"995d94dac98165acbec37aa586c52d9c7f0a65394027e3350338eeb69a801155","pub":"022f8ae9595f1f48654fb99985148c5c041dd4a1da396ed59cfdee3f09d7166e93","addr":"23f909e775cadd631b1b3c75df7027382b702167"},{"mnemonic":"beauty fury random thrive grab merit powder wreck affair bitter style girl","master":"2b5ebd0f07795968a7fe8ba12da106195f1fe540d417190ddaf4b11527e5f2be","seed":"c2df6f955aa168424697c97325016298ad6361c3a197ea9b446e790d0b2e877f03692a86dbba512e4afaaaa975484969c14cf0034cbc3f5571374ade85e6e714","priv":"ba6c8ef770c6258ddf7a395670a13cbf661deccc4edf5601e70bf44d1d40d63b","pub":"032f8907f58fa7592e6a8ac556f605a981b7cc80c94431e78bdd20ba086b22c2d0","addr":"9fc0563bf0185e0e99f266af339220588c655280"},{"mnemonic":"code aerobic tent hero install segment truck foot employ manual dice time","master":"bb99c30775706beb704fb7a7416c778c295b82d93c8919d521ee915468143401","seed":"bbf14d684a22d95920436c3133dcd0748dc6e3a133fc61cd78e9f1bc9aff37c473f0ced555265f961d4b7e70b6151c9c7aedfe6930e6a352d2da531275833a4e","priv":"6b766aad48cd0ac49d4ea1cb1bd9961d0c0d2f38f241c1b1ac2f1a8b1f7f86f7","pub":"038450b54d2d0dff23c557b3c66613605dff4df0afd3a5b22dc1c93711c9718d01","addr":"e50e364ca287feaaafc0a6b1cb1bc8f3f1410a02"},{"mnemonic":"media custom wolf spider bitter require blouse soldier barely pause upon inspire","master":"83ebfa6de22ec8362e519d5430a1479c2185bd44749be80f3f5381cc7051d125","seed":"ec99f944a7043eb3da146ecf22086de374cb1b55c64f436f9489b7f4f1e0ac6adb0f937080bb20405a4b225bad173729abf5517e92c3bb75aeebb516893d54b7","priv":"0771719a4060245c49152ce121c01ca8fefd04eb559a610a5a084a772741141d","pub":"03b17977e89ee44c699e018352461bb244a783c4e2187ed49fdea72a479969e745","addr":"493f3d15f460402da46eea1dbe4b767273eb15a8"},{"mnemonic":"build key hope learn place romance parrot ask spy whale input chimney","master":"d3734ac55147344c1aa411a2a161f42710308a5463ed2183b9cb561a8f1a92bf","seed":"5065c3b0a1b3273acb090c991269ff667513cf41e34a11cb802b8880591fb5f9e89ef614306261b0ae2148e5747649b6d5a375ada3749e75e084c3b28faaae4f","priv":"ed51941c62cb63e1e232dc903894fd4c8797d69f501f41f85e1763745ea7247a","pub":"038ddc7d19d6bee458f791b34d2acdbadbec78a228066a4bd5434ae538597689c3","addr":"ee83ae098ae348e6c5464eff4d177c04e97862c2"},{"mnemonic":"habit pill guard artist void crystal various owner shadow inspire plunge price","master":"c0a23d72eacc59b5a382bbe6b59d4541f5c65abf8840a16255a1610ac56df1f2","seed":"d7d1bc83db47fd6215a4e193f654c8246957f7f62b6f8b4766ce867ee58d69b01e749abebb2de94f607e2c442554047a65570c4ef1e764c56295a8326fefc232","priv":"f2cdd0461e210bbc69f810f796189167a71aef2fdd769487c772135924d35060","pub":"03a0ff432ff63da4b30ad757931bf41927c0311f632715aaffc41f1a39dad92208","addr":"a9fadf07acb53dc1003c0de03f40f73767cf84bc"},{"mnemonic":"miracle chest bind idle bachelor science catch scatter current argue fiction ethics","master":"fb1730aadf636789c12f30bebf66b5c9b7ec1138e126b9280491f61013e094b3","seed":"2139c6cd3f1788ca6f91147c60d14498295daebfcb65f0732d3c2d327a1ec8e01cfa011e840503f5c49c89e9092ac88e5d688d0fa945b604a851fe4f4b48e404","priv":"a4d77dc6678d78fab38419b72857914e5848c4daa7bc8e47e960a74708fc30c1","pub":"03b946212019343e657dd0821422044234507602641f389ce1698256054e6b194e","addr":"c67df9937478387372ada7cde57712ed05e6cfde"},{"mnemonic":"garden box bus under chat pen connect access police mom crunch elder","master":"c49d46b19d0078803cadb2a63572295a9cea729fb31112b48cdddc9311ce874a","seed":"fab44285c884dcb44b1adc9823cc021c0560a92bb9ebe23ddc25a08c68935e64733aa1f7b7a4ed30494d8f74cd8373a77e114884f74e6804696cf94a6b0012f1","priv":"79ea8bec554ff6ad0f20806224d7f0402a07fcac87db0b4f5a6cf84221cec17e","pub":"02492778ff035fab9ee383b424a90d694121df7cab7ca984aa8a665693c44cf726","addr":"2a899dd4387375c42068e42fb90793e5f689d413"},{"mnemonic":"morning street camp meadow moral chalk pluck winner light same grape drill","master":"e5a773479add64869e28f1d1a01fd6200de25fd53debfb000504a6231d2ab263","seed":"5e24f51f1676b996b470c01db9db032958f58e1d22bd7efb2bffc55baf73700d948c5f82eae0f6b82f0b9158141b173187ffbf4fc792e43af194c992884d41cb","priv":"4794fe7f9410adf7f567728f98daed1eeda0248d7d0607e57c4ec184bafd8504","pub":"026145b6582ac105e06921c3856db99ac7ff518621d984214cf34f5c155f0c8736","addr":"f263e7676644a577d7b535df98f7eb6d3f45fcbe"},{"mnemonic":"annual very slight slush tomorrow stage mother girl forget castle emotion move","master":"53725daf3dc76a16b54a2086106ea4eec394802f70741e2895a06655ffb4ad34","seed":"fc6f22026780d6255cc7a21746c7ff48fc773a350784471350837ca92d9131e9bccaf78ddc60a5bd8dfa9838755dca0c22e6efaaa757a5bc4b2ad341e4cf5d15","priv":"5296ceed1517058d022c8fa5c8e076851745b98465e0fbbc834a0aa872222bbb","pub":"028250ee9798cccbba647bf41f7b338ab4d15f7e5dedfea1857213e125fc8795f3","addr":"82e76dc9270c795c2316a618abe828dc2f09c1c8"},{"mnemonic":"novel swap prevent funny lyrics erode wool pilot kite junior alley inner","master":"dd900d54ceda698e6ade447839e3eb3f64cdaf8f006d41ee8e1a2f3b66b55754","seed":"8b6b71539ed5ce60bf33745f1172fe3de811affd5a494050c4672f2acda9b4af9aa57fece9b8981c94b1b9701eb27da0f67b8dd216418ddacfc5b84f0c835c03","priv":"4fa69bc81f76265d4df75bc208294244c5191ba7c8d6350bbbf4445e90b9b4ec","pub":"0281946e059cd4dbf81328a3b01ea285e106a390ec6a1b938327a26b85b3e2432f","addr":"12e1ca832d7826ea5c85db514ca80723f83a59ab"},{"mnemonic":"film erode thank mobile file ball inner wasp unhappy borrow polar mass","master":"61b10af9d2c25aac6bf1b1d4fb2e0899c86e40b5b3aab8a29986d241aaf6d414","seed":"f1be2b5ead5055a4446bf8d608c754f4b112f25780aefc7859e9697954910d827969b8ab2d78582ee6f91985c7f740e3d5d5ad08a7f3db9e265aa977d4ccac58","priv":"816f805d3076c855f114b1f8fbe1a1476fc02a71b7b800d6c5fb9d3b1094adf1","pub":"03f08001ebfdcac89f9d4d4cd52f8529b957a6e1ab500d541edfa086ffaf219054","addr":"ed2fc0f401d326f2ea61375272ab741d648b690e"},{"mnemonic":"aim owner direct pizza enhance range need raven divert marriage gap hair","master":"6ebc5c412f961584572008b5d531c275d45e403f3e3672c12457fcdedab52be6","seed":"b07c83efb4979dc2978756f0457d7a4574f5ca3c06c133f2b9cae206f12282c29b8fee9430b22a347aabca5fa91ba9a742901aa4ffbf2a1fd5a30b7a258e0566","priv":"16e205a55aa370cc54cd05ea3805858561f4213c315a4cc91450097d3bf75d45","pub":"0309613fee96c3c5bd9af994d9805aef90ec3b4da315a2e7731f6aa1c25c28fdc9","addr":"ae3778cc1c0df866034a0ba6fd3e4d9308ed4429"},{"mnemonic":"base effort water actor slush space three tuna walk people proof siege","master":"96ed3fbe9c3d5647a24b899dbb2c67d69a629fde37f4973c6032555a48de4706","seed":"1dfbfe4c352e01a0d72fcbb4cc82645a81e02946ffdebeb465d424f92719dcde887566f784be14784742eafec3925160e87c4861663ac1ff722b554e2b1cbd37","priv":"7abe37156bddcd043fba717f9be6ebe3f9894f6b814390d0556053be00566e84","pub":"035621b9ff867ef93278aa007087ebb30bf8a045ea4bde45d14969bef6054e806f","addr":"b8ac9814855c57ddf5d9dd367af8d74bd7740f67"},{"mnemonic":"violin naive wrap margin glare sustain suffer nasty whip loan tuition car","master":"df6afd71e01d947df8fac4730e6569a23002ddeb2ab53ddc23c35349cfd55fb6","seed":"ad8e656352e03c098c0ddd1a5d9556b92f013ef9853264189968677656f0b12d6afff540bb8b548671ec2ed60a5bd61204c463a80c10e5d44380db05fc9cc4d7","priv":"607de82b3e17947b94b43b0dfef04eebe28acd497e6d5b7773feb983c0067b6f","pub":"02dd39ee3d3456e77be05aead5a1d0b71b03237929a8f085760d2e1496c3914286","addr":"2063185bcca6c0602cefec61b752ca5cd47982af"},{"mnemonic":"rug pulse coconut equal coconut soon helmet trim peace fall please robust","master":"a47a965d564ace3708293df5216eeb7b963ef1c814805acf55f76a9f44372ef5","seed":"e099210b6d5259379dfab4cbddaa188fd5d61cc9bf9354f6546db1eec25eba33a34ff535fa3adf285e7460aac8d724dd5208d08207064ff6d2f794f34c514747","priv":"c8cc7b2a9f01d89708fbebd824fcaf1251fdbe0dd4953f43a9079947cddaa2e1","pub":"030361dd18f40d337500a32de0adcc92a2044481876e17562863dc32412c8b9fae","addr":"90165eae1989ce6ab3edbb2d8d35cf843138eed3"},{"mnemonic":"expire company bean basket weather apology lottery energy column used goose advance","master":"66e2f9149b1c2ac8f5f9b139a52567d1284f8484d9cf338b016c4d361dbeac5d","seed":"a4218fc8ca69a1661bd0cd9d9a458c996c48502cfbfd72b0b018f7432ef41c8431f70cde82e7bed983e49ae7c01bae7de6d7bcc590677e166456e5a6e4ccc137","priv":"d7377837e6f73b9093b13741c27c8b25a0a323aa7046483b3f13e9ebf4d436f0","pub":"0368018fbe6931afeda06980639c2f5b532245eade554f5c2ec73f3a532d056718","addr":"a41364a6daca7cc6536aceb4a32e657f3ad22a84"},{"mnemonic":"track essay chase camp denial ski worth retire expire amused paddle ivory","master":"d764799a1d97bd937a1b9dbf4a0f7cc91bcd06c6d7c1a1dd3d25e2dc8d63b0a9","seed":"e3e62475c7d13f79f2005f61abd2f674bbb1613587b3e694c70f24f6403f0299140b68567608420af5a7d540a3707eb1817fef98aacc3e861c17172e3a6eaf53","priv":"b2369fb324c5ef9e7e7313a87470984de6ada9dbef59def90c594c374cecce93","pub":"036ecd0c3e3312f15b3ad399ca5281546366e33368c00d7066bcc371919df9aa40","addr":"42a6d89451dbd00904633f43389133bf199a090d"},{"mnemonic":"mean hello inhale jungle brown cause curtain arch orphan spy aware deer","master":"a66b0528350e9aab8e3f7985a658d50bc31d3cc88d145817f77f889de8afcd3f","seed":"3e240baee99e3e3c0030af994981ee7c10311faabbdd685cb41b971b647aabda05df165b31954506c1dcbda0d15bc9dfb3837d8561e8b346439d059431552c00","priv":"f516389c1d667c77455bf3ea25789d8fe6cbc52c62fdb54849f857fcd35d7f88","pub":"03fc762324c6a0ad341118a95cae96d737eb0194e05272b92160ad3412482d6fb4","addr":"0ee6e446b5713f87b9a8384c3fe356e45a4d6e49"},{"mnemonic":"clog just stomach title gauge park couch coast fault demise march smoke","master":"f964ec3cea5791c86c3740626bd8316bf3373dc874af01e2ee844c0eab7b9ccd","seed":"8175672d9e9e2c8e9182f0d6520eb1b0ce82a17a56d51019acd5edb9eba0c9abe7ba77a895717eae9bd565ff0312c65209c250ea48965be46292a4cf7c1ec7bc","priv":"445d84baed03c168e29c5167e6257198fb2f7fd6893b4323e692bf3514364719","pub":"03b43255f28016c8961fd0cf5dc49e427105f290b7025b6138ec444491e80e9be3","addr":"633349488a087a2789bd2a99feb62554bb35a4d2"},{"mnemonic":"silent burden donkey napkin churn equip artwork lyrics wage enemy fade sunny","master":"754eecf77fe825d148dd76b15601f36ea3c1a23b1535ebbff1be9695fe293bb3","seed":"c61d6da1ddb2a00797ec94d1bfe43df5d012c75bbb916e0ce42672f043a979e8cbbc4187867ae36edeec02c5526eb540f1ea4b9778c2a0b534d0b0e9d8a42286","priv":"530591f5c65acab37d4a98df46cd6c8ac259dd019dfb9c97fc34b1c9269cb42a","pub":"030e423006cf8ee7ac079b31591ffcd73f6d63b8e26e765a4b9f3dbe1022b2af22","addr":"e4da6fc6965990f17c8c827af0b0c2a2d9d87867"},{"mnemonic":"quick toast trim image exit clinic then leopard slice recipe acoustic meat","master":"068b8703650bc546dfe41908b04a7cc430add80d2c247784d41b4241a321b339","seed":"73126b2fcde7ca4509ee115803d5bcb22162748ba465c71767e32d5b271ac53c63168d2a16032947c1dc87d5e78e5117c0171abb1bcb4912de0331d7a7d7b171","priv":"a9251969a43a62c2b25f10aa0ee4d621cc1d5aac612b6027fab2a505a5dfa0d1","pub":"035a135e39da761bac2346f7b896ee0d2cbceac71d9679a201bf2b75e00ed047f3","addr":"f7f4f03d57d3726337478e5216c680c4543ca9fb"},{"mnemonic":"innocent struggle abuse math try bright craft lucky excuse fly nation include","master":"631066b05d71d61539a24b7cb2aa659f1a8d0e3dc76c5ea28d4702b18546bd71","seed":"6ab66876fdb7658a98dcd39fbaadac319ca73e280cc471ae3954e6899997f35576a4b7a506ce3c2b447ccca6203092a2c47f1018ba6d75ff58c416a3ae693f57","priv":"4c6c4c01ea2511f4ec731546f35cb469d424fe6af5dbd8ef3f4d27b7013e014a","pub":"021d951f161be476c1795f1987deea93eed12181b8b1a251107d83efe2d96c3a01","addr":"eb09dac4658f82aa173e5388281877403b124b85"},{"mnemonic":"weather fine valley envelope convince cheese primary scheme invest rely science pitch","master":"ea23ee8d99adbc168bbc367b10cec018bcc7f15717b19fbd05de7ab502701ff7","seed":"0c485f94abbe0e9ee91dd661eb2c6670588c712d7790e9d6357eb7dcc1f2bced5d0c8db8dd0b7aea72a6a057ac97a12980d753ebba11c2fb627163e729a74a8c","priv":"272a773d44247e0d0579731593d568c31017567d6dc29ee9cb2324598d1d7a6e","pub":"0305d1ee431078056588a2d2e503c40d1ec6070e3b06a78b2deb04c6de9f4b00c2","addr":"bbb37db4d3d3f8cc16178fa777ac23200c05d78e"},{"mnemonic":"portion visual market hurry enroll stuff upper pistol tired question barely surround","master":"997415f4d0711a371b522baa2a003fb6485f4979e170492c3104a18e7fb90cde","seed":"51a7489d52481c5fd36a703c9e832550f10bdf24b06f9ff023bec374c5089de64e6d06d61ecd509fb44972a92094b4cbe1dc13fc1ce1fa6ba04b03ce803305ec","priv":"8c8acc19030ae9e9ede5111a41637a7f69e624be9f098660247cf0154579018f","pub":"02ae3bf3047431b9d799b99d56bead936c5459039b965a612673a70ab9209e87df","addr":"a2d63ec58cafd042ffac57128bf9ed704d9735b5"},{"mnemonic":"intact elder sign valid party enjoy trophy mix hood bachelor near sadness","master":"fd40da840f8bc5eb4fe8e83611c5ffc897dc315583daf95a9e255bb8441e8605","seed":"e9f3376502c9e4506568876341ab89527694bd9f0184650c3f30fed6fe8b8b8705860e0c63276f0d92db398bfc2cdb4b816d58dc48a5b8ce9325139c1b96d682","priv":"bcc54e226725e41f96f81587653d60b736a8da21af6b24d9306bd6b94d1959e5","pub":"023828cc58f153451683a39c3cef165e8f3a5499eefe018f945b63062fe05dc82e","addr":"cbb390ec8ede1eaee76a40100c1b551872eed89a"},{"mnemonic":"unknown order purpose spice master small inch isolate loop frown page nurse","master":"b8b282b74a246171e39a795778958bfed4fce9aa6040c3e9013b1afc712ccb40","seed":"403e11937a99ae4a4aa3ba4e0f682c158dab10cc5cdd3b79be276e5283b0f91fb7478b6b33e30841b356cedd2091417a1fa09925e40c1ed23a9cf54484883129","priv":"c22ff234c4bb00b72005e1e88909dbbfbba148c90305eb81de0671a5d28da59e","pub":"024bfbef04401d5a5938c64619a6c566011b3cde0c1418f2b62c3a921f3d3f14ba","addr":"f0fe3107cd932d601abf273b7547be623bce653e"},{"mnemonic":"angle blouse weapon upgrade enhance frost fine pear install method duck okay","master":"aad7d48511dac2782ad61a97e3ca94352ad24590f1ffca0e9efc3c6ee69297e6","seed":"8651c2d20d4af238121b528fa601c290efc255a569c8db892ca8f77d634fc02f7098efb7a9a45262c7e86d3d71cd92c7239fe4bb780e69ded7782c00b1ee0ca1","priv":"4b8f93833d5896f673ed59c0bd75a34917a61d521cb8b8bdb22814a0da0eef19","pub":"02e17e65c69b471a9fdb75515aadcbba673dac78c0f34df920aa46ad65623400eb","addr":"c404a9b79ebfa5ed9066e06aca8e091c488bb740"},{"mnemonic":"trust huge gauge culture garlic fluid type drop arch camera true claw","master":"b74303ffd6d878d1ed69a0e406741b51bc725887df08a1c8efac15a959b8d0c3","seed":"715486a3cf1e3db172fce32a23868a832fe7d5ac2844990fc14e951a9a357f16e2b5bdc669e415a40efc7ad14020991497496e980395639a68c6c7b037690cb9","priv":"2c0d6847313ed5c928480a302bf3fa0bd9918a5debc3ddff43cbb4c9e3f12802","pub":"02f79fa697f78fbc6b154d7b14a3b28dedb6b746b9de88c0e9982a54904ef124d7","addr":"c15d6b60ea16407697665acca000d5f792fdd3b3"},{"mnemonic":"shadow sister evoke wing radar what trust main improve moment flee erode","master":"cb1d183803a2de896f83834d19c3e1ef518c3fb6382dd68ab310696bd1d69b7f","seed":"444b9c8d29447c024f11e3c6c1618e767d908dbcf380125a062ce18a552f39fa108361fd18561406eea36e63415d286eabe5d5a5fbd23ae5bfa846a3e8bbaecf","priv":"dd1acc9e8972c3bf4363b3411ed96f41477724b4353e514b339baebbb03a65bd","pub":"028658232d2a075b2c68a519c47d2d74636fbdacb8bb31c9af70a967682816ca14","addr":"f8db02ece9c267f8f5b7de9c801432e694e22731"},{"mnemonic":"guess beauty gift repeat desert oblige pistol pottery lemon clutch discover dragon","master":"67ae574f5ec3766b3a0e1699dfc188f0ec78b51e69faaba76dbb08cd3a9e6382","seed":"395674e7b70cdf97f6072be527bd79a6fcbfffcb4322786f8d17611a3bf87947a87fd59146a59e7143a427c4065759ed6973a00f6aa522e6b13058382eb8b080","priv":"170df49f85c0a741bd5a6647d33410f944619de34e9ebbe7387fe8785b470960","pub":"03dbaec7aec40764a0365a6b2b00384c7966e9b2c97432273abbdfd089c519fa4b","addr":"af3c030ae37cd0ce5d3c41012b904738c7905887"},{"mnemonic":"fire duty baby kidney coyote arena bonus convince soft party blossom brave","master":"2054fc16a8c8b5955c76150c43fe447fe7a6d083b323eba70784687f94780a75","seed":"c16d9aa8d945a01871a46a92881c10ffafeebc0b1183e97812169d8f6e4f094e70f82576947917f3f6e551a9b9dec573478180053f6e0d71c5c48eeee95b54af","priv":"fe7f533210200354ea9c5c972cd0a4445fdd8a2e6e6e830cb541fc894e2e0ddb","pub":"02f9fa53e71e4a2a180d6daba5ae9806ed5e338aa680e2bac8fe25ff1a1a151d0f","addr":"2f028ee2adcec5023013e7a3756fe18c9a87b669"},{"mnemonic":"poverty inhale unfold strategy insane usage festival dizzy drop divert august head","master":"148e592f2c22b1db9d693e3777470b27ed0fcb2de1c0ec2d1f9f47421ff98cd9","seed":"412368afe4a71e2a37b1f87b7ce82f64dbef5579b16a6c189fa2ca29759e410b7c1e13a7b591711fb3d5bc8fdcb3292b3c828e52a2c1cd20aa55c830b8506a39","priv":"7e070b5f714cc7e0e031be68dd03e6b3e18673b5966d9c17616554df4e0f3288","pub":"037227c68b192bd6ed034570d5b5d532354dc47891acae0815d0acbd8d0346ac2a","addr":"439c830a56e6f8299c4d859c2cd5fd4a821e6dc7"},{"mnemonic":"gossip quarter proof require develop about olive boss fiction quarter rely build","master":"8b7580ddbbb3b766cd08088792cde2429c003b8b0fa5a9165747275685223a9e","seed":"a3c24f6f125702480e2d8856095a96f3e6d596678f15817414631ffa525472a01bceb58a0790e1df38dbcceefd73dd9b6bbc5bab841503daba8d73033494c254","priv":"5bb1bd6cee64ee4cc9b08f27b34dfd3da9ea263cd7fe7b4d3fc8a6a2db4e0ec2","pub":"03bcbabf0702cd56f459b8cde03db89d3c953faa3c108e90b75c65eca10485b5a4","addr":"c3ba63ce6c961c11bb3f7cfbe7667ef2c1ff19ad"},{"mnemonic":"dash small ensure soda crime wheat future style guide repair diet panda","master":"468770a80bd9e0190ae3a7a695da6a7bf30ac9bede3805c7d1dd4f6052e4d7c4","seed":"59eeaf79145cd625c266dce31faddd42eea93d15e64be3a430b9fbefdabc85cc3366115a07d819bb5ee026e118ddce46a2d906680b59917ff7adcb3314d6b077","priv":"99813e574552f35d2ae337f8754afb37d8387129c5e714461a0b72cdb30d0bd2","pub":"039e8088eabbbe966cfe54264bd1335697ca335eb55d56a89ae6a2af0bcbe2fd60","addr":"b3926244d741397940f6218c6db7a7c71cc012af"},{"mnemonic":"profit brush exist mobile diesel keep oval guitar cover maximum media file","master":"f402407479104621247ca60a34f75391ddffac32511b61e83324d85d873f0da8","seed":"6d538602ce7d97d7cb5469aede489a9a4f8af829d76712c13e7851d9e63077dcea3233ad51a7c311d367d4d982bf963c016c23fe39604cdc3d1dfe25baf1f515","priv":"cadfc276bea3a62afe66fbb5a4d117aaaca562b272aca37a0ddbd5f5a20c95da","pub":"036aaa723e425f879d4b2e731fda45dd95294608daf9d553a40f59fc4cdc37c996","addr":"0b6a4c2a542c624ee95719f53c99e3f6c6f7df19"},{"mnemonic":"oyster twin legend bubble bacon wisdom affair bar search just daring teach","master":"722c8eada15c60706ea1a9fa5aa6225142a623d6f5bd946589b22b3c9e69f56c","seed":"2f3967f0ef31b8d1bfe4b125678ab07328ada854f5bb589b5fd2c5479c3306eba54233f3386409e4b68f95be7f4b20c054f7930ab022f720979c847bbac99b80","priv":"73b2d8daa926db7e9072d4576dfbd511017e1ca7876bfb453112c8308ce70fef","pub":"030a96a78ec8dbcc9d62b9a8ce221b0f740358e75ed7ead277b56a2c56bd93a468","addr":"0ab19ff6566e8294c16e734306415bed696791d0"},{"mnemonic":"say poem daring wild toast force fall bread cup crane next patient","master":"89a87aafde53a9a8fea6b38549b6bfccfc950dacacda40f83b613a6322299164","seed":"b86bdd449d73412f10419a9534fc545a5f062d615ae197b6ce5143a1b00ac838b09e9db2cebd5cb556f469a4eaf883b8d9683b222f9b8843314134bd718b0887","priv":"60b1a4533e8afb1ac5eb5448db1540b859fd3650dd4e7c52b8b1a98ad3eac169","pub":"0255161266504a58a273b413e75fba8ae3c49046a3bf8334b2bf4a203f837ed383","addr":"2c390e3e85f391607962fff3ef9c3a7ca4ab5704"},{"mnemonic":"bone path relax awesome planet exercise road reflect life ability device frozen","master":"fd23233c87545130d43a46064fa11deef11d56a3cbb0a2e52be1aa21eed24f58","seed":"c72634cdc1fb47955eb7d9fd2391b3098d407bb5da35c0a88fcb38746c4d673ea113a96707828b18549271af8cd0f9be51f5caa9718ba31d783a3b26d450e7d4","priv":"d946ac6ec053521443b3d8d2dad6e947dd544b58912fa7b87b0b7b55f8570981","pub":"028b9c6677d3fce87d4b324ad336e486d382f7b56c2a1c8723d993d247ac1e1caa","addr":"6ed322bd71b762e44bf4554937122492e039380e"},{"mnemonic":"true solution afraid clip year symbol burst alcohol orbit village arrest balance","master":"3cdf923de0656e5340979c614d12ca869b97bcb476f8ddac3c10162cd23ceaa9","seed":"13c3eb909b83529db1d166eca7cad6b918e1f58c6be120aae8b7fd2a2c848d29550551ba3d710cb4d4a8597485e20535d6e65a941d206c69774cbdb04113ac17","priv":"1432f702f33b6c318f79d2655da268dfba6075126108cab3c8d88f4de2a6a0e1","pub":"03d100bcb7a2b81bd8e49af05a92c9a874f4aadcc836be590d63ffe8a08b63a0a7","addr":"3527160f146f542703309ee02b4ef783416fc9e6"},{"mnemonic":"family trumpet pact beef stand naive book escape ensure puppy envelope dune","master":"ecc1fb248992b1402eafb7d3120569255268dfa5ace3d04fad48b1917a42c3bb","seed":"f0f55ed35029e7f123dd153df36cfc9bc97c633b9b8752264bbbc2c33bb5932ffbd1d657bad87f8ffd7d4d9a9355226d2155fff92109adfe573ec67a18657f3c","priv":"8cd151b71c1f1424e2f53a35af5d427965f453572a211d8b4315894d370184b6","pub":"022ec5ca227ab19d758ac5941b9e7e7e13a06ee9a59c94d42dd6d013ee7c3d1cf8","addr":"93f08bbc6109187bcba87f2b6bf86e73eef60483"},{"mnemonic":"feel grocery tone drastic clap great pizza artist current true diary suit","master":"cf0614735905c88cc0f2236dbf71fc61accb6fcba39fabbac4ba1275a1ce6e9c","seed":"75bee915c2f3216cd023b878d06aa4d45241a49d10085b851303bacf82c36b392e01478359e59b54c77882948aae3026539d687298b85c3517f31ec0dd80e213","priv":"03e47eec1c8f7d3ddd3bf1997bdec4802a5b997e80a9a9fdaa8ed93f2641b146","pub":"024adba9bba7c596189ff4b057a2329740e03166cf6416612676d68a6df32c56ae","addr":"ee63795d783ab1a27ba8fa2a64665c6a563134f9"},{"mnemonic":"health across rare laptop broccoli verb course bacon offer hockey vendor venue","master":"a80307838f0014f827d55ec51e5384722d7a6a24703d757aabde32dca9f6dcd0","seed":"5fb4a16684f338f15b5fa6ea48975ababb129b3c01c726493abbfea837757fd27ff0a70bcbe2d08a7174fb7848169f7e22f483b8976adb0a4b2600657c9eb912","priv":"255717f5e26bd51d607b059c9a7ddd153d9bab0e832596df648fa671d8535d5b","pub":"03ca70b2fe6fd3def827767c0b26b25534bfe22ac74f77c0c4c05051154a08ea69","addr":"c4029c4186f3e762228f4d43b4d8fe19753b99b5"},{"mnemonic":"begin step squirrel window liar lock endless maze health galaxy swift scrap","master":"53ce62b273658f9ee3ef5b78a4e9d8b9a84f383053492d86825cd9d360763406","seed":"93d7f29ea325b084210dec914666f70ed46b83b7818d2dbd1614352134dcb021d539acfb2f4d916fa5ea48babd11d95f12eee97860c19db1bc2f369c6cc96b93","priv":"50455038499b153d77f388654037cdf614bb85ba5470d8937fb108a123241521","pub":"03f1f12d396494513c14a7508a9ad1dfeb1577af519a250b48798ff59f5efde3c4","addr":"5c46de48e642722b4325afe8446608a60e7ea89d"},{"mnemonic":"snack fall math great upon wing casual acid clown despair cage heavy","master":"c40433c68e968ff1081d3ffdd47249f1bb3cff2214f4e0f19227442f8e7be4ee","seed":"6962c13ba9d9b79b31480c117cd1613f6bb9dd6613e42b17b7434547694c96059026355a2c58b682ebccddc5f84f50c05b60b517e27eb693f1eeff24a038eb0a","priv":"972881fe79c997d86f11440cefc6c52a46a1b3b9953a255da6488e7ac278299d","pub":"0276ddb2041eef2c3b487a4afb36de7cc5ce5ee693461aff375131177dc4d28b40","addr":"17ed4db6f0bd80e929e048d526dc55a74ad58eae"},{"mnemonic":"vibrant valid carbon wish bicycle adult hobby lawsuit problem toast clever lock","master":"903e9b75fb472ad89da3b1bc74937415e877c1973910cb9ddbc85fbb465c18e1","seed":"b175935f86b62ceb93ed1bc1d2f3aee77a628aca7def8f6761df8b624a29d495a150b373d12a5cceec7d394aa91d0e68c5e2464a99820ac5add276d655be28d7","priv":"dd46bb3b1342a5a3c3844ef7fb4bcb247f9a81a48e20722faa1e03ba59808191","pub":"02bacfbf1b8b6d4a6e8a36b913d61831668cdd3dc74710c0ae0851b87c65789edc","addr":"e0520de38f2d2c2d3e461b1e2fd3076af5b9e927"},{"mnemonic":"obscure false outer neglect transfer other index debris bread crawl morning scout","master":"601edf66610cd4b9467bd73418a3dac8b937ef2d08c09ecbc89110443c3c8869","seed":"9d6168c1331c952ba5c2b19a0894bddbcd3d6a0960ccd5fe685db487ab8caab4109e2dda7c487d6161427895a9803ef3fa857fa2106e48083587032c6d30a217","priv":"2389d4e6527d9190a9ad8720debd487a00d47d6ad6228d643e1307aa727d1757","pub":"03bc72643c1c9a13f31de0a61815f950aae5e186328d07bfddf8e1dfe952fa8b49","addr":"add81ed8c06032c52445dea0db02a9f56b738742"},{"mnemonic":"minimum coast chronic damage page antique mechanic material worry alley nose tray","master":"d7f00c2baf2037008e9d1fbc1acee85127db59ce939491aa5cc19033f55f51f0","seed":"0ce817dd3a344f8dcce47336d3bff28da5cb9f5a71fd26e54c4229e9c0bf943077826d72c68e7570804b1992646641d79f8ac1b0fe157b7e12c70413d9625e22","priv":"76e0ffd8727768a428fef6d1e4186459d6b3664fec801ec542608c955dd8974c","pub":"02c0fb2dacc13de0d29fa26144d0974f90b97ed706c16ccdfac02eafbadf9e4e0e","addr":"e28e2564870c7fd74244b111e188dc82c27755da"},{"mnemonic":"evoke example emotion suggest apology uniform giant empower future surround pizza scout","master":"ae3bdaf7acb6660fd151ed30d5d299f82556bae13873f6cd9e65111d991b4d00","seed":"840044591bf305fed33beea796f2c5a8ef72a5005797762ceb8528e1c0343696c02012ef81a8e964548af3293454fc6e3329059e40a95e9225fa254fa901f3fd","priv":"2ae6395640b6827f7b3af5d2a4a0f0df46d4c6c5bf28528eb3a896d60c80e0f3","pub":"0378059ff10a1d3e0ba1876622e9d45a9b75f01216bf14737a68b48138920e7adf","addr":"c1333d4372eb2dea3311829c10c6d12f17437cb9"},{"mnemonic":"endless come happy cause skate short list laugh amount marine glad pear","master":"c1643f331f86b0cbf7297eca946e44d0d1a1b3e704b6dfce6d53d9e9c6eeecfc","seed":"f3901b079e9987dffb0378a76f099e39349cd6abb9c59c23ac3f1cf90b988e82b71bcb3466b7a2f9e04e0b5b27bc945a3b4b714e0272184cb64e9b4f8d6a638b","priv":"e80f64abaa7b55214d94b2bea74d25a45bd6385bb2447fc53adc4be4820edffa","pub":"036d7029b6f83bbbd1238bfe9a2b8ee654ebc1b2ea9d00494345783342705ef7ae","addr":"56fc7b9a42b8dcf74932b92934321f2568606240"},{"mnemonic":"boring math photo park connect wash captain drum kingdom replace exist beef","master":"4853a21045f669f43eddd0df88100e473320d2f76641ce5f9d010d654f4896c9","seed":"65e6412f40852556186217c0ffddd4291b77651f8568d97434f1ce3bafd4784642d9eda0c401f9ec57ffc80c161832afd43ab89080fecdb8d6a2570b27b2f0a1","priv":"67f6f9aed318eaecf6e80b3a89748900f3dad77502893e133024616c15418799","pub":"02b0f15eaa2f0b9c09a03280c9689aad73e3e60e6c971ada22b9352cf381d9a7ea","addr":"741b1795cdbffea0b144b22ead2d466413bc232e"},{"mnemonic":"true also hockey holiday increase humor main lonely invest modify penalty soft","master":"c1716c4c6563885c995c00990cedcf3c90734ec9cd0bcfa327b19349762d1bd1","seed":"e192cb10ec4d6813342e8ae74c60ecba75c8f9f23cd60a92c8abc44211fbabe82f4f11e30bf68bd447c8f0147be7ff9ee9b64cb8c44ac8697f2bd1ba886f8427","priv":"f72b0a757b8ceb4bb80b47704eefcb5e0448a9bcfb7385fa3b6492628c36f2a8","pub":"020584eefaf032c19e853bdaad1d1bb8cea4001b8d5bc919d888b1cd55f6e88b04","addr":"98ff8a4e963a8e8cb4a09e10a83cfb704abf92f7"},{"mnemonic":"inmate mistake detail main sugar find maximum crack soup tumble helmet caught","master":"9b6e9657a31f9baf6f303b2df638d84e549fc35e23f4cd7b8b96ba608c474657","seed":"fea14199acf507de04127191e47dc5d20d60ff473d5aa600ab697b7854a7351bddfc24d99057671273b62111990d5bb6f0088af026b38448609d3a4ac8f58b74","priv":"2800c0aa8490524c5add4d3a2def895d8d54e9608a05fd21a7bb5373f594999e","pub":"03d49899c17ac5c0a8c3720c1a9593950d2a8a591c8a8fc24812d198ec1931b5a9","addr":"e198b4a329be8be7f67e4c7d63bdeedf9ad5b45b"},{"mnemonic":"embody ocean catalog shrug valve extra potato subway casino father denial oven","master":"a24ea5416ed8d137670224056db9656e8c1a70f8e602bf6a49cd2f7e6968fc5a","seed":"447121225f8095e806b284e249c1625d925999fed396dcd7c36d9fbff5339659530fe2df0760a9d1d15dad32e1a4c1577c518bbb378272b305434d138e748831","priv":"548afb052cd083e9504a6d602614d085c7a20f37556030550d13619cc39241c8","pub":"0370f25b9cfe827ca110760fd13eea09082573b534411d1719a12fbc9867982e4b","addr":"e6abb5bdb479ce55759bbe1d0331db6046f1aabc"},{"mnemonic":"brisk present attend rib envelope keen mosquito athlete guess ginger budget interest","master":"8e34652bc5848d8fa141e06899c93928c5bcbfac5e1daa60c77af837d7771b96","seed":"4305389939cf757a57a7ecdcdfcc09f7699c315704a3d23243968932386f01dfc8666b7dcfee1d7ae26a747907c85a949843ffc91c9abf3f98007d394b1ba2ca","priv":"65e554264f67ab679321ab7fa516b5988e6049847de929d6e1949032adf1452a","pub":"0358503d0c6dc10689a3705838741f20b83bd5496c4befd2403f69760533f7b28a","addr":"80b6d095ea92c035fdd56adbc4d38f209de13000"},{"mnemonic":"never gravity problem draw arena very panic patient clutch trick calm topple","master":"a6cf02c1407405402557a745a96019f2516fd7ed03677871da922282358b23ab","seed":"ea44a019240e09c4c642351a7aa04625c309102032b9f77ecefb4d33c25f31179fc52c300b4a2e57603c08b5ecb77600bf9f4f9fbdb07cb0dc7e822f709ba7f6","priv":"38ac40ab37d588c0b7ed4a6f4adb378c9e1a6d8a3cb220853dd56abd7327df4b","pub":"039f5f8a5513c74284314c5c5775ed39c77ec9081b978a3b096af6670630046730","addr":"c6a7dfac1a85311dfb3a3c6191a6124ce8ba39dc"},{"mnemonic":"aerobic slush coffee volcano tip speak across evolve nothing deputy limb arrive","master":"d0b24358e5a1e4cb2fcfbb10d9b32330e02be92f3397e70c8a81b04f065958b8","seed":"927a69f86c0f796ef2a6f89698ebcc6c7d2df24672d1c597c10f2b3dac8123808b46cd63e726eb6f1699b0790f14da3a82d9da2cf0fdd32a9b936c1763db0522","priv":"1d736f96fb08caa2ee8c9d4c1506bbdf235cd3ce076a976f8a7be2bd621e5a23","pub":"03f6d508014c45fedbd92677a8dc94a72a7ada2c893d0e2d508c4c9be4fbc669e0","addr":"7ccbeb5e8927c714b3d4c1047e66757bea289bf9"},{"mnemonic":"aspect glue bronze steel idea trend win collect ceiling puppy gas flat","master":"6320f492fc27070bdd7b99436ebfdb25f462b588f50915e5c79578613b53e41a","seed":"e0c9803520833b770aa6febcf2a0aaaeaafa6d39400141908c6577d99ff4ff26062451a4f1b2ed4dd91eafa345f7efa1d565fa101cf0ded88188e9d07ce62e5f","priv":"f87d3a46e925d395a8c4539469e0474cfc0bbed8005b50d539a28c85e3a44a28","pub":"03343c7d2cf83e568ea0c9b92e766c6e021d4a95ccf169c2c9d085693490d66f0d","addr":"6dba7380eb165ea86e2b07e30c5fe1022e046da7"},{"mnemonic":"curve better narrow reopen vocal gossip fall tornado fossil scrap goddess direct","master":"3fed34f65702bb4cd41a309cf81ae4a8c13b569e1de5420103bea9cb264a0ff5","seed":"c3f0c08138f32640b3fa1e6d9fde51163aab66318a7709933339874fe8bad22e75f6c19004af5196fe84348a1f3eaa37add1b645a320acf8a1fda40fd788b428","priv":"c99eb1a2f56c8ccc3ee2d2bdd3d849b6a60e1e82200f72e55d236ef1b0a9fcc6","pub":"028c3c8e1902ee965f55211362b5277748a5da54b43f0807a216581e6d686158df","addr":"507e551fa72ce7e9da2b19f4258c2ae79793aa2c"},{"mnemonic":"insane screen heavy sphere turn drink direct exhibit turn pattern series pitch","master":"b060bffb238a046de32305be06a806093f62fd0d52d1ff5b44b70ad45f502996","seed":"0f75c0f282ec504aefabcc1cdfea3e4166b4f6d4782771a905683e26b05dd5603178cc3fde6fe4febba6542350b15a3c393927ef1e371ec450af6ae6f4ed5a5d","priv":"3f590738a71a45fb5f111181747b44e342212ad15350db1d3ca475b9ef4914f5","pub":"02e50487e89882de6fe3ff87c7b12542a8a6a8a8cd2b4a08be5071aab04b2d461b","addr":"66284b62f4b7f506c6aa0f935d034b00f35fe66d"},{"mnemonic":"answer mobile swim shrimp jewel smile security shy decade sign physical width","master":"64cb57bff4e190f89d2d7564be94cfd1efa0014ef403cedc6946eb52a4a78813","seed":"3f645e90cbdf7eb6aed9afb802fa22f1c0baf57a79c813fe21478a7f2d658dc83c3498c75b0ee4e01a02cb11609473782065c7656083d7986df7bcb320603691","priv":"12c7e6691ffe251287754234d7b98747f12183b5535be6c886f86268b28e9175","pub":"0375b4071b801b389cbc66de9443623ea5b86d310297369305d869e885e187a0c4","addr":"b6fee98515f241c4ac41fd1382a1d7211dff3af0"},{"mnemonic":"match car rice essence try reopen wrist party choice creek inner comic","master":"60b8c48a8c8cb2d68a92559d1ead30a2cac313df4f5a84f94d0b64a3d5569047","seed":"17a91ddd485e6becbb822434a723c5143a11aaedbe9275b36080f92303fb3ef4d934abc5d36bc51b35946a4a683f932373e4a3276feb0393c499a961b78fc18e","priv":"1d9e0692e0c3e8d06606423fd6fe3d336b893c13b38ae3339aa3d7635e2c0046","pub":"039de765de0080a12871f7a278fd27a21ff6052d864f36a01aab4895a3e20d13ef","addr":"6a1216c843cdbe2010e5f024e265b31aa01592bb"},{"mnemonic":"leopard garlic permit menu opinion kick clinic upper start vote truth okay","master":"9db65a69d3ee0bc07c5ee34244faa0f6e8008c51c5372ccad6b9d54497c27f94","seed":"f125a9285412d9aab52baf0045d628d41e870814cc1ee92746d0cd0fe955bd30e3f5519521c6c7d172d07d53f318cacfc5b9d4b0a4e508f9a1056526df594283","priv":"da4acc9d2c281a03f904b42962e021401602b65c815b9659bc4a344f6f35e934","pub":"02744a41865188a5b3a37032369fa4ef214dd2ad836a35dc738b501736806b6606","addr":"fd86381be60f3ed78fc53abf84a8652b3c84b7b8"},{"mnemonic":"vote divert tower history staff finish lyrics empty bless alien walnut hub","master":"10f25de189ec007f9caa97230456a55ae87a807178e8cf23e84f761ec7c69cb1","seed":"ec42f0f2043a01fa768a6c5e889bdc706747abae60609511755f21b7798b7e3c476d38d0b2894f2519f2fad6e279d77a04e1ffa864c9059697da274b32bf3b88","priv":"4073cbb35009f9e7ad4bb18a0c3c7178ece1b9e07c9df1d595f5142c51a92bb4","pub":"0340a0d2e43896e6cfc4d0a7ff49afb1ac28a5ba112af2882f86510865f84bb8ca","addr":"21e3b66a23dbeb25b3b0e2372e2fc7b64364ccee"},{"mnemonic":"debate between rent foster stove powder truth remain cancel pupil object romance","master":"aeb2d34623bef5822150858dfbc2c0c53986c363297e9c3fe1ea64613c6701c2","seed":"c95a64fd29b7b9f15d9077e6a67a8f754bfa55bb952ee35ab94ca001caaec42b45ea2ae7223fd10492dfb02604fbb87de28b4202c49f72be52b7c55db0c8edf3","priv":"aaa218916efc3fd6ad5b948ffa4a3239984b06592c3e7809df3bce89b7c50465","pub":"0221a21829f0dbd3043b9a7645c182e835cd14c95ce9931c1e17284b9172b77130","addr":"853104a703410c5faf86381d5d2adb4f3254abee"},{"mnemonic":"dismiss fire ghost eyebrow salt report pupil include case east blind filter","master":"636ab989611298c004b6ceca6cf887c25d44df49260a8f755cc159d74fa971a3","seed":"5ac06b4e40354a95bcf97270de3db0ac2c9bcd44d1a83c40e9f2557490cf794dc8ec43e71d3dcf3f13e6a7202d84b835c124405a2dc79119288ebfd6352a1d1c","priv":"ce591b790083433d60e3678d5ae488f6033c8327b494789f457a4a137a99bb33","pub":"02607f14149c2272136dfac3ba34476203424fb3eab4282fa6e81c0bce0357e81e","addr":"9b38671825a0fa55e15833ac583fdaf3fcce3800"},{"mnemonic":"awkward slot wrestle sudden core clutch again pepper private reveal shift baby","master":"868dc5c7376cb2ccca274744e97e1b6f8390c1f2fb669862cb624fda1e8d9408","seed":"065aa8d9dbe5769799f29e7a99e663a6e622f0463c6b8093486728d2ff2e8dfe2d9d30e357ac6416515f043b9c96267f3b0de08f3b88c6bbe9486c3c78cdc44e","priv":"e6d6be1b041e0d52d576fa52f4987cc2c8490d86a49184a231703ca0f3d1fc16","pub":"0375e417a16b94bbb1e8cc1789535fac4abb78b466d2a354045da76405ceb8c35f","addr":"280ab94c67d7bddc3ee6a83571a2941b06c83676"},{"mnemonic":"whip tired like merge crush bird venture verify grow fiction provide coffee","master":"1a1a931d51b74af1b4ba19a4ad97b2d5d8c79396cac5d7dd7883d83d79fa81ae","seed":"a03ee9671bd73e717e93830e97dce58b4b5786321989e9f446daf96a6f328d70f5d5dcc4c40d21b7dd4b27aa6809be2a3aece2f3c2469923b8e3d112c899e3c6","priv":"8bc19d1e811c334e4417013c3c85a2040cea8a3b61c18bec0c7520bab9dc082d","pub":"0224c968015439332e83d1737b7429c7bcece458a00a94cc83aff758c5386e3878","addr":"a069c8ae758f12a39e86b2858865d95e953afc67"},{"mnemonic":"prefer benefit sound knock exact pull clutch cabbage local burden small report","master":"9d8ac0f2bbe4caafc11f2cbd9e644e62ec5f54003701453e9c08ebb5b252aa10","seed":"a6d48540efcd54706017c3a5c47773a4dbade3044bf445f8e811b2b2a1a584230d070c296fec26c59deeef37a7487926783fc96fc593c270e90d7da08766ed38","priv":"bb6d7a3a4717541b7e33146b75789999b5d763d14f0962fc43ac30193e711b38","pub":"0288eee81a2e81977eb56b163ea601470d99b9024b5b99db2af88228842fc6d4db","addr":"62c96ec870a47a2cd540758e27fb19fedb11d9da"},{"mnemonic":"case choice castle monkey awkward kid submit layer bargain reward ahead type","master":"c3da04cb84f0f98ea8723f2b6d7e6a3c83b30e5ab8e0ef75bff51ca0b4a00707","seed":"c65366f8af99f805aad4f87c4f73c074d1c99e69fe65bd2bb0ac6a1062bf9595051133c32d5abf4910cda20b9e8a8cd76e22e692e31c02f9327eb703602a9ff6","priv":"71a0279874cd44a61fffb0e65d7fcfa0f4f7c24db912f18f587d6393f8fc1154","pub":"0265ace29b8dffee0f31e6bb3e42f91d90eceb13357e6d324ee2cbc41528ec1c4c","addr":"cd772b14963185ed989f1085142b2b0ae2e5f980"},{"mnemonic":"educate meadow confirm subject tube urge guess black friend later cement spirit","master":"28cd56e6a857ac35c617c4665c143583e0626dffdd7a5e0ea55ed75215bc45e4","seed":"bec29b984cb4df491eb1154fb2717662606fa63742febe91e10d19057c9134b4d4b8677ae23e006b450d6d485a67ae09a9c34fcf8cee5b22be821dab855cfba9","priv":"fc3c5da684c39ac6ae5a91a3b94f50680f6562187b5a138551d20149113d03f0","pub":"032eda5239cb98993519d44e7838c971f9bd8ef140da2fa4a95a70a2488f78f1ad","addr":"5a9adf7df64dd7f7e9e0d29b9fb90069e8230090"},{"mnemonic":"way butter chimney fantasy rebuild delay shoot toy ugly festival resemble promote","master":"599622e23b3db7ee9a6f8f95f5e39b2562170fbc4dc0d84b6869224b9304f134","seed":"a5e0489af660e70db67649c03622aa66b1a6c57d2593204cea859a146b1676893c94f4390740021a51a3a076b27239c7870db78ab7eea48da0a0177a10b8e16b","priv":"e16a619f8355c4cc276583b67fb2b2616d23d09557539fefbe915c6922e80ae4","pub":"021e6f57790a3250f24b6323cda9f648cd0b1907e5c7a81369d022748af8a9b0d1","addr":"9c7b9192469e256207f7758a906d0ab3c50e4fa2"},{"mnemonic":"sniff rely wine book guitar repeat civil elevator olympic wasp dumb often","master":"43a2904bc971e275f33f12109c2067877acb6b00cec32e3913725114b48bb2d1","seed":"cdb3853a0160f7ff9f3b6a9d10192c11ba3f74d45f4bdd4366c9153728105cee7e117de9e8b13be65d3a284fed6866ef4850898c9c2ac4821f55a9c6415f7e16","priv":"970e0aa6e521b0d938c41143fdd75983f5a315ab51fe0e2c79f5c37053e7dd70","pub":"0378b468aa83eb47cceddd2ec8eca4004a9e99ccca959ede92d9b03ce3e38d5099","addr":"9b285c714fbf2d0d9e39395b08d07e3eb87ed87d"},{"mnemonic":"salad print drop winner chicken despair bleak warm misery buyer clip glory","master":"77c5e3581d686b79e863b82f41e563fa5a487e11a782f609b4559ff5c52fa091","seed":"494e915c3897e9bbce29c8af192e7360865be489b38efb5f6484955a525d7120d7637921f7ce7cfe820fcc996c9d9d0edd76f8376a48549057267fc7193cd66e","priv":"a7e988c4a3e661ec230fb359e8f6f7b9593ef5bf33b9086c1460fabacd162600","pub":"02f91a2b6f0545a45ee7d50d6899de984dc0d29ebe6f75cdb3dd169c696daaa9ff","addr":"8bbb9c4b435d0f42ae033e2819a600ab49f3a21d"},{"mnemonic":"inside alone salt borrow fuel stereo toast hotel want arm happy marine","master":"0bbbbf5948912d5e7243baff26886acf316b6ce9f450ee0d60d262b568200400","seed":"afbec9326da69fa938e71403cac67aece539c5fe1156d34ec737531b6ca38b68e60529d589f887ae24899ed8ae53b9f8329f64d84fb62c95a7cfcad45e83f6c1","priv":"8e2532f0440ecb83316645940e29d0b522adc421fb9aa49a8016b6bb1ad34e16","pub":"030de4b35fe61c0fc2fb4fd295a9352e98c7080cc99a6f70d6f64229745c161be1","addr":"519f731ed0412ac24588381879f050bfa9b01591"},{"mnemonic":"cousin drip gap gift ozone omit road parent square lawn crucial color","master":"742d494238d59034ac2026b9a94ad7cf75df5e1b481de734c440a8507e2236a8","seed":"82a0149396a6cadb670d7286506e1a0fbdd771751b39562eee0531d1a2353d29229940395cfb0e00fa1a6d26c9d117039d2a1738ffc93b34161e29de73ee41ca","priv":"aa04e7953be44feea3ddf077d01644f5b4f1eb85fa89521dafe85c341896104d","pub":"02f0d80a4cef0f71606ef476aa04ccd34182bc12b0c45708b0aac49fc2781fdd35","addr":"4a2358c67e4faad28e0d50066a9da25912c1cc57"},{"mnemonic":"list power fresh cricket must expire globe noble park eternal tongue thought","master":"c5210503dee7e7530a84ebb0ca5ca9f15670dcf987e82d67ab2213ae76275b95","seed":"7e482fcbe082d1e9520fa44c8ad117f4d2fad839c8556ea3aa4096a7b940009021611938b4cd2cd82434f5ea37afb4dfdc3548af496f0afad91bfab3117b241b","priv":"c14825a7bf41e5daf44cd9917f33c682da9fce939bab16421bd7dca1e04644a9","pub":"029a20080d20312ead4612ee0e9cb5a2d641ab929865cfb19c3234c838e6f75c44","addr":"750b5d9c00adb243177506688d9bf4943a3ff666"},{"mnemonic":"bless goat worth boil street wing quality visit honey couple upon sheriff","master":"c66453fb857a3deb4ff276dafe0437ba6dcecdcfa67b095053a060f9d5e67c26","seed":"b29cfcf2aaa980c88ae8e0b151601e40ccd6dceda39b4ae324d6d906bdd3342db7ab0f20ae75c1f1b424bac7b679b252532b4d5990d36d91f7612120a5c22b25","priv":"dd96f23418a459bfe23f676db88839e63d1bce7ab58b76d28e494abb1da9616b","pub":"027f81c68bec50476477e5d5524919b7e40509818a16da7724c62de26f23fc2d65","addr":"8856e5d456716486cc794be572454bf41f013404"},{"mnemonic":"slogan outside park during produce key meadow cricket glow choose pass tree","master":"4d6772450ecb47b86c562d5accee0f78c09b182ffe324fe0078fd324474f94f8","seed":"a050602af53f0857804abe575f05a664c292abe43782589fbee0aafbb9654988b6a46ac26d93ba14166d9c6f887dcc1693c2aab5a782f4277c0f153e3572936d","priv":"92918d979c61e8c6a256548502714cdb0094ab6fbc364891bc094bdee708357c","pub":"03dddebad5131d93de5078fad3a380a717f2d2dcb65743f05a84dcf7f29a26f9c4","addr":"0c34fd5317283be4b9ae5a953f539028a5f201ba"},{"mnemonic":"coil burger alpha grow lyrics check page spirit sea mention course fame","master":"9b4a2e05f533427551d7e44ccef49057b2fa0ea57a5890480133a8cad67319fa","seed":"013af1c7f10ada279b632bcaf0211006d13e62165646ad3af69da3b60f044ce62e9bdc7c1c6758da037664f18f1a1189683db16fc2ed39192a7737154984f417","priv":"1a9a114d594bfc3e41c3f507114ef3b872b70563fba390dae992317f67fa0241","pub":"03c5ce908d87792e067ca19d4fdfc15e3abda1993f3ad1f1c8bc5168c58c3c4e93","addr":"cb513df0682dc11374466aea70d7cd9a45d4fd44"},{"mnemonic":"napkin mystery powder birth crowd fun disorder bike lucky core dance punch","master":"8fb55d8de947c13497a83c9631a4fe9b0b491cca2743a6a056214c1daf5cd87d","seed":"f8c5fa5fb7581ae597edbf214a2755ac2bdd58dda03927c21c983b545674de67d69e258a196ef36e3f3e319863a54b521ee1e23807df9f2432b5004b563c2509","priv":"3846cab8eaa4af163f79dc83e5968ce0a59b7cc2f6f725767f70fc1780c00599","pub":"0399eacd20a2a7426a0946fba205891d22fbc041d264372c6bc981c3e7200995ab","addr":"3fc8f92413e731f59ea2768ca40393a92aa8dbca"},{"mnemonic":"sock real audit mind page price rocket home economy glove water rubber","master":"205d5de977b27ef90aa092c70456b516aedb62bd164fac4e4ff638be56d9b9cc","seed":"129afead267c2a9556c3cd3618a29b659e98d651f52259acb1eb4ffbdd6e61d87ecc487123994fe4eec4f65808d9cab6228f8054f8ba68c59a6de8a1997bf420","priv":"94f20ab0cca31de6ed426a818e8cf11299b8112905d0bbdbed79de137337983c","pub":"02ebd561df3cbc137540c7b9bc0c919021d4c4765a9f602078b028e469dbae397a","addr":"0103fbf9c8f122fd4ac6635f9178154d66b619ad"},{"mnemonic":"option faculty depart orchard foam orient seminar detail castle warm pink pen","master":"90dc715ea43f91c4777eda4e9c1dfc9f909c2cc811b55575410d21c0a9fddf4d","seed":"94c306f3e3aa6e991b0f9a8d42af67d058bd2ef0ee233467ba0d23936bb0e982029a887e6b1f9bb9e537ace50e2235a9976dd79b03555cad90da5e73aa0516ea","priv":"ff6cdb1cd48968c64608ac08be92e28f9808fbaccda86c1f5fd6d905d49dcb5e","pub":"035162c7e9506539401c3a0c181643ca621f5abda005f6aa14792fbaf44b862edb","addr":"d724d1f5b4a987109f0c84cda0ed290d88e7c668"},{"mnemonic":"jacket goat equal source proof congress potato solution rival lend finish bulk","master":"cdef2991efb462f091fd3c4e092f8926a4f5e18d6013c5545224d3ecd8e61821","seed":"01e84e54b7faf2374a4b4bb4e56f07d8b13f0dbb0191c23fd41b4520c8123f26b526a463404ce264283c0f3d41c5927681b6fa388d9a91274fd693fa265fab69","priv":"feebee90172106d859d545187adc06732e188580754c96311d9acd825c1ec9f4","pub":"0305697df9f3fb6796d40145316d8f90ded12e8ca18a5956651ee96ab26e69001d","addr":"d0955fef013a29bc7666f1a4696eed57441e2633"},{"mnemonic":"canoe tiny raw account weasel fork still mechanic cricket address squirrel void","master":"9382c4fa09665993b8803f3cc92913c5564be40b63b1c19c81f8f9dd415ba83a","seed":"5c12270e9fa3ca2a008729b1d5fc1a8dfd52dcc6461969ae71d2f3fe04a7c59dae4faec17f84567afd7bab3c5934382ef3d8bc6dd6879fd3af22bbf30fa84486","priv":"9f1d4cffae3c7ce9fce5f987e1439167273c83b6b2dacf1a11ed66c6053c2091","pub":"030a2c97fc8aa57c7fcf7d21c29fbe00ca0866e58f64fa56a85cba811445e0ff78","addr":"48b6bf075dffc6f03e77c67b3f2f573cad8e28e9"},{"mnemonic":"topple recipe surround useless elephant fan gentle wall since street enough harvest","master":"353c700ba61c0b56bd7a3a65d29d53e17bf99abeec68fb79c747ab006592c331","seed":"9fcd29b6b00decb8c8e2a14d5695941854cb391bc25351d7030587a09f64e92bb409c4bb7429329504c19c7619212c731216fd5568dad8e2a1330fbe6efebc7f","priv":"c900c7134a5b92a2a0d3bb0c117c08dbd67f47f7562cf330d619aa3c64b7ab6e","pub":"03e60ac1d0a9ea441a821a780d894ccae6ffacc207ab39ff905122d435acb17a31","addr":"4202687424a7c883cb1dd96353e7dc4697f35f3d"},{"mnemonic":"any myself dizzy magnet hand drift garbage reopen fiber great stuff burger","master":"74aeb0c2e7a7655668238f6a090ce3657def8df96d7af744ddc52d4900451a6e","seed":"0e0a18cbadc5ab76ef4194f7eb069f266ae34c854933b3fa9603b4fa39dedcf219d73e3b283e08a067fc994d46bc59e1c42c18a6a5609111b8fa690edbcf5d01","priv":"f426009813fdcee2b4cd38966e6214f9559426705621ca8b862d2a4cacbbcd4b","pub":"03b75491e3a05b32aff6972e720bd694ef496f6a753ae309cabf4e9b5adc2fa6f9","addr":"5e8c4290a5ab9cb6af1addd261ef37ebd0e6bdf5"},{"mnemonic":"spirit draft dilemma cause main admit thank slide barely diary humble enroll","master":"cd538c907349401ba6605eb1ca7923df44a30a049d5cb9d5a42f0f66a5cc5f29","seed":"baab841c07bf90c8b1bb82c56e355fd6de5a2c93e86f0f804a897ff9c391712d2ec5281582ec15337aadf1f0e835a8c98c42e86a4869e0e1ec47c063fd19f04d","priv":"cacbe0003d96c8263f09f328663ab1b5c74cd6635504b778ebf2d7d30dbe524c","pub":"03e71d9a3ca15f3d481ceeccafe14e6ce1214cf854aa245bdbe28e2b27d2d40353","addr":"f4b073ca68bc00077027a2793e7d6a24dc4b9434"},{"mnemonic":"state subway clip baby novel broken stand soldier among fringe track wrap","master":"0fc4edec9e5891d61e74dd1ee6b52f9601010cbf2bb8949c1d38339ec428bc88","seed":"46ff0c2553e5494666b6de0fd8fe734a8bf523bf6953dbe8622c66c7e9645670624f85a3ef2e9d090e9b153cb5923460cc1975c481a5c2868e51cddd15a9ca35","priv":"4f92a517fe46051132e74178a69f94a2dcd9a1120a54e09188e7d243bc97db67","pub":"034c0b78b452dd0fe61464dd0a44facac7ba28f126fc2a60b82f82efb8cd153349","addr":"2da2b5a6ccff13b5281582aec90f4c9ef28293b2"},{"mnemonic":"nation shuffle siege easy birth motor also family infant siren upon warrior","master":"506af6e687482c47562e38ac6a41e46e2291d777fa0f7abe53ab698065f03f17","seed":"6a4cfce60d546e03f17f6d977ce6d9dec6f4cf8b6a85dfa3070a34ceaca022c5ca4c6f187f1c23d720078c41d540fd04c56bd5061efd027eafa9dd8e650e745a","priv":"b9354ed6da16a0cc9b4404d3226de88048b546f5a01375466aae09c53af3cbf6","pub":"034c3ef56d2471b16f17ecc3e1d8695e0b44057fc8ccf76625a271487781c735ef","addr":"41b9aff0432990ba791b76ebc13af27c634d4a51"},{"mnemonic":"snake manage joy opera creek dwarf wreck merge oval rule elite coin","master":"02a8c9db54ea6d54186726806f81935dcbf6b5fcb9e91d03ad618fbc9f9d3879","seed":"7d6db7e19c66ac1f54395a5a4f7d878e19c24e0cb720ab2a146e2502b4c6832efca2edc2d3f1351cdeefb53a53d66fe64455790fb687234381c017fcbf692265","priv":"76d273285aceb1d4686167749496ae591df991af93a8c29bd627747bb2dd811a","pub":"0208492167c3478e65f8a31f051961d2ac809faf7777dfa7296c54cc3639de71ff","addr":"b18dde1cccf8095ae14353ff4ea995b5beb01dc5"},{"mnemonic":"edge aspect sleep design jelly vapor car blame dad pizza own possible","master":"7d938db55ab464a9ca1e9bf65fb4de0e25addf0ee2e0faff2fcdccaf209de40e","seed":"2d2530b934297fdab1c193d6aa9b93eaa1ea353e776a8b89118b31273f93c2ae78d7b98f02ce1cdfb8465fec0a97b29b563764409813bb4b893a3683dc9d9bba","priv":"c183cb66c406d72e64eee84dcf330e61514028a82d56c56490c4aa09e26dd987","pub":"03e7b33c7123aea9ee99d349eec2603ec7c32c2863034fcb87df8399b73885c97a","addr":"2e8c251e27ee90d6b8f05fdb2c7c51f92b277f1b"},{"mnemonic":"cancel confirm rent key glow confirm indoor chaos flag curtain indoor float","master":"0b49f5cae01e50cc4c05bc466ad91d84ea13896d93d468f951666726de9ccf1a","seed":"aa4561254b44e01ec6b00048e4346754b6626000cfe8e566180a99cdf8739c0c76e16729ee4c73b055e7c59f5ad30abed0ecbc1499fed87ee75cf0cc89f9a087","priv":"7c4e98bcc55251dee796fe3960a8b842322c51da57fe5cbbccb997714392016b","pub":"02ffec93ac53e470bbdc2dfa89c2389a1db404ae6e57e2586b5e638e1397a85f00","addr":"c69d4ef8ebc35e8a418b00c7263295052191763c"},{"mnemonic":"become search judge nation inherit short history resist luxury moon garlic protect","master":"72a0a669e55a3058f1d20be19571673ad281e965667c6bb7afe83e3e89f0f30b","seed":"75518eca5861396c14bce066dadee8eb5f9a74e7099cde11cc9b0f1cb1fab1df87b5fbdfb675761868c81dc7dfc805bd2e425678b0a562447a6684160eaa6264","priv":"276b9a47745eb9266100e62f8ed8f8fa2ee3e42e36ef8e010109acbfb667c1ea","pub":"03a596424477e9bd2500b20cbd0290feb0d30b755562561c52973edf826bae3324","addr":"933df39b013756091a3455104d61244fd16085eb"},{"mnemonic":"profit execute broom clever wing noise crew purity steak assume april leaf","master":"bc7e3bda0564fd300d6f0033fd13d75f7bec7464ef692bc96f83e7ee9427c6ff","seed":"353344a63ebd9a6e78ded4cbf52a5f29a64cb7c1d90b001d764f5f4fa419f569181c07f8bcca22117c970f65d6f9c06b44e934ad21257e0f1bb500f8a26db987","priv":"9120e0b2f502a6b5b5804fb4eece7754ed92a59fe482a7a1b4190213dfb60457","pub":"025f809c0f6a054c4b875c7bce8791f23cc9daa6a85558d6cd48818f29d6b978aa","addr":"f25a6479cee5506bb53b4b06fb326a508ca77abf"},{"mnemonic":"menu library ten glass coral taxi prevent learn pelican garden magic busy","master":"7f4687dad9ba781a99edc31d78a2c68875f40afced8adc8a66d55efd3f68c169","seed":"607827fdd6fb239229b116e73be3993a6596a09cabfd19dfb9b03482d052568c5443f4572393b0e9d460a05832c5fc41e811311d9bb501c43ec75e234c61785d","priv":"5605ca7fee44c088165aa3474327c53dcc13ffc73d8b4787a8b0dcdcd7fdbf3d","pub":"024d754ca81f064cf6dae96fd1344cab8e917e46ec639f677eea33a21bb34462c9","addr":"663ae3370a5b68058dfb1b2efa62f4a2222b3a89"},{"mnemonic":"green useful pair bulk excuse mixed train talk genre inspire much eyebrow","master":"318169a8d80848ddaaff93bd0fc68b1282aa8f5e6f058044de6ff82c62446005","seed":"2095e4cf4ec5ea142d9300cf431e47c6ad401ab1693a6518d5cf7950d1d5d7e0c6feede5a29b3721924074ccb527cb962ddc5745b46b794dddb4ccfdf31ff1fc","priv":"e9c336d9e59b1f4c822899ec39d256174521097060db24f305e3d4c3b12c35c4","pub":"03f44d7d4269f3aa14466483d80ad483af1307387170f563222e843c554f215b00","addr":"359955417cbda69e538cc001d5aca0bc59a077f2"},{"mnemonic":"follow half desert universe canal guide pony two fuel nuclear pull tag","master":"1f3ffb60e2293ecf146f414b28ca6a81dc6768c34450f2907eeca2851ebd92b8","seed":"e692e2810049aeeb25672c3d07a411940a7a7308e9a2fed2a67210d14dbc1de2258edba62437cdef1f913cbc65cc8040bd52f601c2edc51cc7d4744dc1781147","priv":"3534e3fc0a973dc314ff3610ff02c07a1a9e5f2a2003f8ce754c691acf172565","pub":"03e7f0b65a215a8d78831f05f10db86874dd0d900059bcbd64d83d08b05d8a5f7a","addr":"dd74030f9d82c0c40d2798e731b7c5eec61a0213"},{"mnemonic":"enjoy chief later rebel avoid emotion kid reward find patrol leopard destroy","master":"0c8eadc9ddd4cfe9b2c1759ed1372c513bd5226c1aa4afea02c8273d226182c5","seed":"d522815571acf5953d4bf6894c9bb5274e876a5ecb13310dc3db73f2d55544174d744cbc7d63a6ea07c8b7bf8bdcbcfe161ac57dc0ee488ed9fbe0d21a070d95","priv":"92e9da2b0ffdfca29c83f64a685f6f512eb291b5b130c4c5c506bf713016859e","pub":"036161fd5b9ff9bafb22e61860d1d3130e007839939eb3f609352bc73376552d17","addr":"015b10da504e82eaa290f2f5057a2581db032f51"},{"mnemonic":"giggle medal hat isolate congress else guitar below chase federal absent photo","master":"eb8a28df4360243f9dac597fa92de914aae4133af8f3a18c2506f2fcdaf4945b","seed":"95e8d77d1709418b4ac0b8cbafa302e2019644eedfbe52233ba988b55f5451781583ecaa8b1be51ae18e17ee5bbb35d3826302701588555dfc8c851844161acc","priv":"35da7e9dd8200ed89f461c484e63ff3ab68a9b1cb162bbc3331394f4f2ab8793","pub":"02bb24e03a89e6a6a7d318effa8ab645c46e5dcc4f25c3e4d75308144b5d2a29c2","addr":"2c271833daadd196147eea05df28dc41314a27ff"},{"mnemonic":"use protect bag nut fault off absurd involve ramp cereal symptom biology","master":"0f5a77192d1a941ac59a41773ea7d6b4e87295f4f82fb0f43c5f12d605afd56f","seed":"7d74703c2442bef350254d3dce2303a8a56fe4c96e4ff80ed57756dd7b8266e566ea2cbc3abba9c724deb9c45fe4cbd6a8c8bcc4bcfea2665e5193b781aea933","priv":"18c64949d8fb6fd392fb4846c119eb71a6021cc1c22991706fb776e8843a381b","pub":"02b94512126ed2d6412873f61bf16592f02df176cdd4c29fcd70085fe3d03127f9","addr":"15e94aeca2bbd591e337d57152663e25bc094747"},{"mnemonic":"tool twist jaguar excite borrow social sustain normal echo fork alley hybrid","master":"d6c9dbbbe44afa97a5f6365066a11a8fff48793d4c6720ecc419bfbb81329202","seed":"164785fe64846a802a9c134d094447035eaaa6cef2eec9d5fea9aa74d333ab31433c7cfe4b712b6a3b04048d239101a8dae5cb4ed37699658725bc2186ffbe41","priv":"cc5c6aba1301195af2626001e3d19660043377c75e7990063aa45ebbd30ab266","pub":"02ed0554dd8861043aab2105d7dbc83809193c59952e829421f7b9b6e9e56d6f0e","addr":"7db5745b47c147e40ea9fa2cf54488974d0bbc4b"},{"mnemonic":"approve bright target voice relax control knife again special future anchor crystal","master":"332ed66acc5c24c6a19c450775329c946197872435d77b0ea594d4632adb04eb","seed":"da2c0f3433cdb37ff151465470bad3b227114c46ddb025542133b4c10d942bce6cd34726c85e638fa82c4295d8fe93959069d35253ee528fb1724be1d95447f1","priv":"41a2cdb57b5cf352256bf9c2b155016160c7eeeaaa5a3ab2f06cd1df3e4bd695","pub":"02e76d02ff3fc76c21a995add6962e08bddec4abe23994668770d6cfd02cb82f42","addr":"39dcdc76bbd5c2ad8821cc5df8e816c7293a82b3"},{"mnemonic":"like wet pig pause steak name tornado else limb february secret subject","master":"e7dea9fa8e88520065302d4227d84a3d4226aac4b7c04bc78dc7e68efed73002","seed":"3926c7749d953ea66414c369fbe3f26a7a3f442ca98a277dfb362eb74432cbee32e44a6174f1e3fd16aead63e798c894d88ef260747de219c1e8631d800c13c1","priv":"804cc7215bdd8073b9c7f8e1ea2648724ec3e2593f1c2213875b6e4022513ae7","pub":"02770a43f589045b52ee29065b2cbae37ff65a0ace98c88531b4cf88c94c3f977d","addr":"cf82c749e61e9961ab72a76cbd3f71e0c5a46221"},{"mnemonic":"memory core ice box board flee ivory apology acid warm sugar resist","master":"4ae1d18a2c3cdc0c4b383d20846866f1a2ecb799e7d2c5c125e81c30856a2bfd","seed":"5922aa04496cda9a17e2f474805f095fa2bb70cce0857dcf92acc7737af2978145cdad0aefcf201fcb5aa2666a136b2eeffddb5476d9d49c0cf0d76d14bb332b","priv":"fde667c98a06017967b9169dc380a7393797486d07bba6575629f0661465a67a","pub":"03f8e990fabeba27ea70082b69628f95e5b86cedc033578426995bc1358949466c","addr":"efcaf3eebd6ec30c44fef92eb59327758eee3334"},{"mnemonic":"vintage rocket today version chair avoid mean play decade sport frequent magnet","master":"d167f9af9105ff115790c4d31ca48e4ce5cb3b571b4596b8ee78be5a6290e3c8","seed":"af58c0eb0e62201b926ab4c04d67b942f6ff40147ccdccc02a3df295fe69ca661b2a23fd2cc0f9148c4e92165ca9725014ff0abe5cb7acaeb513cdda359dced1","priv":"33b248b4a292ff6f26455859924eeb646290cd54a2cf587c5527e2f432fcd6d4","pub":"039802bdb2bedaabe4201344c1e9276d1981f403151e2cf179e4cd13861a54d568","addr":"c9ed9bc2778a33e5712b90843f1b0f0252c5c3d6"},{"mnemonic":"crash lazy cruel match youth note deal rack gym robot work pioneer","master":"13a82f0a499ea45154151ad95d52c3f15d84436c21d734b5ea105c902f85559c","seed":"c10e386ea97bef67bd97e59c5da37442ffc968893fb80ade82097b87a76dec5ae128962a4d69737a31eba4f1606e030d4c85df6733dcbb03e209a4b7931660c2","priv":"eac145103c713225ce05ffb862cb921797f9f88d48628321162798117e37494d","pub":"0260d3fc9e0ef5e8c38e3de4da944d59cc575aa530dce9fe8d95fb8eb68d6a4bd6","addr":"07aa44afcad33d8abe6e83da72d6d556a3720924"},{"mnemonic":"distance desert squeeze eyebrow episode enough sorry gym still label mansion thunder","master":"0f686b29302ac0d5532794598b98cfba275e4fa3dd0bef15c0b0866bfa0c9c0c","seed":"9fb57b9bb255323d11b7479bc34dc706e42e6ae8bb3f3af212b0807ebc9fe56a90a36c92bd17eda435fd0ce87a0465cd10a371b44dfb2e1531c14c29cf8ba466","priv":"7a140972fd7e2499dab8e22a52b0cf79c33ef58d1c5df578e30515e627f044a7","pub":"02332ac4729e52ba3ff4344ca262726bb58595670057aa967451302bd19579e8e7","addr":"f7c0cab3704f9ba669e318d17e33b1b5a7b3ac3f"},{"mnemonic":"zebra useless blue insect radar century lumber clock daughter slight quote stadium","master":"1168c3de22b717bd3e840b4ac6334ea707764d25bbf7ac14cd5d63ab127fe2a5","seed":"df9f562a972569f8dde2ba35e53c97c536ca3bffbbdc990df8cdbca812747887904a4f983d661035de0b3a85677d0092edad32ef528c926bf31541ba63b8e019","priv":"282da5f2191001a4bdcdccbd0000317ce62b09c0a48626b4fc2b45da6d7873be","pub":"02790696da42d2b21cb031e9b77bf855e2f5a214f80cd05618181433eec02fefb7","addr":"68f483b9d998b9250d320c43278e423d0394e8cc"},{"mnemonic":"laptop pepper arrest tribe glad keep behind gravity ketchup scrub bottom parade","master":"06a978fb60c517a506d2d8fa17956f144d1a5d57c0c9567320d1b21b8e7871eb","seed":"38c05886932cf2bca3cb7732e92b4086ca0575db2deaa241a0c9295eb79d50765a4bd92a03b76255144f71bf6f197c4b5eb6e3de8dd6e6ddf6d15ad18c90de35","priv":"62c37a4349e0d4edeb293e50adfac737ce73e3e0370439c561d117bd4ef23f19","pub":"027d978c9355669fab1ac4db17cf12a103f7501ca2011e022110d5b4398810039a","addr":"6e0cc4997d42b970855685f8c9a196b97b2d5ace"},{"mnemonic":"alpha slogan usage lemon cancel cruise rice crazy laptop donate city fade","master":"e3bed02bc801909cdfb1c65b6648f4df19b8927199e3d0f069f6713b13f10123","seed":"9b73467192fc857c552d60dc0223e3c4b604cb1cd50adcb61c9aa723d245e3ad44cba7f99f0f24fddd0c78b1bea41a86e682c9c482b115d575b9e3aa27f5650b","priv":"7b8d2c22c398e4a046da94656232cc75cfd6fc0e0f8191b673414383901b724c","pub":"0279989cb1f22fc08f871d023632a379d038bd9fa902a6e46f8bf0a780637b4efa","addr":"a4d3a5579aecfd9790dafc6b4e89972933c46d1e"},{"mnemonic":"chief runway cloth craft depth firm task ready credit multiply program smart","master":"d5d076659b0e0bb061736956cef361aa1a6a0ad6a337a6ccbf4b76a40184f405","seed":"8e60f22168de4f2a6c9db805a6485379d2facd7c99dc36981d0e209746766233d5d5012b03f8556195737bd71b88fc54eaea0f68e4fae4afc19c133f2ca5fba8","priv":"adee70b6b1dfc264606e0b1c848f7b5deb46de4af91c5eea9eac962dd085bb3c","pub":"0226458b01eb1e4f0d7901841662b2046f17e0945230a3b1b2d8a65aaf5ebdbe8c","addr":"c9d9042f15ecfb29595ed4769b1c858d1f627468"},{"mnemonic":"invest glory debris naive pill detail sister cattle physical favorite squeeze rice","master":"2ffaac06321f9aa3783155de5197448783583c027d8aa9d9b787d2a07b7a4c2a","seed":"3016cd4934eca835d3246cd7c05ff35a0ca5e3e0c4b74bc70aa31582a6da334c0f7e91458bc049ba3469a8aa7f216d27d44ec8ca4cc5f376ea366a38106c7fab","priv":"cfa4b9f12156ae24e632f318be54072149006db7a4a611403afa97c978351900","pub":"029e3e54ae265087ab8066bbb7e935af291b3ef5120b00f44019d9dfccec8a4e9b","addr":"3de09d0c1ee046365da74449b6c98ce3205e20e7"},{"mnemonic":"private alcohol loyal depend force sand twist couch beach report miracle abuse","master":"8354e18ddc5b38a6e26f9cfefbfd4b27ce3f65c91174c88143d947104ba91faa","seed":"507df1232f5cddcbee60de019cdba03e9337896ae2fa0b26855d48c34a9a2cdd1e93f2b66e965cf7666bf7c7ad11f00b1ff764b675a5c3df8a1a17b253cb9e54","priv":"d486cc9a23d56e1dd8d865ba042aa5cb9f8ba06107988e1a0d999b14da3b667b","pub":"03b75ef54ae8faa3f3565fd6301ba7a70114ddd184eefc74e716fa2e3c2df6c2af","addr":"2c82b93644c227bc66fc06c922ec1566c3e11c9f"},{"mnemonic":"memory achieve vault hip prevent category cactus aware venue dutch raccoon fresh","master":"16bffabbf3a08959dc9c1780781133e6aa096cef9d9542606c52e8ca2ea0230b","seed":"a4824f3efa0c730e3669acb08b1cadc25f3f63943983bc4f4f1505cba5c85959ec16c2cab98008d10e22f3ed6239e3182bd9b603ae1536755d222fc60f91419e","priv":"7c2b66b79e2e99ef0f794147aa93d3da8e62ebab7ebaad7813b586ea5db28f9e","pub":"03298a67eb59a27d636c2aff41d73ec658c87b136ea53a534ace18fabb76486dd7","addr":"89d5007339cb57fdb72ec629027583b8f3aaa5da"},{"mnemonic":"alien floor comfort six demand helmet light actor distance success buddy burden","master":"36ed5350c3672be815eb365f61ef0d0d42870b178aa34fa5c5b7397cbb7ddcf9","seed":"ff46b78794944b4372affad3f096339f8d9c03631335d9eaf4e4fe68a8fd9d58a6d6f37ba31cc06bf57c5b66aaad6ba64ed28ae4188195227fa07bfa587f2f1e","priv":"3bb1328f115390ade3c08de4f9672ae96bc3d5b783bd9d26d7e4ec12d5818b8f","pub":"02b37bccbe6c7173937b3af482d4a92280b670d715e2619fb1fc906973bcdd4d7e","addr":"935788847e1517096b9f31ccc2ac48c2e5a738ec"},{"mnemonic":"soul upgrade rebel wash hour gain lady side own double immense merry","master":"039c6373307aad9366dbaf9bc17e70ec1b5fedbe382b9bddc55ff606baadc0ae","seed":"37f9cc349c21182a3b34c66ae099de84bdcf30ed20160c7251f43f831279834dccb95745207defbae856c0a38dda3d7bb251b97cd2150c155ec64c680c82ba73","priv":"377f589beeb549285eee37d34e5ca85f4e00af8483027afb655e47ae05d1089d","pub":"0266f715310d9fee40c5c95da1b6a9a9aa51648df99326e29399b10e9cbcc51f7e","addr":"89a2ac362b8804981ecb6043bbea65587c997f97"},{"mnemonic":"stove pyramid vintage defy belt high have leave comic brass online caught","master":"eb9be6fc059732dd9eff612f2e4ed7121093f07889b87e8c66e103b83724e1f1","seed":"2537a9ac9dfe5c31c0f40c69c9fbf6a8ea186d2cd6c6d2134aea2f3ec2f28f5339fe623ff593da08857ee84193c54e204049009f8c86ded026a4cdca633b2b9a","priv":"a8f4ea6ba49c421a7d310b83bec05902cf2f2629a3845e390261c3917af3a17f","pub":"038a6d8d8947723f80f65dee0ef8579dea5678b67bd258ca591d0ce5d2ec060bb6","addr":"38d61629cc3e3ce7a614825cefb125ddec897b59"},{"mnemonic":"uncle seat rate acid ketchup frame marble limit demand exile wealth dinner","master":"fb1b8ac2f5bb56231fc93615bd8e25720818819d3df4ffcaf63dba0e7e7a0815","seed":"8e0bad11dc7784f19715ab90e8846e84155680027997fa0314fe32efdb3c026ae2918740d362744dff754e75b1d54050f5f02237cc4e15aad165ba10cc7b046f","priv":"cd20e39179c66285edeb6df646de54f3510f166bc1821349d779fcc103f13839","pub":"031a9529a2b5da261bb540f43b860b540490262b10aa09d419dc3b96d2e9aacc75","addr":"d1b6e238bc4a7e63e0a15f034deaf1a5b5161928"},{"mnemonic":"human benefit idea stone hospital misery warfare door goose unhappy crowd stadium","master":"b8b5781ae12ea6db767cc01d644cc52179363b72a7b67ee8d7d20fe8ffe4f41f","seed":"fc3f6e420f688e8553a2cf8d3a6a7198c5523aa6e3b00b3e1e4bc352288f0390951bcf698bafc12334522e04979fbcfb36f12fa789a85dada9909304de559193","priv":"ca41478acdd4f0413a843cec85b2abff69aa53b4f900da10918810b89127faa9","pub":"026096644513086624a2ba26daf7da0e4f5c7455bf852336416737fb72dc1137fc","addr":"e57448e2edf9d63574db45ae06510a521bd80522"},{"mnemonic":"violin cave ask subway session gaze settle pledge decorate alley swing evidence","master":"4c099f1692bd7137bf8b50e51d2f6fef0236f88bacfc4c87f83fcdd43a3a1aa8","seed":"2c3cb4cd88a4de52badeb41b1e3e1d61daf61369d5badc36601c4baad611eec459a0a1edb4046cc21ff50f396688ba6bd37fedf24b17ae447b6f7ce4b0a7e81e","priv":"5f1d6278c5d244334eb10d71e4e642017c7d3d63076507b7efc9c63c8c7e5df6","pub":"02c26860be7973c41ef183ad6ffb901d07bac225b5fae444df8abdc605c7a1efa0","addr":"fa055b86c6a1da4666ea4345e9d98ea32198805b"},{"mnemonic":"dance hip come square bread reduce ask riot shift twenty scrub derive","master":"964f2b5fb6c3f11f33ee1bc9db915d820834cb1ddf9cd35c17effe93ab3e3e14","seed":"bd4b3ee7b0042661b560cf39f8a9f8fdb70bb75c7482b09b296cf660e2b6360b52263cc38a1c546d0f935f0a156a36089975a7fd5a65ddbc960e4b6418e1d337","priv":"6f9b31f5247941f3a0e3954b05f77d68c469aaf25f0755293b1fdb17bcba6478","pub":"03a3cffd72d5e6360090e4a0bfc8e1c691add6690614ee5fcc7867780d686259de","addr":"95ed911acfc3d1332ecd9c8b93a4372a27911cb2"},{"mnemonic":"excess route notice shadow post business cram kind ripple odor enhance future","master":"ab1d6e993bb9b533e854f15591af9e8a74bd29d000d5c8e77b98e3e34e96fcd9","seed":"4ab45c5fa427c0c81853c3b5c2754ab1f54873b0bba3710204fe40ac69c13d21ae011fe9c835566db313947749dba53496f84709b71f4dba08a7db209922ee4a","priv":"98e0136920ca7d3844e7fe1cff54db7229be2412de8de831b94235e8ddc2696f","pub":"03714b295b752de7f1cefd195578fa7257d5dd8b47a39e584fc4d2637a8f730d1c","addr":"9019db50e3ad4d56ece94e7d5067b27a33400a4e"},{"mnemonic":"flag maid oil survey first force grant equal brick dog where strike","master":"85c3230463b78c924cb57ca637b5af3f5910d962861ead4b16af5de1b4be274b","seed":"6203eede1ed8164b3ab32049def751b55d82ba6807d97b3eb094b4e6327ce732a54de31a9fc6178266a4fa7e6452b004d89875694ec13ad05475d7ad86ec3241","priv":"1aff198e964909f87d5b15c1693e5d191b9444109a7ea4bb58952752623e77f2","pub":"03921265a585b1ec932828f58cbaea6ae709c7f2af0691ba3f2f0636286119bcca","addr":"7f38e5412e9011a5ca91fdae448bb8b15a6bc4bc"},{"mnemonic":"jaguar panic thought mimic voyage able inch pole vacuum twist velvet pulse","master":"f7ded49975e280cc791687730225a70a89c79f5245ca72a7e538295aac1ac710","seed":"52f058e84e0809ac44c37485ce9da088c1617f05e92553a073378a0a0b3c9cc95aabb6d1dd2c99d084b03afb98024f9381d958f6ee5f516baef2db97c493009c","priv":"615bd1f706f7a88d9816200f4c3085ee2c748f9a42b25b444393f8cf2b46191c","pub":"02635816dcc956bbd8d9d2ebe94fb117ca20907a238c99245a9635287404d30e78","addr":"78105acfd135889bff6f0f70c92c38e0eaad72dd"},{"mnemonic":"pond stairs still avocado rapid peasant direct debris spice cupboard pledge budget","master":"6b5a25d678b4fb67cfa80ca3ab21cd6bd554e5434c4fd362ddb01cb46bdbaff1","seed":"69d5e57322a46cecbfe1f895c1b22e9bf17d418a06b73d49e3fc83012ca2649818bce2310f1b195c5b4873d31d6e797c5edecb8f30377f5e638ba1b4ce2f3823","priv":"9aea611859425145441b6455a0ee206327c2de06e2d26974197873f2ae9366fb","pub":"0236498052412d5c5dc3ef0d195a2a537359fc44246fd9c8fb39478caf29e668cf","addr":"faeac1dc66f281714303d637666c09606504a227"},{"mnemonic":"december cram web moral spell comic tag lawn since helmet moment act","master":"ee67281243cf2f77274bdc4b91a2ff1e660197bbca2fb42d5aee60e6f55ab4ba","seed":"8052120f630a33ce44aba16f1807236b1330ffa6170f985c630532fdd2713aef0e1d681699c4f67a9b9a72fb0432335c243828bea29489c92d1b01d016257ef0","priv":"a98bf3a99fff927ec2b0f208bd8a3a586ccc2571fc6333c57f2f1b7c22d2c8f8","pub":"02743cd05cb536e2384da4e0f110fa4f807abdba3e5e25e426e32fc4b5c65f761e","addr":"a1f0b4bba0be62c6b2497826612303892ed77b05"},{"mnemonic":"basket tool pink steak antenna process accuse brown walk pretty only check","master":"ce30c7daae3e0a5293ece548d66f07852003afcc80874474f5a94eac4a00c928","seed":"9572350a5a22b4c0f95fb2ce61c1f5e5846a3c2fd6e4cdfb2aba0d05e04e5b67f0fb394521b73836bcd4555cdda44acf0ab7ba43b475795868a6056295967822","priv":"edcff07e74dc83738075605d76a0c6923dc475ab122da2789b5a195a421c354d","pub":"02c03e024e6f53a1676dccd7850cbb2bc1f6a9a85b1da7cf0ecbf1c653a60dae1e","addr":"ac3c8907bc31fe66155a47a37306ff7b75905133"},{"mnemonic":"since equal mobile pond island before crew boat clean behave climb good","master":"1d1eca07fe5058a9dd7b26d1afbf2f4f71acf1420dc4ce9d2e3959734c442f36","seed":"4167279cfd447453ee7f46328bc40b4961f814229cd72762af278cf56a8efb18211420cdba43ccb06dfdb207716390df9205fa880cc647bb48455f437ec8e4da","priv":"60622d64880831974cf62d8f65be9e4d89e6579e6e0f1e5351a10b7574f3615a","pub":"03ba031ce6dd8976cfb72a2121165ea4bc0a8cdb14082504a05a917de09bccda29","addr":"50203affa88d87f3b104e237058807366f33c1f2"},{"mnemonic":"inspire immune poet penalty remind mule crawl drill rare fork track creek","master":"7c581d1907fb46fc46e6e9b81d83fbae02a75a2ee50a8d723e24700b530ce917","seed":"3822ac35fca2e3b5904e3284deb5c178b7c64ada6d7dd31347ea302e76ecb46d4bf926158016b76106ca61ae068fdc594808a56aae5e39da7893592310c33d2f","priv":"6f87d364a299b42c40a641d121a255228b62884d6f2d09068a384f7c6b515831","pub":"03f217a49a2068b2807a4f0500a08dbc7bcba6ffd60b0fe3e4f381a089b74506f5","addr":"c4a20e80863522069f8059e91bb1a162a7af7356"},{"mnemonic":"inquiry exile okay attend enroll author forget essence script conduct apology rather","master":"609da212416c631e8701b1fcfda5c412e0758270daa7bc796ac1492045a93a5c","seed":"4a75975cb2852f8dea2ef90535307e0a0063985a1c2347db1edc25bb96dffbd880ae88e8e5a21e91b6c26cdc98673effdf0ca84f416a45950cbb0ec74cb7fbed","priv":"c2e4db33ed61ed9f7a2b1452515b971a1bb20dce3b07efeb9437fe6ed481c9b8","pub":"03fb6407710ca5408d137faa85f2837879c4b0f4df59182a3d5f002e49c34c3bc3","addr":"c5217c9cd9af8ceff8235b2d127ef1cea8e94e35"},{"mnemonic":"entire diary route emerge moment only lounge situate expose hurry hip mosquito","master":"a919ae0bb832affae8e5269efc47936b6bf3e487740f8bbd2c286866a2224762","seed":"e97e0456756e343a7d56b1edf7468419f8b431c6c850299b382d3d957fff7c48f86114eb5640aee13d245c2a34d390850ec43c427bfec555d40a489397376340","priv":"eff22ef90183b533c5267d9c19f29f7a6fc2c44b45dcfd4b440181b977087585","pub":"030cb4259aefba8429f5e3ab0009e080674e887748e51ba2e0a055d2df3bc17589","addr":"d5db282d076f9d474651970abe5d2e3fece873ed"},{"mnemonic":"ginger glad purity aware siege tornado seek orbit sniff spawn process surround","master":"5498d52a17868a0fb5f1d2416277fa1a4220ac3a498f18f15e750d1140c57f86","seed":"3674479b527c4f27b578f0609f800de86a46591eccef6d40d3ac4436ac8c92ff12659e1e404af552f1058e9f17e90efc160903fd985f5b8069c66c9f6708abc0","priv":"5fcf38e09f4a3665256644715fd606ab60d9cd62f4c22962ec94b6fc5fccdfc2","pub":"03da1b1b03fde4241b05adc19515eda3ea96febdd5ea0e8f82dcc7cd98f1b74029","addr":"1186fc924724531d8ccc9f9ffd49701e62056c52"},{"mnemonic":"laundry reform post update crime page snack another boil pet cement primary","master":"3b1c3ee0d63328bab055d691bd29179ce5abb933759fcf83912adb41ff1bd9c9","seed":"60771d2e964301990d7ce6de87becd62e65852a4da9b819ce3fe28d72ab0e4619445d934172c1fc9361d2176f4ccc8d5b9175f4e933fd5e9681d8e8b177fadf6","priv":"755dcf792c67ba8a9d8b0694d21fbd33c51fb7aea67f05d2c8b0f38093ffa7ef","pub":"037118c561ac7773ab212b899b57f5527b77577a39a4f413232c8e7c6a33f9091a","addr":"bc2e19256932b58fdbbe5ad809e30a3ab2b2685a"},{"mnemonic":"pool bean dilemma foster reveal renew exist bar sick spot bulb trim","master":"4d1399a0181de627ea555f388952dd5d2c7a7b83e1a618fe8b07b03c1bed18e3","seed":"d788888f57bc052bf0d35abf7be1175152aa607b901d1040f4a28c8cef343f0fed2031e3bc9e1eff77eeef4e024234466a55f70150388824d6fa10051133a464","priv":"00b7f71d77cf0d4e13e51403c92aa66ba543e9cfaecd810049d17794a4c0ded9","pub":"02319a6d654cb42a231f7d021e2cb7c9ea7624c37d6ee32b218d5ef79a31eaeb46","addr":"f6d78ff49d6f12b82e24bdd77bebb536566a39eb"},{"mnemonic":"poem leaf scrub bag bomb palace discover pear rhythm treat negative system","master":"4bbecc45fde87cb80a4cad7a4b08068265eb8c12d4ed36d1c9a9a7e5e73c39ac","seed":"efb6bca601760ffb2b183bd4cd2e84a864eda3bb4b8b1369095d3df69fa7ead0b8bfdf5a097f37bb4b1ccc452cb8935baa165f7ab039342af64e9e50bfd51b36","priv":"c4988f397df2821ee196f98e62e4a1542e53ca1e46f966a4d13c4e3e389d8937","pub":"038c8e4571f8f411827ba778340beb7bbc29fb47af998a852da29b4f1583d5c600","addr":"67b94e1d532cd8e42e5a74cbf20f7d079f42055f"},{"mnemonic":"punch twin village ostrich frame goose dance history valid mountain volume high","master":"f9ba8580f4d53e34d9bfd3b6a2e17c5d8987c879945df9bd20407d3f8144b108","seed":"07d40cd18ec6abbc351aa23172dfa6582ed83d5bb24d5cd830d7cefd23d8a2ea6272efc6686606e61507d5a793b7fa06f83bf73504a072e32a002750f5f240d0","priv":"10222b81cc386d25eaf5037fb8fbfa9c401c1d192fb715397f6636dd94e9db3d","pub":"038b04836ce19b454a0af260bc1271ec73f1a0998d8659e9cffe38fa5e4d696a77","addr":"55bd4a574aaa1be2c02aa2eb40254f8cdda7a682"},{"mnemonic":"ready embrace photo find orange curious essay pulse frozen earn wild travel","master":"361e9e44283fe7d3bab83395ecb8373dff5d0a4d60274695637cb02955523741","seed":"ab50c5ab74b1ebae85811108c372651ca8d275e7c2b5d0fec9f261966395482f311a76dd297f2d2997c6c59247807506ed20f524a32dff90637956cb7868aaed","priv":"1ffdff9fd05b67d22f10076595e0025800a8d60f022f2bd99ceeba93681372f4","pub":"03b168906d5b255a896509c8ecaac4a8141d22ebe005e6dfb2892f6f12970dba2f","addr":"a7d30e12ff906b2ca0c6df3fc68274e7e30725e1"},{"mnemonic":"pass paper cable blanket meadow talk govern admit busy base hold broccoli","master":"db0e45010140df4a4514284d7ba78ac7a5771ee15820856afb1d15a4e3b0af7a","seed":"521ec955279d92fae9dd8dd43162ee216798f4a0276a2c98b29dec8dec9bb26f17e6a49ce999ec55e061379166f25116c01b8cb48ded23c3b3087dbafbfc5371","priv":"b5bf00005304278d5e4aa792de142a6cb46bd6283ab02222de50cc2f01009e09","pub":"03c188a8581f09d9eb14252f8d1f5cebf1de8189526992889115c6edb1cd180090","addr":"0f8fe4fac4fd85d649d7e19d1773897aa6e75f43"},{"mnemonic":"weekend infant spin powder hurdle pupil disorder always excess unhappy price decide","master":"b1bec76f3cb15f82e5c9c65aa23d0871ec06a590a3823285a412ec9a243b1c1e","seed":"5a8d16dbd0586561cc81273ee320c6c3d51bd90bdf08119ec81596fcab24335193b33fdd621800daefb49e038ee079184e569b941ef5d839987dc1e24f578039","priv":"90ffc2ec625f528045a432ddae8d20017c9b1a883ed22ed403783e10801077e4","pub":"027d4213cf485f4eaf3ea06c61057f92ae8fde8362c3b2f4b167639b74153db673","addr":"c9b1073f122b5ebd155d4904cbc32da4281bed6d"},{"mnemonic":"agent seven dry cheese rhythm raise junior sorry spoil tag opera bench","master":"8cd8ddb8ad3f12fa347780c4614e38198a51c00bc61ecb572616382d6f8388ed","seed":"ad6641ad541b411261101e5f76036fcddd8af62de1966a3b9a1122edd1e6057e38fb5e129c86427a68590c87cf9410fc14ec08dff184742a54461c205018f43a","priv":"f15efc08c8a578f7035a672fb51c2f6929e169e5ff37802ae8b50f1664c025a4","pub":"039926cc43000431dab0f0f4818fa024ddcec0ffe9c483f8ec294cc863f5133574","addr":"89846353e3a3becad919620dae0a2d22d0533559"},{"mnemonic":"floor sting insane slice pistol blush follow muffin acid coral aim make","master":"f65fa0d49225f5f373eed6d7d6f9f8f73f80840c6027c3871645679e51f2dc81","seed":"8782d6395c27d8b9a3b0fe29e44093e5150c9b82bfcb6344e6134e954c1240cb33fe8c9489b3ad3117f5c112f02f0eecb0e30efa36db18b27003df5e542face0","priv":"de11f15f7cfb0038dc07ea2007019c17747e5138cd83b37ad30621c9f41b1799","pub":"02b662800bbc56c144f6b39773bfb4d496c9f1442900b59641aa94c6b50a783fa0","addr":"70b1ee56807b9191f77b1d18ddfd181677e91654"},{"mnemonic":"canal today stadium spell accuse cream chuckle method unfair regret sibling old","master":"90c0af3882fac84793812f44eacb1d4cf13b56863c70ccfd6866bbde1195036e","seed":"c1b4ea5bc074259d2f25ad7338b423c5ccd2083b60f0ecce88f7c5d4cb39806f2da873c05cd52729ee07512cba3af26f21354a3769350d5bdd10868ff46d8e28","priv":"9ff9156b1f137d20b486ea125515fd7a2f057145fa8313203606ead961ebed84","pub":"0225998b8535e9f2e269e86caeca1ed90a86414d8c449011ea2fd9a488b7097528","addr":"40f33af234da7de748b02a01687a5e60429ee07d"},{"mnemonic":"object sure already seat attitude great winner session cool addict direct popular","master":"86a35c7ab59d48a897f6b4a78221c8acd0850010a063ceb912488352fa19048f","seed":"fae4348ff7c42cb1ff8542bd19721823917037d1cb017ffaf64547be8ad4b296212d6e952b2af66db8541c7e881136aa76e17e4fed926064bd5edad8f25e0dcf","priv":"2df0f9c67615ca9370f8ab957db6ad6cbcff1b5353f745dd24125ad36d7c77c3","pub":"0367582dda754c5345514b2618d0844e83f8fb49ca39a70d00537c70c86b6519b9","addr":"128a4f8786a46bb7815e59abbcd85bffb526e953"},{"mnemonic":"sudden more spawn have pig observe embody title collect junior sing bronze","master":"c71aeb48c73d6ecef04597f248dfef9ebaab37e9df625a483db1e883a972a36f","seed":"eb1dcdc3ecd77652223ccccacb85a255f350028a843bed72ff96d4e3de5566f667af1d5fd48aed32d2e580f625bd258cdcf6760d1089ee3f9653375bb1139f9c","priv":"455da9b7df9d00ce53973439b23a26a75463c9ce0bdd73eb16a39e019d7786ae","pub":"0327c673e375a95e13ab6a940c18a35874331db2c0abb283736890b0ed1a09b79e","addr":"d173a47de381e714e3873d1e0ac05ef526b0eeec"},{"mnemonic":"world gown final mind dinosaur stamp unaware apology foot flavor hockey bamboo","master":"040827137019c4a9d29c1d65849cbac940ca0dcdac2ba8def0421c990c90e2e2","seed":"48c5532c17475f0a4d63d76daefe7cf21681b32cbbf4ad8cbb62b6fa872411fd2b8821f8f2ea97cd9004fe4585e5ecfa27ee6c46caab89145c3b0b4b7ef5c073","priv":"d66195156c08032f912a71128635b25750335aab186aec63ec9a83e9b24c55a6","pub":"022d8790106436a60a3b74d10fb07e06cb48b2b13ebfb81a608039d80e9d7c1e64","addr":"fa08eb0d89958302d67d4de8b99fe0c53ddebae7"},{"mnemonic":"bag bridge trip improve blanket machine asset boat mask flash vicious pig","master":"21df138f80902d1ee79948ca3836ecc29a0f9093b06a240b29ac7c3aab89750a","seed":"99cead310304d8ef58b23fd2b9ce7fb71386111ffda2f609898bd59289862b6f464ba261855b1bdbfad8f7ea25e43adce10f7386cb6cbb744ee05772b883d176","priv":"c82490739f0d969706299c3ecd89e4f47d0247471ad2d3f7ebba531b8d6804d4","pub":"03dfb5455095553fe24c1474c5a5dc0fb69aba612b79568486345f73fe27d36205","addr":"020c6ac4996d1c91b2b2894c426dc8e32b083fb2"},{"mnemonic":"auction okay cousin sick accuse steel limb staff tube gold hero add","master":"5bc8d22635bf6ce1494c820527e26a94c57f6987d6cdf6d40825138c3283e6c2","seed":"c7df0872664b4b4b0a7deeb3c26545380bc61fa3734a20a82c96e73707ae975b76b12f31da65e863040b2215c34a4e9f525ef38e555757a9e8a42a20af2f78de","priv":"0bc4a9bd3b88ad78c34a309183da9a0efe4d8e27d098282e3bb248cb960e018e","pub":"0200d5e1fe0707ff11dca2c30a0ac83bfa40ebbb7e51197993c6910312fe91d75c","addr":"72ada6e822ffed23ac5ff5147a22537b984bfca3"},{"mnemonic":"trip below tourist offer burden hungry later grain quantum universe service group","master":"7990e7b10c0c6bc95f45933e8f5be1e758e7b7b2ee39b8caa00e8ca50cc66855","seed":"a96ab2ab3fa2bc2547cb20cdb3e39eab2ce9dedb053277c7802bc0bdc4ba9d08a3860b48325c662de187c935419211bb64ca07448988f903cde04eea9f0f6e68","priv":"6d922bc8eef11400f93de7ce47b55d3e862ffece29fa666ba05c778ffde8d91f","pub":"032567a2ff9a50d1c4e6cc525dfb96da1edefa91fc09c32ddac3ad446056f1ad7c","addr":"abaf696230fd241bfed2c76a0452456bb608c17f"},{"mnemonic":"bacon together open trust hood detail liberty bean spread awkward antique minor","master":"b96abff8fade8664e35d68c78f7609f1c8553a02b80c81857583df0134513370","seed":"772590bec2194f5b552ffdb2eaad756555b22e979ef0463222af6711c53d77623ad9c34abe48b7389e67b10e56aae448e9d064e4be58c5d45c4de16ad56599e1","priv":"532a98d8be2812f88057a91510a20ed4e7fdcad022162e3d3dc14a34104859ce","pub":"020020a4aa457c2944b3c333141e9dccf1c500bb277b846d85a77141f69332a315","addr":"3b5c6eb43438c07d8591e7c4aabe8d4540490bd7"},{"mnemonic":"bulb jewel comic drop copy wreck unit engage meadow hurry acid thrive","master":"c0755ca5e91d4ec8f6dc7b2582d65dc70786a3ea67cd40dd68462ce13535ed61","seed":"e808525cb5c66bf4080ace7b3ff7d6454d07723ec23fa16fc0b3a346d7fdbf71dfe5f383c13d68de5b5f04cae47503ff352ae340700bcb75f2ed6f0eac3b7c5a","priv":"4f592a1d10867d00b28197be6207977e13c9fc551449d05be284642c43597132","pub":"035ec6120eeb601d6b3b444e066252a4c917cefda62c49c0ecd6384c1ca4db826e","addr":"35f84051b0a02090acd509fc801b21864c45ce91"},{"mnemonic":"devote guitar planet kick now above act sponsor account blouse divide horror","master":"1d5329254a9cffc9de60eaedb1735bc8b25c77142a9ea2098e8227ad289b967b","seed":"462b9b3d13f1b1e9e802525e3bd5e22f97a31b352240c9457c1f6d5f194c6e7b7bc37a4fd2607a27adbb77dd837b9114606c8dfc54d78a1a4c8f703889a2e50f","priv":"d5a648822e5c20ee1c56ac5b08a54e561a392d540d3e964499a5a970362c3829","pub":"0381ee04ec2cd440ee26d5a37c3775047e0215b2919736e092c2aaa7152ae448fa","addr":"daf4d242b80955a2269006d530ff6826f718fca8"},{"mnemonic":"youth error panic brisk panel hobby mimic nasty address little original sense","master":"57a151782b47da723e7bc39b13200bb9ee0c3621e839e179a92f99ced03d15ac","seed":"600441626b7035ce2b4e1a90a872ae2279cda57d8f8f44ae3c99edfd0e23ed4afb3e1f4e9b01eb5cba5cafff6a650f2d586d1f0ad85254cc99caa47abab30b4f","priv":"08030c2dd269b5b60f12ee6bb27aad68d3490ef128ca704f390e283ab608203e","pub":"03a38f69571f6187ce334833b798fc0d32065fef197f5812e4c392de54fce4bab1","addr":"02bbd2f05a3c4979db5ac72246d7e620e3edb769"},{"mnemonic":"age excuse wall torch dove enter movie almost build shock blame object","master":"cb4958fe22c8250f41998f6e869eb6cff240550af2db41d0b92e9bb64041469f","seed":"bd585927d17cba54ff5b2b63f2a98267d197ef07caf6a82b3dadc45bc5348d99dc7dac59e45561e55c3513a62ad1942ae2763168562c74ed808f1a59b32a64e3","priv":"7923cba208f6bc84ba7eb134836b96b69bf1f75330caea0be218df31885cbfb1","pub":"0369f14dcd228c164170d5187c21d092b4238386e0c8231a132cbe41e4ba315df1","addr":"93a1e4c78f24c08c48572169fa949001049a6528"},{"mnemonic":"expand shine stairs delay calm soldier deny volume whisper island topple cross","master":"0467b91a321c4326fec8f39cecfbb2d273e628837044815cab899f8debb66376","seed":"0597787fa9ed69ce29f6bfaddfbda091c7b35b6dfec6bcec23957e6a547819c320504afb3ed7a7c5636e4496271d2681891ecafcb9a93ec71bb7b5d9dd06c710","priv":"ab2422cc32992afafc497d2aaf8e4ffb193aa02a5574b0be59cca80566ae8a91","pub":"02348311d8c7310491aaa1f3bfba7945844cff5573ac8b5788872f594e20746830","addr":"a1d27d518ffacde5dcc9a10ade764cff42399996"},{"mnemonic":"sense palace seek enhance hold exotic sense pyramid program fuel deliver heart","master":"715d3a14fdee63848d94f9269d97fa562301f6899487a5ccc9d987c8eccad3ed","seed":"e80766a81744ba87d4faa9199a2b6d1b829256aadfc46f3b647be1788cdf324f8a4ec4ef52af07bef0d60ee090d3c2f45ebad582eb326b688366ebd7390df61a","priv":"7cd5560b3928e4048efe644e39bcc1eaa9e8b783c0f3f0ef5904e030bb6d63bb","pub":"03c7759ec461940a6a3f90b4380286aff6307c2ff6acc234df44aff978fdd7430c","addr":"0d43f6bbde0c5687561d8f5d457bfa78581b407e"},{"mnemonic":"poverty defy mistake begin dizzy behind annual olympic glad behave coin rhythm","master":"eb342d1dc891e285f0d1822af5e00ce3472b869c73102f87c008f73099448ab8","seed":"710a0f8ebbefb347f83eaf54d2977cd64e1f90d4f8de33c8ff041f807d64e5444707432877ffb4697e2e554d1e5bec48ff7428d13ed83433c4200b7aa6bd7c22","priv":"6c36c88b1168a478325ad77e220a77f10a2c8933fd72a2babbc918cd683cb265","pub":"027934c90cc3c75daf4971ccfc56f672fbe33f86c852f648afaf260989961be283","addr":"d60c6edc1bb9b47b0f2baeddeba2723e61aae00a"},{"mnemonic":"artefact vanish security tooth rail claim drive black push ocean special uphold","master":"08d1f1528ad6dd4424ca11825ac1b47111969f21b0285b3bfca9a2e28aef095b","seed":"add463ba53586dcf678b32e6285d40dc5502f91c3dd1128351380f52a28d08b9ba747c28aa85164b342e95b44c1ee03ce9c0d9029979f346ab6d9dc3a614f7bc","priv":"e22dff0eb96c0599766b81a0399e62589bf6e734003e45bbea048ac37c8c9bda","pub":"029954b4e87d373729575ca9b1606c566108753e12080de2739f64ea0a9b881ed7","addr":"0c670a5b8b1fe0a5e43d7efe0a905f67c5ae47c9"},{"mnemonic":"supreme correct virtual guess funny grocery assume dash blush rubber wage chaos","master":"09eb5b5fab562805b57ed0f1a96e66d56b8e132d885f39cc5d76094a4e169d91","seed":"994fbf31e1213b7c113ba0b47563afe37de2acab7bd17ee071c04b1616c6cb50d853bcd5203a9a635fab9dcaa07f0d9d4168a7303fdb53ef41cf5ff15db83704","priv":"1b56d4fd8c5fc994f22d4c7fc856aa18814f269c0f43fe65b52c914a186ec265","pub":"03941aa1d30a3122695e69b6a7f8c94edf030255255a33d82484f90c491dc77f1b","addr":"ebb17b37332f0079728e9de0f2b40951a233a9ac"},{"mnemonic":"pyramid insane eternal man arrange earth predict panther atom fashion claw present","master":"25ad3023a8597a1960b1e6411d75a821d86000ccb3e92a66646017f56dfe65b8","seed":"56231905c46f23f005085a4618005b1851055dc3f639f6b1169189c9bedf1bec6efa219631c333f0cc488e06a0b5babbd781071b7327dd8667bba0467b6630cf","priv":"0a4413be4769217c1f03bddca1fa921ec7935b473e9f13ab78f2b377c08198b6","pub":"02f4e8d8f9f165017e917b9128160fcc8232e03a7d4905583e60a76d3e532bcccf","addr":"d7356ce66dd427267edffbc7d90b1499edb2fb61"},{"mnemonic":"enlist pelican teach loyal like false property ski salon kite thunder gossip","master":"4b0285f521bf09632466c22873be5543b1c228edfdeb25838a3100d72c9bab6b","seed":"9c0e2337f5f02183d2dccc181372e47f8d89c3ba580e144fd6bbcc4d852e49d4f3f093eb1e29e9c0a58f84c6339033b800af15f212b01e7c60f8b89c3525f180","priv":"63a88432a7998b7af6962bff643d46a1d8fd7d4076923eb4a0f76a3038a7f26e","pub":"0284e4cfc7f7513515d97a68efd241f25c47d0b88f57b5308e508141b27b9ef2eb","addr":"2ae41ce0a0a995d865357c09749d94564f91ad65"},{"mnemonic":"congress like unhappy run unusual citizen flush force welcome arena clean student","master":"478229d977380296130a0a3d61be2ed2f8423ee7021544c32372beedf9e8c955","seed":"ee65535652c8733c881553f9ee7b9312a5ffe999ab40e12fe5a7b54101bdf8bc078de75d8dbee815604ebe1fce0eaa7104114780e074d4907297d29c1eeebbbf","priv":"caf650347982b40bd75eaa1830cb5d0089bfc011156c927ddec0fd90b333f590","pub":"037d33ba4e7bafde02969dabfbfe3397bd6744f1552da1313ce129f49eae410396","addr":"a00609d65a4753b3888416518cbd4c25282f355d"},{"mnemonic":"science reject slim wife shove laptop pull hundred genuine method canoe globe","master":"c011d8e6c42749fe6f7d1aea4b04b0d6e618650b0253710c717ece6d31005d05","seed":"40209df29de5baf4dd6b82df091404ec2f1b61f47bfa5e9a23e6d030848d8bd958138192458d82dc60c6c46ec01bf77b5c447e7b2ed0dace4c668d08c86719e3","priv":"058091efb05990cc436342cc3ef6efb2d0f02fed6380370d60255d37a2844939","pub":"034048a3e9bc89ed545de8f2131437838e7fd9477a7c3fba98032e2305732cead0","addr":"dba1207953cdf07ef09213624b99ae24780e8051"},{"mnemonic":"hint where immense cactus sugar entire stool accuse suspect cinnamon pipe car","master":"620259cc620b3b806fec360f2e9b84c4c5b94f9ad34c53b40debd1181e2da675","seed":"3332bd304e7a5b1120a80ce1fb74c1e0554c2fc5d3c007fa58af862c4c2450d9a1fd12c90ca6be5dbf9b69131eac8804fbe0e45ff433bf4d2f634b527319458d","priv":"536ffb48ba8ba6872cd9065c0d76b511a522a7e3b38c84ae16bc3eda2ef49e6f","pub":"038d3d8f70aa9ea108a19076d0e90cdde8d302b709aca1129eaf9ec281672b8aba","addr":"0fcf72bdee5071ce4f241e3c908ab5b0b969a37c"},{"mnemonic":"load loan mail real squirrel gossip fluid wrong amazing own post exclude","master":"c1cfa046473eee67b03ab8be8519a26c8cc72c01324d6a7e6108f3993a76d937","seed":"0f20d1b5e5e93bdb2031411be4c5590f977ca1ccc4550d7c8d8211a62221e6a5c6f34f7f99edf1f785811703a3540bd2f3dcadb15947cd4181b6e80fa988996c","priv":"b0dd0c8d5a07124f574ed87b406f4d51a77491d78f05ff5e80569741c8f044b9","pub":"03c403433ad539d2bfc212628180632b8d860172c6ce4ad46a3e94ddb1657ae889","addr":"145995cd3905204ca68f23c3203d5fb6d6eb8fb7"},{"mnemonic":"attack zoo topic note remind direct inside budget section outside permit inform","master":"ffc2f55b2c123430dc29c09fb431b125b5a3f321ed0ab5f64b179fd3358b0e02","seed":"693b14c3a0b6c0854971fdb5edfe2b5e5d3d37e524a96186d15fb0ab23f6d250b250f5c23a44d28ef9b94210df582d85c17208ce468d09029039ac5dcbd1222a","priv":"76f689bf1d6faf5456946bca3b048cfdefe39b74eb3e0e9d85c2da386db80d26","pub":"021e00bf6a0a71e0a37a8ffac002c5d5cc6350fee3dae6fd197a18ec880309fef1","addr":"7249de82b9250af13b7c309d32688ff19e7ed001"},{"mnemonic":"practice hard harvest gift bracket panic weather crucial have play reveal athlete","master":"cbce18216889b4dd4d2887fc924e98ccb5aae1e9b5d7433c120c79ec3ecc0aea","seed":"02bb9503765066c4e711e1a78be25e7b49689e107f58a2acb252b1c16dbb259db566a06213848fab833a32e34ce565788d7af30f584c21a21f02ef30dd2878e8","priv":"e6e7cedca2c3b1306cb06addcd2a861d04bc383c1579ba9d044a5c752b1b38af","pub":"02b11ef0b566fd9f429f88385507d63575094bd21caf8d3653a8b829c394de0920","addr":"8c0edef9f59b632305c72112f160e9c3616e3ebf"},{"mnemonic":"frown mix normal orient tower hero attend occur blur ship ball motor","master":"87c9a61c0fe1e8760393b18cc556b8f6d1d4bef0355444aabda127b342865d67","seed":"8e35626433f0913c1799adec7b23de7cf6d0689822d3a2f8d1bfb6ab041c80db3e5703c96aa09ed0db4e4f72097cb652e6d01d065bb6ab86f19e498793fb44cc","priv":"47b7699713fc59ddd67a556639c3f1ec0783a3dc3424cdeae4335707a549181f","pub":"0281ee7c3669207a68e189aca625e1b6eaabc909ae611a6eb2072f51a6f26d545b","addr":"ddd6d8013e5c4f99900cb22184075afb7842acdc"},{"mnemonic":"beef apple unable rocket balcony tag tooth spin sunny innocent clinic dice","master":"6b08fb53a185b5da79434bff6de9b10c558fae63beaf5f487c36760da44cb28d","seed":"f06397170fc337caa0278b2324f05095d587887217f5f10b13b04e1286158e4fe6a15da54c7dca729744e268255f4d04530763580ac7d660b323a8e8fe163753","priv":"923e63fa8400088c1f464357746b9e95560c23a755427d792aaffbb73551fbd1","pub":"03046ea68a2e1930e531b00376a4254da2a1ff0ed278aa800af2fa17cac40021d4","addr":"3ed4b79d2755b7d95fe1626d26a2b674a927b3be"},{"mnemonic":"sadness frown tape chase swear cushion eight funny sight dad solar civil","master":"af805962cf1c7bd97d0e4e981d3157834a17d3dce23a426c299b128685f28bec","seed":"a6292e7e8f3a502c4eefa0cdc94fda1d528642e084f45b30840e2ae9e7be636bbf2d67156e3bd352d1bb0750fa4df04dc5b8b6479c7c98c116c05ad5fe2d4d83","priv":"0bc87cd2cbddab83294a804fca193a6bbcaa3a07583bb2dd35619f325b70b7e4","pub":"025811f4948be5336572285ce58c97da84e5a4b7c542180933a1f4b6200ee4ebe6","addr":"9c6867cf41071e1f7d84ace3d2802ee46a1c08ec"},{"mnemonic":"bulk topple anger gift matter soft dune hotel dutch guard cycle close","master":"816ece50d6fbbee470de36fbcf646a83d224dabf5ca206786202f59ee7be8831","seed":"4980fcc86c5112625b63300e007a26287fec1b2a9cac0e254a8f43c91d897c03a3663fee0b351fd877171ce708b3fa471ba67290d6ad32075f0f6be6d3f70ec6","priv":"51cb46ea5db7c500388df8310bc5c8db7bdfb7c797030aa8f4a262b53f82a904","pub":"034e93f88a8da10122de23e2b25eeaf19aa1df514293b1e8fbdae2ad9fc2782779","addr":"c81ba2724c2e99a7168bd74cc79e222dd845187c"},{"mnemonic":"account lobster inhale champion relief scrub poverty tornado romance build amount exile","master":"202f11a0730b769f90d0fa68b81e9fdd78be483e38a9a39c447e8315d8f9fba3","seed":"001ce5c310547070fc2169bf0cb7353b90e824c051ea9f285eca426cb7f2527cca995865b0466c86a0fb3e208dc1ded076d2b985c8557dc7a94af7c6631bdd93","priv":"d142d2616dfe9e3aa43634a94a05707a8f0fa58ae0186bb565ecb87c96f648a2","pub":"02ca5eb73da42320161564c42520ab1a4b5823805bdb4dcb44a4abd88a235c6b2b","addr":"4481e257f1cb7d8105823e54a1b8d0254745874b"},{"mnemonic":"defense knock simple usage cook shoulder alcohol muscle pigeon balance become sister","master":"26df035303f63f356b451e829e154cac27e3f0c1686679c784d405455adfe5a4","seed":"44955b360a1622c1a69d20315b5fbc982502903b45736acea4f146c2cf69632a99630195b1166be96e4c90449abe1cddfacb3be63ff2b7fed02846b0d9244022","priv":"b9dbdb8952ce34d5f575b8b012a5e3041521efb893004f45eef2c01eb4f5fad6","pub":"02e9a6d02ce5cc1c14421c3d6db53d16a048e0421128f1ecc1e3e41d7df9d4e609","addr":"4e78dfe3fc045b8f65760a337ba354e01851d82d"},{"mnemonic":"bonus surface unlock noodle genuine stumble juice purchase grass table call piano","master":"16474b5955a793884279a9936804299a953427a38d5bead30553ec709bf42c74","seed":"da8eae0d3aa27a6ef6637dd17d57fe98e75619837c3dac48b3b546152d5fb1dcc4c59a86f65e8716c82e3014ccde5779e6e33c2a2658c71424f4ff9ea6ca0065","priv":"c9bdbc26bc788147d12c4bc3b13ff3774a7aad1ac66ce45e742c7a96eafa2a5e","pub":"0398102ae1bffc71eaf086b652c9bb847dace83d0b3f87d91ddacfb1702762cbe0","addr":"f0ead6caf66523b7e655b4ffd26a8b35f0b09eb3"},{"mnemonic":"envelope scheme knife muscle museum town valley until quote interest film keep","master":"bc01f4cbe286c6ad87553e0ece0e142f49984c2676ed1fc5142abb75637d47af","seed":"89867eca31ccd75983b064d62a1b4061d1f64c1731e25e08c65259139590490827869749ec30e8218e593e2ecbd4303984dfdb7b15775a487ba0eba84953a940","priv":"b5c899498ecb94655e622f999bd7ef9a2c4d26c3f555ee6888e5b4e1abbce1e9","pub":"0316d5c61149c0f83944192a788b5b64b9e6b1ce49f2604db67e8e4f16416ae153","addr":"b2a48800c35e6592ebe5003a46883a00360e2b44"},{"mnemonic":"also genre defense valid point smile hybrid radar lesson sniff one recipe","master":"3cc6fb6c4ddaa98e3daa2e984189417c55c1bfec4089397855f809659f9316cc","seed":"e962b4cbed0c3d5232f75595e7aa3cb33f1b2e093bcf9a21a4f8c6dd9677aba42161fd8eafe38fd12ca0ce3cb58d4d26fb7d349b1a160bf7f6f6b6c56284ac6f","priv":"420f0121df8cbc367e966344fa28d913bd1c3a1032efe5a3627d94039281e98c","pub":"03a61034ea8ffde7a239db255e414008c8e913a1405a34d9a606108f1943a7fa86","addr":"5976e21c1f85766c535011aac79e8a5f8b0f08a6"},{"mnemonic":"flavor spy elevator parent theme become slender recipe media pudding suspect melt","master":"4ce14ced0d4121d342d2c514755ba73b17eda70cefb20efa5aea71ec27ee47d6","seed":"0040263c29e5d965556054dbe7a738ea35b46775bea5859bc2e5b3872c89574e4f18de3f6fa36df65f47b13417763dc8c020b498ed3e9f11f46f019815bcf9a2","priv":"d2a1436a12fc9e4f2acce77564b8ddd67c1107d525eb6128c1eda078d3d8d845","pub":"03246bd048416493a970d97130d54db7e263af82dff75cc9fd0cf1e061f5d3f8b1","addr":"7eecbc8b6082d62d5fe28846a8ddc20b16e6a9c2"},{"mnemonic":"path number useless federal birth such peanut rate swarm flee current grief","master":"01d57fdf15aae5c1d45349fcb7bda6ab271c15be88429ebd1122336b91937540","seed":"061d0906c096a3338ac0877a102b4bb3b375ec5b34809838dfb47b186051a0a66c98e0d4a4dfac2c02b86266c4574c141f7a7c9365a57449ade60e28aecdbca4","priv":"9eb30cd9489297f0c4793df375a4a497162c5b75c36feb0a979da41000cc842e","pub":"03e036866bb847db7570ce0e2459d009dd1a89eea3fea8c3ce4f1f47c4781e32f1","addr":"139b3c7e7cb476da573548067d0a29b5abc111db"},{"mnemonic":"observe layer grab few fiscal omit clinic manual climb cloud song million","master":"cdaa9864952fa51a5a10de9210ea9e0199875459304876fdce150f042a415583","seed":"fa2c9dc476532ac66ec8e219c69883cb9645129765b4698b7f2010cb4b86b2d25ebd45e6c582a9f886c5fba4cd4d7488e81d705e63508e67c1698b77b8e6a676","priv":"238ae189645958242ffc9b3b868d78bad1be7d1351573298aac47ee78a5dac41","pub":"02ba7dec8131970a8f4a837bc225fe1e8fe20ef90b6363c058946930fe6b8cf629","addr":"4aad44c69095bad1588eacbffcb5ec324dff7563"},{"mnemonic":"solid business era limit engine fringe recycle harbor organ like tiger avocado","master":"afb951280a835f1ed21d00d478a644451e254310701d8a8025f5c716a5843731","seed":"2692dff98bb318f1f583e4f5d87a453b9e1472781b38f3b6a19784f8fd3e9b156ac6a292f8ab56e1da0967e159438b87b73042cbaf3e9886ee2641e7e97dc821","priv":"4b4bb7fa92a26e738da657b31ae57c52f057540f1371066b2570fb247b2862dc","pub":"023ecdde05d734b6ac286c9b14e1577f691f114b6554d0f1b389fdc37e05af9a55","addr":"5402fb7a4751cb34b261a2a2be940d7bdd3608ff"},{"mnemonic":"convince thing assume midnight debate end best cause laugh sweet unusual present","master":"7cf2f1baf94a8487a364a742db15bef15d1d1a7583ea26dc575b0181357e31dc","seed":"1e267ef4dc1099a438a346c7ca4c546149d6a57dc4cc6623ee160677711144583245125cfdbe45629160f3da711fbc57171564c4cbc771b1fd2a21236751eea4","priv":"9eea5ab5b8b22018197fd3c9256cd21be7dc26a111c60bc3d853bd977a19c90c","pub":"03e17aadccfc20dc41e65f7256717c54f9eb3898fe335395f25a65d4a96cbd93c6","addr":"85d9c9992d5351d84d40790e65c29b52b929f7bd"},{"mnemonic":"property youth river offer mention cloth mention pride opera repeat hidden orphan","master":"7e0faa6a216e4ae162547f5c9639530abfd56ff2026b4f18219d1c82934ab2ff","seed":"dd9faf30c2ddece69bb5d937c9ee58172564ec51d760fbdfdebe4dd445f1819bd6cc21a2a4cb70fa94a0d941d994d3ff58331be94f57a16589cd7a93c19ff10c","priv":"fa343044822d07308bc523eaf778bf697302cf8b88a3431bb5a0a51974a43199","pub":"0383e1d8186c1b3d0c567c91966a5c7aee8a1492feba372be735f9a612c1910ed3","addr":"efb2221453dfd951ba456f1c5ac164d3faf08032"},{"mnemonic":"awake virus civil cash clump equal phone wet friend attitude ask act","master":"87a61b5729fc2e294da66541b79085aa3f67c03a3eec40559111e68fe5a80412","seed":"8fa5a84240149f39dd60a5477ac59586aa05d6809adffb8184e4154dad74c2ab9a446f296098c44fac8c839d3405e0a2c1edfc26ba3aad9665e6b6984d320fbd","priv":"726210437d3054875e785b12d1aa23a8cab85a0a809593cafa9c63c62e6e3c55","pub":"025494819085e1d08d8ee2d421e4ca873682c69446ec5a412d7c7a7520900397af","addr":"e26e023a2aa67a3bb5e5988be46ff266722c0153"},{"mnemonic":"snap control problem flip minute huge lady elbow plate fall cabin trouble","master":"931052717250728c04dc605a8cfcc6a49a4c520f9fc343607fce57f5ae7a9e66","seed":"f55dcbed51a9db2ddd39d1164a81049af71116896e79ced722a387e878d00633830ab8cbfe7ee8e16ee612e1e047fa3d3c2a0fe230adc6a84f0178fef6aedc61","priv":"72aedd9eca0a5f17b3c20866d6d1e98bf01a1b8b9225bfb1d93f93c594726ee0","pub":"03c07579c66433d1b676630a0ddd343167fe91419a14a7859092b6b7f81341dcc2","addr":"37b2d898f165d5cca507de65f103231ea5128788"},{"mnemonic":"wine foam depth wise faith parade tuition search demise skill boat survey","master":"5001f6ff67ae2a32088e0ad93a227206bd66f5ccc7be991a27b2809354050b03","seed":"d889ec2bfbc930c78f9a3fc356e0dcef9d636766af361c8492189df1779bf76f4890d738106132cc5202ee97b849c9928a8934fd0b40d610a38f514953e3b02b","priv":"c19f1ce95ac35938d19d41e45d7122e8faa102e219188d681559d4db3f6aa66e","pub":"02331368ed143ec22cb1af2794bea8dd5e5661b9c6b1407bfbbdf1c1a151250b7c","addr":"a70e3677cb94b449a400c870159dbfa448e137cb"},{"mnemonic":"picnic basic you priority gown town oppose penalty various half follow nut","master":"59f5a86a5f6cf3254607f5e9846c7725d7cda493ac9850042de3bc7e8902583a","seed":"85645734c0caad6d0f3be793f71f08f2b87cc92b515e75abf94a202941c45aa78f663b455c91b6d51de40284d9c26a5336d444346b408bc12d8690e541a43583","priv":"17efc82e851c2938c22527638f4f3ccc2ff16ab95c24429c583b6f68d79ac948","pub":"02e534acf511fc86761ccde5eed25d793831cca6069f09694467a3b7434cb3fc95","addr":"d75b0c916f2329006221b040901933b2bc309838"},{"mnemonic":"enroll shaft young ramp moon message echo piano advice time blame mandate","master":"02f99e44bafc4e61bc3afff77696bd72af71ef05c86dffb2bb3bc241dd60861b","seed":"6e1cccef229d10e15ac6f1d2b2a579146ce011411a6e807cd227f3215c32aa394428f9a11900fe21699ecfd09d5ae6e4e1a30f2778bbdc15fe30927e32e1fa5c","priv":"8300a73d51449f909e8d0dfd843aa4cbcc055259f7deb54f40bfcc41acbcbe2a","pub":"0251fabe51d7eaeb45a7c82ee6cdd100f338692d796e7f1effe6a705cfeb21cb71","addr":"ada0f17f1854fcec548021ce617ea90a05a2fc8e"},{"mnemonic":"remind lizard alert mercy badge sustain judge van spike obscure account twice","master":"50a01f4e2adc48491e54c26a8c30c38f451de1d2d8195661eb50f6e5ad6e68ec","seed":"1194a8c42df528afd1b1eb41b2721a9b05f9456b09d042f15884d136c1713788ed8a32dc2153f01b560ad904c93327855450bb93ca8db384cda230eaec68ecbe","priv":"b78c8076bc4378ef0ea80af91addee35557f0fb059c1b434c254ae6c76716ff4","pub":"0251109362a0885fa59ad162e24c8f55cf4895bde354cfdbac7278d69124f77022","addr":"6655b6a665acc146984fd188c3c260668fdeef65"},{"mnemonic":"chief report afraid nation silent tower defy display suspect dice switch finger","master":"472175c2f86fa94d913108eb3842ff03fad950e4c7714cab8ce0c46e8e674968","seed":"c3656bac565a87cf18a1cfd8d488905e4b18436f93d0cf1d61572741b6e0ddfa794ce94a8b05e7796a6c9757edfecc6212e8b0ffba1e71064f67c340829b36e4","priv":"f16f039577d1fd9d6bbc18dc26c03cb37ad303ee1b85468df3de138ad927d098","pub":"024fcbc106c0b515838ce4d32c50ca1ef6134c314668d98a3ee30bf27e18e2fad1","addr":"a88574f43c1bbc38c2db68fae3f73f4244973b3c"},{"mnemonic":"now renew same wolf host minor obvious tape install barrel retreat cash","master":"a75fa702bcff39de09bcdc8f55cd1110c396ffca982d7c48f6d3d2f98ae29938","seed":"6d62aa254ec89ab960c04b4f72b5fd9acc135ad79ce4c9b3fcf25e0caca06ccf05e63d2aa47630b6c7fd3dc274dea540ceb4808eea2032ec3373d8a77b336338","priv":"dd211f6c5037d095da723423be7c1ead08f09d44fe01ffc0b2c0b83cccba6ab8","pub":"02ee58e7d2d8abd00c101024aff3da181d54ab84165e0b5c02e9d53dc336f0d11f","addr":"d9c4235d8222253cf41236382326190cc8f3983c"},{"mnemonic":"bonus message butter logic disease coast transfer explain away swim taste draft","master":"ac79c0b183965a1d918ec19217ce40c6ac1d84e3d57c8d0dd7a0c6ded35f057e","seed":"3fd63c9c7e1745a0f2526a70de96f251f1f61db25e808e3a6ba500e1a1c8e0693b888837cb9ddc1e8d09acc296e908eddb9386b97859bacb10561d12e46056dc","priv":"842e49ff7bc56dc113d532e7d7b4fd4d721f4600af0e67088b6ebbd491dcd4fb","pub":"03176edc37f7b671f46248531479b45b2b6ec77edb92001b46c64c7b88e7e588be","addr":"8170b83efdeca9e923de156cb5da2e3110852c0c"},{"mnemonic":"quit culture vintage misery pilot cheap wealth buzz false donate edit lemon","master":"b2fb8551d9d84f229e26e7874d1ed77ae8066ae80e04abae48ea84f96ae448f2","seed":"2cad64c36d24dc0cb94a2b2dac3ceec1498860ef0faedb78f702efada34c350f6b7f7760b14efc177893797160a838ead20f5a890ab05c477ee70cfa0a5a6c8e","priv":"38d5623053b64b8df44950a9f305288e3af0c411238ae3a89ea45f28f8375c54","pub":"02963af6b3f4add138a3b45b5b8f01bae5e6ba0434d558bed64fff01c6750ac053","addr":"9aecc7332529b0982d8ec14350594438ff5562ac"},{"mnemonic":"paddle mountain rent siege length essence negative amazing soap pitch blame sorry","master":"f179f7a22dd44ee96dc443f7fdccadeef1afaf9deefc8819cf254a554a3332a5","seed":"b408f67dbcdb8089f6ef0b241f026f6cccf85753ae137888e80c47b3267f58902e791675cae2854f556b067915821516fa04e00bfec6cd8e474d29639972741b","priv":"1fd4e1444a9c49ab77235d823e24d70d18b5d37cf9feb550c1e0763c7f9980b2","pub":"02bde455cf78c59409eaa2d98a105b537c9aee34c53486a4247299af90be3cdf38","addr":"46269ed379006a40bd873c79a9526ef076260eeb"},{"mnemonic":"abuse office gather ginger member carbon trash detect mammal shield like wink","master":"bde4ba63249cf7e6ea92a5724ae2f34477e42a8303fbf5c100c85c3d3ab8fc6f","seed":"ca4615dceb4adac1b16195899d537faa0d6e66a243c30accbe4902d26e77004da08873b0899ba21e4233d048c2d171cc8f9e657971f2ba0dc87b843f782ac619","priv":"05d5ce699cfc49b676ee843c9f85e1510f27cd65a76ba4d46eb6db36fc033c47","pub":"03c465fdcfd7441ab8d34244970daacd29a30c0d972b92a961559906f736d4cfb0","addr":"e60e2b02b46ff358acaeba84fadce61d7361f482"},{"mnemonic":"rude depth finger strategy wagon cherry mixed assume sense aim diesel urban","master":"ac83ffb8b0b9bc49758a81e567d179fe060301062d332bb40e353b788bd986ce","seed":"368f7051cfe851c638722e3691048292a1f2a94a83f44ac9e7d6d5a882c822e75ed5116cb059f0a91550b8b2237d32b9a0bfe556217455044b3b44962f4f162c","priv":"4af19a58ee5ea6c6cbaed88cd83c13a57da1c8002b816c833fdda7388adf8662","pub":"021ba0422b1fab7261983106fcaa20a43d8629633c95948e42aee12777181c1efe","addr":"aaccb6d212ff003c8754147b89b0718a58c002c9"},{"mnemonic":"mountain bitter treat hour purity swim panda damp notable beyond rough spider","master":"e48be94ec031c9cc4361550d88facfffaffc67fc0fc5adf495aa18e17c431007","seed":"fce2cfd110d408ed37c75fd0a88fd7513a09a8dc577b38176150f7d2835959f8170438903a78a5d84b32923bbdec6d5069c532621df387c65bbc2a879fe162a7","priv":"dfe58c17756a93be86fd81d3c874bf4ff6c45cbfcf049bbdf999a8e798e448c4","pub":"020d3913b431030aba9c57920708c5648ecdba1fb0111ffcf44f91f67ae92bf176","addr":"1ed6bca6d4080f039a12e3b0e772052231818121"},{"mnemonic":"protect chalk chapter dream icon boost layer couch soccer tool taste congress","master":"c5d0b996ee26e80cd48849482caa435956d87476d3fc5087a900a7e666ef3bdb","seed":"e40c57922c038fbfeb1ea7dce70c0807a55a2c62f58f947d8f05cb66ea7b26131e8b2b81ba9add4185bb8fb72176922190ba2e15de9caf3b4749ad7840ff1acd","priv":"850e9d1840b28dcea6088c9a4837effa1254f48af181d63f660d18f5062964f4","pub":"037859452c974613068cb16147826addb72f11101db03017612d1eed3e5352d010","addr":"3b58443eca15b2061bd5d7b3240b93e012424579"},{"mnemonic":"rubber twelve wire exile shrug will alter violin crucial border drill pattern","master":"15c68b495a571a78a09687a86495141f94b2c015f4c51a9dfbdad96e68c6d871","seed":"ecb81c59dc0464e8ff470db36c567301543b2bd1bdeb94512db63bdfe6632d9c88c1aef02bbbe04176ac7a0789c9579431e732adfbf038c89aca077d14582a8d","priv":"00ec93d9115439212ee358244b5128b48a67645a4f5bf94fdcbff2c8e93cffa2","pub":"02e68bb8dcc584b4e54da27ca229a66d6a222dbce0e187a9330b1740713addb417","addr":"14f8f956d84c53acad6e5eb43e8fd7362d341363"},{"mnemonic":"loud ski diet extra rely melody space canvas humble rain park fossil","master":"1e09a38b1538e950b8ba8472c07b619334973f9075e41732851606645e318d51","seed":"a2d3ffc96f020904af3760c11e9a9e87e8824c1093b07c92a8e6d98c6aec16adaa8ce6995d5d6b58a04824a765d0232ff995183ac38a5cc2bac14f734ca8496c","priv":"18e45a61f9e6ec29019df10abca1878045553d9b924c859fe57621f212133edf","pub":"02a0053e91ce99b2c401fc40cc2892023b30c2db914403ea0da794bb77f69e93e3","addr":"bedc6716f1649fc2ae412516cb0a1d68ec2868e4"},{"mnemonic":"potato tackle almost kiss unveil spring smoke nature agent carbon swallow final","master":"5917e819604fceb3e7c11bfdf6b85809f509f89b3bad6ec7069e8e29258df791","seed":"76d3089d7214660adbbc748f9690b70f7787e9e028fb429086caba19c3b412f931b2768a843ddbdfbb6b6bfdc6349aa0fce1168d124a13d8eda61fe37b407f37","priv":"13c35356aea2324ac57e4c2d605c45020adcd4be336e097dde0b23059499e947","pub":"02e9c1615b710594269b4e86436bae98e4e9c00e7ca0405b89be47c02060705ae1","addr":"e9699c41d2da37635fe657c557f54f51d8e4a503"},{"mnemonic":"innocent cousin jungle elephant speak rent arrow maple danger menu misery breeze","master":"c2dd7273c7f703e2c66974dfd25a1e7091d83a7e6f8ef64954c8b61cfe4e84c5","seed":"32f96dc9661f448f82e2100afa787fa09afe19d90171a3e2d7b5a007316690198a3da22adeb22a2fdea43c3ee98a6ee2bd33baf1e84034d559e6019a30c2e87c","priv":"1e9f48b65f2c57f6af4797a41afba8b017de41ccf6be00bb2a6dad09a72df167","pub":"0268e685815391e6956df39750aa3e9ad8e4e558cba04ed4c136785e2bf82478db","addr":"3ecb6cf97afb26e1e0272df4fbad2e38be15287b"},{"mnemonic":"shoulder lock swamp goddess length trend tongue razor heart donate curious social","master":"c71c518c4d97855fbba7c0d7df9ea8f4e6211962ca9f5378b493c6c1d3b6afc4","seed":"e575bae2e1ee08815052f98f5c4bfb9873f171b0dedf4385e378348310c5c7f6d1cb021696e5913aac6b631ea1951bb977b3bcb548579458807cd565771945a9","priv":"2fea7aaea02fd5d5a5918ebd643bdab939edd18ef406ac5163714fd731e1157a","pub":"0363e2499272df247aa216ab8b274e146fe677bb18e706fc5377f8c921ff1c782a","addr":"de719e1abeaaf11712931d05ee39990e1331055c"},{"mnemonic":"bitter yellow post enable knee tag spend base blur gossip lucky lucky","master":"1af25d9330946339620183b1f1209c4d1ffc0aae754b82d71268400b934ea426","seed":"9e07914810a7e2d91a3ff6d4efb0686c14e59506dd9dd3c357dd5a30925a3f57c0a4983589ff113833abdb7d5cf7dbf79c08172888539126dc286848c1e49ab8","priv":"6e1ca5a3a31b7f805e412f0bcde7f82bb3fd984661a58c07b7967e327e664e47","pub":"03cc8ddeed92731c6b475a964c885865c5a11bf59ba24295d1e1117feb7f1f3e5f","addr":"8b516445842b755f23d0e671f10a5c0b1c2e48f5"},{"mnemonic":"forget organ violin inch panic sword report clean garage sauce math man","master":"29156bb726af212233cbc6c191e59a96d7ce44b6821538ea03053f36d51a919e","seed":"66c639ef4de2dec82b99ad4ab7bc73c0a4fa79d28d06ee393ccdbcc27ee375e9dae7672055dbf6d0d5ed67f2e99d4840614223d85aec64dd35607aa9b266d9da","priv":"f5e49029f7141b33f51703add1f4495e04715674fb62ad2d781f8c66269fd32c","pub":"034132d2bc71934628f435b93a9d161a3ce242e7d82dcda0a3a8c2f304e3057500","addr":"cb0a4d79fadb82d7b947889b26f8515db8fe46e6"},{"mnemonic":"under depend door lens retire faith scheme dolphin orange maid carry disease","master":"62ecf318e91f233b59acdb4000665338c8d61539b7b079716c85ceadcbd6300a","seed":"30ec1c26fb1dd7e41c5959ef7a3615e6d4e5bc21fd8af5efe1f8c0634e765f63462d7017d5a62c1e992bbb626ffcaed002208ac5f8867a97e454c1bf0bcad8ce","priv":"2babdc8642c9c9beeeafb728e948bc8531dd066679b85a9b58676c0b4247cd89","pub":"037f9e2241008d25844a96272632255802c7cd3866c5a83bffb3e2f724eb59d385","addr":"10eba132bdc71c162058500af51c53074ea1947f"},{"mnemonic":"swim topic sunny exist exhibit nurse ozone guitar trend page machine pitch","master":"5a30155bbaea42d54e9a27fa7587c712a19ad6c1c31052f68418f235b7bd5de9","seed":"673d936ed3502149d68172a22785c2aa2bbb3707d319fb692fdc6a4ace39ec3596fc406b60720ab5993af07227f42608b5a43e8e732c72d8ddfc82e680428925","priv":"e6759f20947caed563dad40d46206c67599d4d622502e46199fde1e17dc3d76e","pub":"02dd5474a52b623514948319697c646b519ac6e63581d27b01f0780af8af085e66","addr":"85fb1118593dd8c12acb0c2104438faba5dc236d"},{"mnemonic":"dragon square define chronic round romance scrub gaze powder visa please symbol","master":"1f1a35ac699063a47220536ddc3e988c055cee5e08303b867fdc16d5488861fe","seed":"dc2037120b143c919a3f0d71c6822f29b9b0ea098d286f8d4e40b3240bc9d19d4f45da3bdb983f49c304c083f534c7a26471296211845c13b49df97be61055a4","priv":"d99a6b75adef1455ff85fc94e8a4ad400a326662e01e9c0152c797b842c060e7","pub":"02eb2aa36f19bb90fca43f34316a18bb80053faeaa909cd6222128286af6c18bac","addr":"d24f7932d14e493a54a5384dcba3682e3d6c55be"},{"mnemonic":"first knife erode dice talk coconut act example sudden garment scene income","master":"1214f622b52ddf15c146c74bb0843b653117459901214a8a198a0eb59b4153ae","seed":"eebdecdd33e9ed6dd2e825c12a73e4325593aa14a7faecaea48d6764e6ee6d9d4140ed9e105247b2ccc0a1bda976fe7fc7ef8483c58f465cf393c4f833e86d94","priv":"ad3894b4f558a2e7fe5f0685e4ccd63f57aead98863617b081ac620cd25ffc4f","pub":"039de7903629baa0b6ef2cfa85dbdcb51af3fc9218b01bc57bb1f7eeba5267a858","addr":"fe6dde2516232383dc3382a75e86be3b82d2d8c9"},{"mnemonic":"danger expand toe talk course mask quit virtual reflect vital address artwork","master":"54c66d5d95de00c23ccdbe2defb6cfe78d809d55e457a0b35407ca74ed33eda0","seed":"060b5853c7f3bbd7bfc7b5d532f39b74137c2b6273a30682f768ad62800744e1c6a1db920d151d7e553553cd908b2878a31fc6c682caa05af62eace45a897b19","priv":"0ab2d63d607a2c56041fd953d9be60f5f7ff5e50f3c3a606dbf54bd799e64190","pub":"03f8b555aa7005be93d03e98b6f2a8870b9cd4ef654299be64b13b89ad839038b8","addr":"526ec814ef1712329c1cd43244e92d3c1d5aef91"},{"mnemonic":"custom flock clock grain absorb danger universe achieve decade habit phrase together","master":"ffc14bb5a243dc703a5afb1f904f8aa4f21790b470c9e05fc21cf872bdfce41c","seed":"71a82a4221bf48e1e97c8e144de80e80a9dc5808d579da185e75f6b88bb81038d88210c252921a2d72dd38c5bcb4edd442d2b481dc1d857965012d9249f77477","priv":"d9bab16080df04ffe43c57fa80c441a65b4e49a4425a0db06f52d6db77595d38","pub":"021f074f1e14552ea091e14e680814661b1a75148f8bd149fb8f6a13f6f5e7ffdc","addr":"d63213b298b92b726178855680001d79ece9271d"},{"mnemonic":"spare absurd book liar green humor alarm income sadness shoot radio indoor","master":"f9056445390a09170334e8a225d62719fb259a0c159685c29ec39e348b742510","seed":"a023662c39608142068683c030ad51321ecae6bf954b72465dfa8feb34f1e8ace0d46a072b855e33f7c5e8be70420a4f3baf7ec3ba370e975da88890d4cbb2fb","priv":"e5b8369724ab9aafb2bb44a1d3cceb2568fb0350b45f123a7cd0f26a27e70b2a","pub":"03b9196b842ae4db2b2409389a0747407baef8b19d502156a809ae02161cb0de38","addr":"658f62b688afb4773a0dc4c81925d7914dad5d22"},{"mnemonic":"anxiety salon have exclude build airport decrease unable measure reunion monkey private","master":"4f708611377bee900ca76817926b905bbca28bccced3ad0e211c7609c0562fef","seed":"cdabd5c6b9a64c302fdde1e7cc5e6ca15811e52e432e7019a81945264b3e52d89456171be0e24d4dffea0136a12a6204f2958c303f8c61af84f4b5ed135685cb","priv":"7086136c92846f7deeafe05dddd8461028edf62e947fda55b4f1ac584a78c5be","pub":"03227f8b0d42ee20d3c5cb4524686d19ed43bfa5595debe2ac4840eeeb92f3a411","addr":"6d11946752473bad3a3d593f85e97bb4664c2984"},{"mnemonic":"frog youth swear now annual mushroom stuff business excuse frost cause athlete","master":"0390c3c986b8d724d344395860504caf17a7a347d10aed2f4a0ae7ebc0e07f13","seed":"25b6bc7a888b35e1246bf8c7a289a79ba589cbd949047ba6690b47bbcb12d8c87a4d14d585fc0721217891396ce0b0f75852187a9fea4feacf320f9ae4eba3b5","priv":"ccd3755ba9b7638c2ad6815d34a03869650bc1c35b75c8e1a1cc9c2ad71d983e","pub":"0284806c57cb6013ca5ac1027a07784d05b23bfc4e6facaef108bc5af7ec20e026","addr":"d512ff91fe37ab6bfc605cf5470ff684d6dad743"},{"mnemonic":"bridge rate pen range tip web bunker magnet blue rocket dune evoke","master":"38d760387d07ffba1ebd6ef9fa9737eabb311bead38560cc464c7585b90d6915","seed":"953c78a493fa99014a542b2740b5eb2623f0fbaa765a5aa79e61a5344867dade60e05c4293df4076e218ad61c66b1112f54aaf7bdc6000b059b2c88558f582b9","priv":"d6d617aacf6ac20090788e43a7eeb58d1b44c36ecd4fbdc9ba287c8bc7f3b24c","pub":"03ee39cb612e75ef609467ed6250b602b90ee94b25ae43be9593d2cf34b3cdb938","addr":"dcfbe07630e2a9156f0787ad4e96de1bec09b3f9"},{"mnemonic":"volcano exact weapon couple logic cactus carpet raccoon state rigid ball tent","master":"8c60a1a859b5684bc6aa996738801f47adb8392ca3f92865b2f2b3a48c69425c","seed":"fc6ede285bb6e6fad778234a5f6c5bfdc23dffa2975667dda6c5470c70122f8aca9c63bd77c8811c43b4d4b2ab4ca55db7b4d457f393436ca1626ae6fbde03e2","priv":"74a1b74d0f11c8297f0d315f9556a96ec5e880bc59fecaa1283ec2a693cd9ef6","pub":"03f62cef4ff1147df7ca38cf1231c48632c4c4b2618e6c7d2bd001e10509f68f05","addr":"8b8e006c70eba973ef8945d89e33b6a5422e5742"},{"mnemonic":"match quote pet worry pizza stock flee tip kidney tomorrow giant ship","master":"02f8e676d2c4dec8e6a8430c22f8adeaf3b25054c8d22dded7e2bb6af5327a63","seed":"4d29deced03c572a5fddf55539a735228b59cbcfa80381a54c5a69dae73f56484318e511fcf46123dd8f390e2527de882252f3c0b69f49b9dc83c7059e876767","priv":"049f7fa5733f1c674a29721a025d410bf35891984608ce1eebc7ab48626ec3d0","pub":"026912ef70835b247c3fee238937842fefebdebf046b7f2afdd4f350152765fd26","addr":"4d221f1336ccedb6b2a9850a15bbd13c62ce0fd5"},{"mnemonic":"swap amateur unaware glove biology frown vintage dream prison bulk gauge bacon","master":"8c370390691fe152f7d6f5220704c9fe6b27009c1218a07d529768f40fac692f","seed":"5e3c155797cecf5509151218e30101e33da6058dad04f89dcbeaba0d1d2310482b278dc747298284bbf7e29a71cf4a869e0c2755f6144cd2a5f58fd581551b48","priv":"708a814272dd4efdf60665c491730ddb73d3d5eae3d74ba8ae632183ed014569","pub":"02e06b607086808b325b7629a95ba7b945e611c3062f967402f04966bf87111a23","addr":"d343acd452e5118b6e4c1a83cb08a521735f2a39"},{"mnemonic":"shallow chapter special riot dial sweet armed imitate rotate south cliff shoot","master":"bbd697f9078e47816c986596fd2af08818e0e84f3c2bf52ff52cf72974add88f","seed":"bd24f3a066e4a994bbd613d12f88268d16d2439f9331932a9b30da17c7fee4fbf5aba4f2f333103c6bc1d0bb600be1c86db54e323b6e9e9394b93eee35a65359","priv":"1ff3375c7c35230fdb97b8b8a2401a59278b383c355dfc1773024fe38acb4a42","pub":"02d3fa09d1e5929fa37218d16448800c9eec188e31614396648b65f3303bb3ce80","addr":"8c3027c978b9be60970e98790b073f62cd3615da"},{"mnemonic":"illegal hospital witness leader wagon appear trick mixture refuse kidney total lizard","master":"9fdb13cb834e01260d56ad2bb7c8db55b768bd0e76464d52dccb77ab806a1258","seed":"a96e21fc0177a251d86cb6ffa4057890112cafd32a7c270e782616b407cda51dcd914ba2bda90c80acebf8969825e8044ec77965e264e085ee6ce78fcc698f61","priv":"17804874b6872c2df6c5da2ae45830f752a159dd03ab0b2ef22c64018e91c14a","pub":"0221388d8dfb7416ae88426999f1e07d41aca9668b10262e995cce20448e315e54","addr":"4feb63cb3ca2d1f6b0add8ce1bb2db5661dbdeb1"},{"mnemonic":"unknown update couple lunch demise sick brisk market area kid service again","master":"26f5f1d04e6f20ae2a9cf5631a1fda6f119e3c14dfb35ff75ced5091ddd072ac","seed":"72e5f09a5c9e56832ae400cc69b98932067a81edc9c0bd0d97d385b0cd7b04f70e51f496054c7d28af2853064982c9625a4fe745ccfe8bf4d690ffe9368867c4","priv":"e59d9190fa1f4f5b37842807ec8c886c9850c7946520f6fc764c232222500f9f","pub":"03da97ef93bfdd16433aad5ae6cde252c062a9875063fa3b7ed2615077e4446c34","addr":"4302a5c24f1ef5cbcc1e286f498140769f3fd667"},{"mnemonic":"leg damp bulb final remain off lion fold run buyer help safe","master":"4b64059f74a801c81a66d7ab2e25597a3f3c97fffe760d5ca70a8857fcc5fa55","seed":"24141973b3a7aae69d48656fc4e535d1a2e094d9ae5d6325f54d6288827dd32602b128ef414240fd88c9a72f790f8fef560efc023a6695f133d8b46eed51cb1c","priv":"13e840acfed4b533303974eb1223a9d4fd400902041be3994101ca517aedeb6b","pub":"03ed7c577c28dd6936bff7eba4569d681abf5bd59fb97ba5d793a3f65ad54f8d21","addr":"3e404c844010458e56726cf7d0881a1c4047ffa0"},{"mnemonic":"observe budget library column blade soldier apart panda express frame version coast","master":"dfb6154ae9a50d8853f5fb0fac07d98cdbdf00fc4511f6f940490e48ec1858da","seed":"a16b567cc1e2c96ef202c9d49b9d14cb5ff14c7c514c8e2bfb214a9e6371fb6f4eff3dbee51e7de2e781dbd815d1e76af525d9766504208949475866abe29766","priv":"b16e831a50e39788755684d0b96f9e4f11b9e637d9e43c27cdd5242091c0a8ac","pub":"030ee1b1e2c7afccfe7f667ba52dcef130de06b35655deeb33291ce6118eb0a31a","addr":"c72adab4e3d6d5d8a9a72e36bd2614d0b4b6e78b"},{"mnemonic":"exit pulse poverty scrap relax umbrella rug clump cruise biology magnet area","master":"0d00e0698a0958ab8ac891db675471b3f7a998f4947115313bdbfb189a8d2308","seed":"a2831c38659377da9fcb2b76d62b76a7f23d59083f33f8c6778eabd804331d46f2f0f4e167b013e16b2b6ce066816641b2bcf47dce75522cd3d1e6d9fffdb28b","priv":"d0c7f92739b274899883175525b6443c265c288e0835233428b97f6f912263c4","pub":"03740d02a36387dc52d66d96357240ec0e185007bbb4457b3598d96680de6309ac","addr":"c4dcba01a757bdf253ed47a41a49c996657d7f16"},{"mnemonic":"impact random cancel imitate base purity devote panel vintage group pool twist","master":"ae715a39fbf43bf9d848024d3eb93d9ca4313c384374fbeb3508077a29017462","seed":"da887f0a16dbc3fed38134acb53466bf1c1d18d179c2f857573fd4a43b8e52b16e598306dc199fa2414700b350174ffcbf4508951c765680f4b3dc7255270efd","priv":"512494ad5290d4dbb69d9247e563188a8705dbeab8dc319db39743c319389535","pub":"03a4eb5469006a29621ea5321f35e8ed8d839a9be99be7efb9caf5e5389dc708e6","addr":"4ab6b8d6bdce81c88b093698870645e7a1f92370"},{"mnemonic":"egg usual identify trap involve winter card eternal subject unknown obscure scrub","master":"6b54ed0110635ad73c4439e189e594cadb02f22d84bdbc7b94027edef2658a83","seed":"f23aee9d83ccd474ac819ce7dc8a57cc57ce082f8032c242511ccd96a395ba8c769d07a7115d25b53cee1d12d6a703f1c0204ee152bedaec1b8c15d5d5b78edd","priv":"0f1f52768a3bc3ce2810109ad40da0126ca5527c494b226048382a9513e11be1","pub":"031d08dd21c95576d1a1a028ba2938537d1c604679fc6e59cd13ef08e62e566a4b","addr":"a0c1e6d5d63341a8707be1673a0dc34fc054a14d"},{"mnemonic":"crunch drive cereal switch sketch gym hint fortune install approve device gesture","master":"4b4f8682bfb429ef36e7ea355276981be015fb78b90c50c19665b6804f7954ef","seed":"6ca97b6725834344247fe5dd5fa0d2a20c31130d6b9c60047578181867650f8e734cafab2158f57b64a92c3f77672352dd71d9df03dd6d592a137cd19e67f3c5","priv":"fac29029531fdccaf85476aae13bb3c3c9f0083265fe6d5e6e612386f3be3ec5","pub":"03683e7d7472d8fe91cc67bea096aac18dd00ae858b8912ca9b172207b89639b80","addr":"aced36c9dad879576f5904d67f504e704726a21a"},{"mnemonic":"congress nurse found frog crane toy pact write manual version repair embark","master":"157ac37c0bbc0732a71858377479fe8bb236664322016fdfd62786ae716f9ef1","seed":"8f8269a5211027a2c6480e9a9d910c385c2e772e12cb756802931b169b602d0eb7da4c603b901f55d4f5c5cb67d7fded0b71f5f9120ee1ce08e74c3bee1f745d","priv":"ae12502606695e34c1a97dbf15b70e1637c4d537cdb0a21896cbdb17277181ab","pub":"031077cb5bd6bea01a470524322478cb5997c06fc77d7154c92f3b7273a36c739b","addr":"6ef29aad62d003f9927be9daea218167fe14822f"},{"mnemonic":"verify service fashion camera deposit expect snack memory proud opera flower casual","master":"7df339fc4837633a008a512dfd0ebe4f9a1236f048839025d33c574c4af0cc42","seed":"151551954b5b4719de472d6a96d5222c1eb688c476f190bc263d7370baebd0740e58f2c3fa00e3cb4615389bd306ed994d3da60808d1d08dd005c5292d3038d0","priv":"771fbf2a2c24130bb356f2490ca67799ea8be2d37b3f291323d5e9b079681cbc","pub":"02f6c6d95852798faa803021107d6a12d56bedcfbccb8110fee698b800931aa2dd","addr":"00b958acb44eb87590ec60f63bf352ec8248fecb"},{"mnemonic":"artist gaze ginger just pride royal strong absent wash figure adapt decide","master":"ddebae65962a513c384bd902b230fdb48f6315d6645a947d79b63c4d45cb6023","seed":"8f7914ef479cab13a658b773db99f56a3ebc267675e1a91a3b595c2f0616f2793cb862cf6038858d363576f994c28c630eaa54299480f168f05d7564261a2693","priv":"b416f93bfe3495ae2ea2dfcae8e587bf19650ee08194962b43ff97deb85c1bcd","pub":"03c12fd1c2e653e3990d15b59d64cd3c34f3f248fc2f1d52946fb218d3e94912cc","addr":"06c7ac564ab51a452c3fe76c0cab37541ae1b3ab"},{"mnemonic":"case mandate call napkin cash test ripple bounce page dilemma usage stay","master":"101248d364cc296423da1839cc3d0774ed090bd9e73f55f355963272129cc184","seed":"b5aa29ba3342da94663315038e9b6c2d61acde2e4cd7d08971d79576224d12af8478abe891de819771a6ddee37269a71b13c825f8ea056f7596d301b00a9c0c5","priv":"4b97318dbb30a0b86d6497a97f3138db00d268ac6165a0fb80f5b8e5d714e619","pub":"022487dbfb8e3061c3a342d75ceb25ad9a6acc6b8df0b224f3f521c8105a4036ab","addr":"984ecec7727a1f812b63b6a6899979b36bff2e9e"},{"mnemonic":"neither divorce grocery stadium narrow electric observe that six diagram hero toss","master":"59cb4dd0ccefad583b8c79c8dc1c5e1d1d77149cac9fb26674076287105a0936","seed":"9c5e31547f43116891fba52294c90c80a583c0375ed100d69e2b72e1453b591b1072ac402d24e011ffacfecd2c8fea1c2b1cf93a435996df42e1c8b19aaa3fb2","priv":"f490ea8e2e8011d7f9b9c57d9143606d470ff00bd51ca69a44c2107d7de7123a","pub":"03fe9d9451c9505075629309bca9b361edb59483e417f07a2759aad704143ad778","addr":"65b28d0f6e78c0743903e41e915de6231603eb5d"},{"mnemonic":"van lucky present hobby property front toy document report switch strong say","master":"5517d9a3e2996bdc9e317a447f0506c33dc20c3c36e6565dd8af76ac2a0158e0","seed":"779e44dd0d1401cdd9d84061044158fa4036d66192c5059bb7f33810e776de434e24518477bd4092a0c775bf7801887a72fd94f0d6bb46757ecc3764f8e17e93","priv":"bbb4c89a597315ac9524df42b17498d334d93b8d48f19188f5ed2327fc2800b5","pub":"022e2a217432ce25ef42196530550d177aff02cdf91332e4a86c8d1fc4f34b07e1","addr":"ad5ea6aa0d47a084f1d01c547165eb51d067871b"},{"mnemonic":"swing shell april silk tenant swim clown beyond under tool envelope private","master":"bee0c171d74d809a83d0a7f70ec1d8ef320efd80541127c9e3b2dca85e344ece","seed":"da69d4582287e64756d8bc49979952716991ebc878764f7c8f93649f5b721c35f5496e7e81f5f21cc987315f53a747911363a58790eade4c43c7c24911cf8b89","priv":"a6c35d6f727685419b4c3717f0dc31d33340536319963186c64f18932bb3d921","pub":"023465c95f48753fd4546f6be7b3c5959ac2de74445c2352e14d0c57b058ab0ae6","addr":"7959735517d011fc100b56f25b6115982d2299e3"},{"mnemonic":"carpet sketch depart tenant immense sock because caught close canoe insect crack","master":"ab35e8379ede1615b44bf8b1a8dbcc3ce88b6d6d0980cd63ea4f783340a1c372","seed":"379373dd202ad95fca8046f17a5f989268cbacd2697a02ee5efc2f022f9019580e7fc452c551d97c9aa2247c566313e454768e38d6585ad9561a09710a279ef2","priv":"a7165228a05945d4b01a1ad12911666504f8fea8c8819df414995bc1eaa9068f","pub":"025a7afe792c05bb3d94c7996bf5ce1fbb02bbf716593b2049f6e42a0328311f2b","addr":"1fe2d6a254c104cc38f1466355501890d370b30b"},{"mnemonic":"world sweet evolve club speed desk double verify gentle account youth column","master":"b2309b5c1e0a5c590859c5ec3bad4b94aaee3e2e7ef21080cfe0780617eff220","seed":"efa3dba671c0c4e35072d8958b4d7af280d8e20d3b6752b34a6b1e561d0f44bfa7829a5d540b52e02dc1b06735dfe18b2073a784aa307253dad71b9146024bda","priv":"a2a6288f9feff9b408fd6b056309dcde5cbc40489afb85413202443d7c283466","pub":"0307429d4171f929f79c8532cec5970c17d6f92ae014e14d99fb1f8fbc0637c9e5","addr":"1ae1b848027b0d1276a85ec2946bb7096755017a"},{"mnemonic":"patch cave blush omit calm habit autumn load focus tobacco barely switch","master":"972320ebeadc9ce9da0a447dd469c95bdcbbda09e6887f64dc9c6fcb8d6c91ac","seed":"dedd6610c32b2e5a3fb93de12f758d92041b0d1aee0bb2626dc0e6e8cebb8ecfdf87e25dcdc4f9646f2e37fcc071ff4137d914df7133a6e22fe8669ccfa7cbb7","priv":"17cfca7dd65152e0a3c77a2bf4a15b0a99b7e889dda49174acefc06d390bb255","pub":"0286d1e4ac0c7df1e1e6ebbe1b7aea5f0e0cef8ff3336a1c2f61c80d135a382234","addr":"b184ce8d18aa006e93ce901fbe879d3d8d6e6417"},{"mnemonic":"extend install wolf token genuine mother swift pencil scrub annual wealth hip","master":"4ef0a071d94253f9a60bffa7443918f43865f131a579ccf93d2ee16a518af2b8","seed":"f66926e6837305237316d7a69fbe18911f73a4f98278a2f6e6b1a8e06adfc1d189875ca401387b74c0198741619030187368c2a58e6b844aacd45fe89fcb6a93","priv":"f4c00a2ce7e9217e5e5e3f5398114cfde57f25833e920f14989e450645087bc1","pub":"02fb09ad3c161919060141c50b70c144cb991a553a57b25b2688e56ad163c3bcb1","addr":"556ed45bf7463ad502fc2fc07ac05fc073badbec"},{"mnemonic":"canal pink undo modify apart bachelor movie coach december exclude scale despair","master":"ebef42622df1bc744290f0c5d930aeefe2764dca7efba491b78ec958a5acc171","seed":"056347f396399c75761136da001671c6097fe21adcc920952db079afa5debb60d1c3612742d96af16de34a44c792da1ad995757e6a25e62953116d3016639c86","priv":"6a83065d2777eb4674e19f33a08b46c44753cce58902a41cdc3b8e3f0883050b","pub":"03a928c2c2aafeedb59d1588a86c42428b70171eed39b94f68f2097d9cdaa4c283","addr":"28053af43e4d7e35b32f9d174bd205206f94028a"},{"mnemonic":"brisk clip brass tunnel credit hip clock deputy dial hole song soda","master":"965fc6288cf02a8aa3081de292a513fd7b23fd010d373045e2a5cb37f38b2393","seed":"553cbc6a6599410913b6304461c1cc8b4a2c09c8bc1091c231d7167d27892ffb84b89c3c001ad40d4740d97224062c974ab01ea2dedfe1a3322f1a041964fb46","priv":"c9fe5b03317f7e7496f8824f24b782c09b5b801b3ba7a08d5bab508005f88aea","pub":"02ecf7641a4b3436c91ff3fe5b9f700cecf8cc3769945c665ff6129f6a60e77a7c","addr":"e578b715e9e84da6beac28486ed9492bea16435f"},{"mnemonic":"senior example flock banner pumpkin salt silk soda funny input puzzle ready","master":"7b0b3ad8cec24080ad6fcb9b1ba4b745820543666d362a188f4aafa52cddbfad","seed":"367a466ca4069c50df5571db657cf4394e843973e5801db4d7072c51453ce04b574b01e07ee8ef0836448f7fa220863e6cc7e6180618efaa3868e78b807b4b74","priv":"31f5e11528a372d7948cbdfb0519f974168d568128e441a5840a02c1ebc71f50","pub":"03b507120d46abde399656100fb664c736a2476a588f2c893d4be9a5f9acb0460a","addr":"941deb14e567c6d60446fe5767a0bb780be7fd0b"},{"mnemonic":"say leg next pelican brand topple blame plate snow month van cherry","master":"82a9d68ae21ace7c2e5d7d8ff58e4f0cc3c7e5db8031d4f83008d06088c477dc","seed":"69956cc226c79bca915b24c65112962205eeb161b79f66246b493d53eb7e1dc56f9dbe475d9650c0e72d7befc0b899f75f7bb3b3c100f7d6128b21cb4cd88396","priv":"cc512c35a0edcc0efc15ca9659bb536b3957420f00b32cd9e3a0d0e1cad5360a","pub":"03c4c82df36b093deca7eabe03ede5c5ed3639dd37ce8598ab8a6342b86142b07a","addr":"d0ae8f85e8c95b4906de99ed528331173f251e85"},{"mnemonic":"develop odor front thank mobile subject then cupboard human high crumble rabbit","master":"73704bde13f4867719c71fac5b37f16f30b69581a53e7f09118ed1368610b1c9","seed":"88f30341bc3ab214f1aaf379a8fbe498825029793d4ed2b50d12ef666fe45f06e39f68583c4cea8ca6a88e5ea62d8aacb499da4814fe346e020a78bc636a3cbb","priv":"53f91608a0b1825b05ae68992f97fbec8dd7adf877c085d1f30981d6f5262653","pub":"025f5e6339f5b651038512ddb5073eaf10c962f6e82bd2bd94c117cd4cf4de4fc6","addr":"d24cd460bc42f5222b18d5632d53163b648c982c"},{"mnemonic":"toward weasel copper blush mammal window weekend exhibit pizza element impulse valley","master":"3fba4e4716bc0b0f99f44a2bc7df34bdf60bbc5c1e2b76ff4295f21428465dd4","seed":"8051dd06bf13a9b79d82138ee3e5cd3e417c6d203ad0f6ceb81f38890d4c18b56d29c93ba76591c499c9cbcce1bdd205b26ab792d506d4903d90104a226422e2","priv":"0379555ca3e00311dc6949659afba1cf6019ab5690f14fe8368f0fd07b90a44d","pub":"032446f977ee3324c946b0d6409a4b7401becffbfcb868827e6639cb686bb2140f","addr":"87bf7d0cff36c282a9140657a4420f67b7b7433e"},{"mnemonic":"lift piece elevator remain horse virtual fragile dynamic whip lecture perfect fine","master":"bd16309fe9a58eb87ddf1b8338ad0ffe4b39706c4d568cfdf6f5ddb79064ecdf","seed":"8433dee7ff8aa73f785d23b09d8ce7f4e1e5cbcc7c20133d81f87c1d47b94f733631d5406c01f756ba7bbfbdca900eb2fa03f6b0a0bc1f06b9f3c3c9ea4d6d61","priv":"c4ce940b7e5cc0606f023daa3dd724d773e886d48af58c785fef7605b2524a16","pub":"03c89852febcb140ba3d5e9c95ba6ee843666ccaa69492ede61dec94e4e6f73949","addr":"3c04769875dca7cb3c6faddbf1960e1738118d7e"},{"mnemonic":"dash output lesson topic butter run ancient claw enlist approve chief observe","master":"8d37dc9da62db3dab7a0f209d8997dab75793704d6c18056f02b6768db414121","seed":"6ca57fc186a6eddbb0e8ac6dea4c1eb5d8361ca08d7b909a8e863284b38180cf8ddd2d9590f7611a5cb80bf1abcb679adde5646e69f62208557ab1a37e80394c","priv":"db5742d8734235964645a018fc4cead9402a113a60de0d7f55ab3816c9780e8e","pub":"03710b31603eef3e10abe51c57c62818ae65fc7f0aa4a91cba5f178a0cbdb313cb","addr":"742d17ad66f51524f28deadb3366859f14cf02ff"},{"mnemonic":"blouse maid inflict jungle yellow believe arrange cruise seat dust endless benefit","master":"d13daac6580c68186cb049fbb63c05bf2282919865c4018acd8446828dbf07fd","seed":"5b4132806e12b669813f1ab295ec58fc472fdb46769ea7181faf6e6b48f3cf4d8280e8ed5951306ed71b40d016afa3ecb71476a23f455ab6e41233ec2929ff0e","priv":"a8b701c1abda145e723d92fb246b692e44693704b52198ba33128267bba63155","pub":"032c532be31e8394d98571f3623372abafce8bdd0ef02c198544d0dc6a6fbc3cf4","addr":"4675d51ea6dddfd9b296532f3f2c101229cee094"},{"mnemonic":"only enlist indicate practice safe romance orient gallery cousin silk eager what","master":"2bee5e0de945af3aed16b2a06423d3447dc0c91af3ab8fb20b4fc0dfdd74bad6","seed":"92a6a62d9b145dfac6f66b7dbdc7bcd7b9ac10163541cb95e18e77742e3f2ce1773d74b0b290e40ecda2aff147bf81fa8997eb02668891a68912cf42cc666fc4","priv":"6a8e812a13716f00c5139220f1afc9a7ac584ed7553fbe8a13c50add54e5446c","pub":"0341a641547fc87d6a44abe879aef7b9f7c36e3491f221f667d10c568eee0fe99f","addr":"0fbd95b59a63b2a4238d6703ff49746a5950db8b"},{"mnemonic":"oppose fan kit prosper message pass fiction machine duty antenna planet ribbon","master":"6464d66007d3609d21971ad05877316fd8fc73a4b61d971676fcbdd32eec832f","seed":"36f65f329a478fc6cf1c9be171f9de9255affd1434ccc3420660a156b6cc0a85a10d5eb1547bdb5849325f5972b332afea7973449dee8a72db256479301337d4","priv":"94c741202799e22867b197c900c11e25855196e9e10e2f74f1939aefb7ddb233","pub":"020b86916271d84b2ea8f8b83ffded3b8f2bfbcb4ac17da7fd59c9ede27c00926a","addr":"d26eefcc75de9069e99c2e98699823b45effa9d9"},{"mnemonic":"acid summer coach step inform jewel secret tornado abuse kit shell guide","master":"4a10d5e6783e00d6f3453d8948dc5b39776de5690775aaa0a8429b2f11679ea0","seed":"46c698780417975feae4b6607e7728a00600e0e8e225d5d8f36ca076521238761c5b910759f70498e7dbda012d4325f3fe81011ca762c2eaa06649a18b79fc74","priv":"7d6a286693fdf1e51c26a64e5e5f8763b328934540b18001898537afa49e8b1c","pub":"0319013f6935be2eea7cdfe0544145708d24ffe9742a64b1a2d22f24bc5e380bf0","addr":"d53d22924ffcad0359a177345c32723e6260c7c4"},{"mnemonic":"general shed quick sea amused piece air infant jeans page eternal lens","master":"7b435a6cead581f339c1008061cadc687c40156312a8201c823158a6028cdb93","seed":"0843ac840c79c9c7dd85cadcea3496bc7a376592b07d233c35bdcfdd09725eff59f0ebc1d0cf255035ab5c7344adc3581dc543b134a5e70eca410b46596ee8c5","priv":"e61236f6e4557b45a6e39058b8606b7e3041de297cb0d39ad06c2e5414199d78","pub":"0241be261330b87c2388ab4077fbd4fab3a66e7d039d3ce4faad319c42b8e886e6","addr":"29777a50646b5f08eb7a428805a9778851d3116d"},{"mnemonic":"view hood trigger weapon dress roast load artefact dumb biology sadness receive","master":"a619455307c5edc87edfda01059cfdbb6c356e9f639b16b80b78e2421f1989c0","seed":"d89adefef230e418d7462194e5e1a817a0ade01435763ac5030ffe94fcf4b1f9d8a06090ff8a742d22d7a78e4a6392e35e8c318f5d0e495d0f8773ff126ab56c","priv":"1f9c2085c35b5fbf1a096174e7f11537b4f6d6327018dbf3b3311488865e5135","pub":"0208e02b8410833b43ab7674e25efd7081d6516aada029588f72a5478fa5c0aa20","addr":"cf4138b64094d8a9f58cb9068305a69ac50c4f0a"},{"mnemonic":"salon diary era brain chat panel design lawsuit behind practice please budget","master":"fce0a096c14774cc4bb44a4e9c65cf075a2ef5eebf96f08cb684455218f4dbe1","seed":"b154f70e78908ca26852b659a6f6252d83f3bbc4261cb1b9faa4ea80dbf1feb27958164163bf7ad82de0ff8b1af07c60f23b376910a24608c8af4b88aa0065ec","priv":"156d45c8db9bb83613334020e9b9486eafe16c1341aa05f4ed2095ff5a11dd66","pub":"0389bab1175f1cdd60a54828f8684c99c603d6b877597d1ab0349ce6a974fb9e68","addr":"f60cdc064ba139ed5ddcb6cfdf6c89ebdc378962"},{"mnemonic":"text horror panda eight mention victory wonder orange error few you illegal","master":"fd6c8375c6c3458be159f4c2fea8d25688163c7d306e17aa2dc32951eec2342d","seed":"ff314a8722d3291744c0ba07d569373771357795f72307366b0ee0c84b71ebd60a54d6f1c1c974bad1150e85415658f5d30fe76062d80468786fcc20ee8ee903","priv":"943fb32cbdd79c2e34ea72a9c31cddc3ebfb1a353808e471b77f54cd108f487c","pub":"02d17d74fcab59fac7d1cbea2838d5db3ecb1c24219b0b086ea1ea69559b8c2099","addr":"996916a8fe8dd544c1906a0afe4b48df43abb409"},{"mnemonic":"apart beach sibling debris chat hope toy happy bean same auction brother","master":"9eb93023f619ad35b6aba1051b791dbde9618bb74059632813b4e0f72b16c773","seed":"4fa270abbc1443fe7f593af42da0b40c17773eb7b9efc09c621b59424f84be65ed1ac755b88d71632a5a384c6dd679887c021dd91aa06fd9547f5c52bac8618f","priv":"3adc47b4297474a18744bf61f18e3030bbf58d68eccd4b0f9a207fc513edb851","pub":"037f6fe821009e2e043e66b167e7708d9534a543391b3ea17abf449f2807931462","addr":"6b9668671f23172dd08382e8db996dc9df687f80"},{"mnemonic":"tag bright bitter hedgehog stable level outside alter uncle hold have voice","master":"63157c3bb0a525d611de7539718f3b8de9f4f7a61bc9884d2f03ae0d30e7c5e7","seed":"e40b20a383e582f304c7feb315ae1bb405e9a5e12797706042d82918a19cada05fd28ca8615d929dfe7ea331d588ae3506cc3cae09f560bc13d544607e075ba9","priv":"8675ee046186c61b46576c02a8a7e5dea1d307667ceba7f6a56bca72fcd5452a","pub":"03654985961e5509210a31d1f54b15b37ff975717ef1f5ea7c2aafc76ced1b6326","addr":"972e9f2582e7ed35767b1b23ee73af4daeaf0b3e"},{"mnemonic":"wave fiction coral polar enough gauge whale magnet science second squirrel answer","master":"e2f288c51ea9bb3befc3245bc0739998db6199615869b4f27db9b613aa443549","seed":"2d9a178a3292c3f3987c35d44a3fdef2d849630ff49343bc5c3456a6701310c56cb0688d7a4bb7c3d58c40472d8a71121fb54f0108f6d682c648694f9ee85aa8","priv":"4a4d6db92c8cae67cb80b4f8fc7e63c94d3ce9ea67026c2544325c7c14c8318a","pub":"023cca73403af0fa0a0faba0545c21472996381917db6e481de9fc0de210dd4458","addr":"fdf8fbd1473714cc6dbac873822a7e0c7ffee153"},{"mnemonic":"process visa stuff pulse shop ability test aspect royal pipe protect fiscal","master":"742d13461d14c18707e2828f69b8deae3e13a9d6c90895993a788bf51f5f8eff","seed":"fc0ffaec77037a17923401aea05d7e37f09d2e7d35e9ad26a5dfa3de6e5da7c4b8c1d16e5ff6ca18570b069e1e8e49ef9ef475665e00cf189eef652e40d3553c","priv":"ef5da20d14c6d948536faf4ebfec5f11e430795986086371afb5a239befc3410","pub":"03a03b2dfd694a9d95ce1fd0f9c97f3db35c02aa001d26dc313c269f8a97bc1688","addr":"0d76c54b8af88721dcc4968dbe47607d7040d3cf"},{"mnemonic":"jar draft slab quarter during hawk grass monkey mandate prosper hour fortune","master":"98e2ccbe3470de355e090d69247d6506ee9bf82473d83fb98c20506543dc4fa7","seed":"e6bae0e46c8e66bbaedd465ed2669f9ca5b2bb68d829d237a1846763129932588a1aa4e69979a4eb3f73010d7c093b20a542efa2fddeaa00032abb847cc7bffd","priv":"9d1e402404867001cb24a3f501b676effb69865045e6ac2b0fcfdc34f9df494e","pub":"03f0bc42295a11b4ccf18b44659cb6d0e0eca3d2034c98f485f5ae43e07a82d90d","addr":"e1c21227bfe3c09188066ae189c7d499d855a600"},{"mnemonic":"camp vocal absent ostrich sleep version puzzle afraid execute clog eyebrow tissue","master":"fdabda4c563e3d7caec47b62f4f06ca53015f98b498676116e7b3df18a4b4412","seed":"b752500a4695f6cd66edb640021b2f590e85f4df2af298388f042cf7b665f0d6e643827bf705d3d1d9786e64bb5e184fb16e270ebffe0ce4ff7f37c285d28db0","priv":"32ade388afcf551e5b9195941ee3d290a39ab041dc9a2b748cc36c53cd43061e","pub":"0346e927eeb5549f8f38fa6280c0932947ef78f63b55410e872e0bf6988e64d03a","addr":"462344dcf5eb679f62d6470927d227365b208524"},{"mnemonic":"kite slogan all win burden staff actual oak cave bamboo advance uniform","master":"43888096d253b010da1f0369f75bc0d6a3b5f14dfbe5bccf7c8fe9bd78242205","seed":"b770074f2868e3aa42bfb76b444f782e4a109f2ed51677a79a69bda83dbdbff3a64b9ee163c57859f143a726d10aa73b223f0cdcdde6497fb95e0fc4a810f583","priv":"26533617dd8d7399f399d59f0f8a50c798668f04f44b52bf50728f20959c68e1","pub":"035ce21f82a71a8580d4bff49e520ab9815ac4d5b6cdcf6eaafefa4457dd9dea27","addr":"178918f829f9cd67d701c9a64b5bfba373a7c820"},{"mnemonic":"bind fire final soon dilemma analyst train ecology say drive slot bacon","master":"9aaeaa7f7a7deb8a976783f523695466b78117462804405e200ad1677e547125","seed":"155349996ca5a6fadb151c9ec425ca1e39df10509a8577f6e63096681c13b3980285777e515176feb7e4aba096b4d9d81a26b4d3477409432629a862669bef40","priv":"a890f151c33c87340a9021d3186c4df062822a3088fb7447bb419bbe5dbeb53f","pub":"0253d42cb2ab28f7fcdb2011e547dc88902e1e4d588e9261aff0869b118bcd4dc1","addr":"19b05c71780f27ec2e44ecab4c426108ea5a0f6c"},{"mnemonic":"image wool rug little visa embark poverty shop shield parent odor farm","master":"c68aae9896977ce21f5f547a4d0ea9995c9641c2a5f2cf89fd5a804485ec0e23","seed":"5c6885f90dfc1286f17b0079ed90dfc3974ce6b60d4193784b9668ec93725328ee5c0d027df1d551541a62fe2d87cc19cbdeed9a235a4510b738930dd3eb4eaf","priv":"d807cdd58fa84e4bda7fa998c8bbea12b7ecb5147c5edf841dcbce2c8663be43","pub":"0259b24a008d6ff4ce4d589e081ff100c28c3f8eb5440c8643257881f10da3658b","addr":"a20d7d609e6b2c855b9da18dea5f7ab3d091aee8"},{"mnemonic":"enrich soup all neither easily combine police ordinary review room keep swarm","master":"8265329602cac11df40567d54c8d4759bd9013c7a325c3d628b81640e95af3ce","seed":"3998bb700715a777bab05afae33a6e6553af17bf8c35eb67c7d4afcc38d6f35875c12f8602f381f797157102334f9c01c483f8fb41abb5f439ebefb76fe260c7","priv":"8956ffbb87e45ba0ac8f4142e179e6f934ca9b88d754fd5347c340a598878088","pub":"02af92f546047de11b15fb4a4c13c77ec6034248b84835f421826a44a68477fec6","addr":"7a6dbb8c88319d3076eb0b387dd2a9e4209b3229"},{"mnemonic":"tribe unfair track nephew erosion spike machine exist wine banner horn document","master":"c8e67f2accc6f9d543e1619dfda891664d349f11eae5617d32a9132c015b964a","seed":"ee1bddbc1eded07dbaf52feac014380400de9e006bbbb74f0c12095b381ba01a696ee3c3f62eaf4324e49b397755cef44667762ec46321f5762ef0e269dc9cc2","priv":"4caaf1ce46e2a6bf8e058fbf063da8683aaea07af831456522ae501d4d09d517","pub":"03df708621a45e5d5fa1108caebb51c513ed1616529aa6f89e3442a840aa37d73a","addr":"4d5e8ec1737a693fb2820994f4dd69291c5224d9"},{"mnemonic":"assume wet effort damp similar original salon aunt grant peasant fatal toast","master":"ea31d3203ecc33935024caac7c319223ff0f4b694cf011538521b318716cbdb3","seed":"11b227c8cf099bde463f72b505add695254eb9fc4714231e09e337f1499791ee2441bd5a148862265b6b5414d47f767398fa97a392a82a0c70648b4a52c1c2a7","priv":"f96a9c148945df0490611dfd06ca16f485a153e96857d746de0f2817cd2412c9","pub":"02b7b1c5e504b37104fd92465cdfda7261a60aad61b7b19b040d074fd07ec8ea39","addr":"036687e670428aab8b8057483c02ca0ea8dcc8eb"},{"mnemonic":"celery inspire ritual apart bring pause sugar monkey leaf tunnel minute alarm","master":"fd42c88307af74bce721f71af73cdc15eba0a186923fb9ff122d86597c1578ee","seed":"46042a350e5932c11cf735b60382d9a331a21f199cc484cdb9df4d8b9be0400c94d58ba1bc4d41826e605c625c7301bbc61e71f3da650d2928e83e07de6a9097","priv":"23c351e14d35d01f62da3cab73dacdc1c0ca052a76a41b58ae9d5c0a242e5fed","pub":"027ef3a78f366db4396cf1da6d124e31b254e90ad0c517267fb5a20a0f4034fc93","addr":"64a202ed14304b5f143d5d10a08167decc68fc53"},{"mnemonic":"text blanket lake damp doll guilt select torch midnight tumble toast dove","master":"c9653205120cceaf6cc768674a6389ee961403a4364e96220134acceed105299","seed":"79d5619f5dfeedd623bfdcd7d201f58ba55a2fbfd0424f32b9a220b4a39cd048e5cc82686e578b420cc35924e8fa31f1a4a29307dcedb35a4c69567da300b07f","priv":"7a7205d096a658f41be1d4d6b8a8644bf370c34a10a55f4a63ce1117d71715e6","pub":"029b2f32b98281d644232c4d603aaf89a98083edbc75b61f8aa5ad2c7ca910079d","addr":"ee416c1d1471a6d06b755fc92535f0bf1a2e3f4b"},{"mnemonic":"crime level shadow chronic rotate era reunion fossil boat shrug patient artefact","master":"fe8df8e3413387b50476e0ae97fe9f3851d5645f90b0bcf0b47b18d16387c057","seed":"0be8bda7509b72cc2d39c38609510fee439dc03600883e39f596cfc30cc2f48dbf14860ca33b7b7dd6f5f41f3d2fa71d20fe3995a698599605c5ea23b95917ce","priv":"4462e7a144223c97450b5d6728c6d017ed953490f7e762563993fa309152ddb0","pub":"0278a9fcb45bb02944c9cff032c013168943c6e0193c6ba6299af4397e8113a340","addr":"a925672e895976c8783d48180cedd09b2edd6108"},{"mnemonic":"chest flat tissue cousin defense ramp burst once rocket time super retreat","master":"7a8c847ca8357ab65fe99b5cca5d0b70bc8da05adc747c4c2f201fa1e22d753b","seed":"96003a7547f32ae6d8e5ce1bfbd5e580cc8c81d3eca4397e5e1453824b672a6d966d97fdd462ee8c0553d832c28c42fe61e78f01d056b2952a6589273ad57514","priv":"e4847fb09c9438d765da59b51c3dd825726ade929294007f9ccab300c100a2a6","pub":"032ebdaeaa817d8b8bd206839e18d17a85bc44ff4d7f0a5367c4f48098b511b43d","addr":"449402b089274c0b78b40e6f45e8297badfc1bc1"},{"mnemonic":"elegant dune all subject country diet flag universe gap ability hello torch","master":"fba87eced090b1d991c077467db81d22e2691f9b15ea2e8ccf03a51a556ee13e","seed":"1f1cd5b090411b96728a6959a4639e3b2bd68d4ea5c6ceb801a5849af109650237d2a6727ac80e7b317c625faa593d7a8caefae3ffbb55f110bd66672cf516e5","priv":"31cf4c4c7e75e35e16e01071e2db66a51758c8cc2b5df3377462046e4d87f3d2","pub":"03722bc559c95cdd7baf08a6965a47a7762fb974a854d290295bd853f6be0a83cb","addr":"b7f0dfb1c5136bd9bc267e9c7b33c047d6a1429e"},{"mnemonic":"give citizen chief eagle horse alien below flip vanish eye sniff bus","master":"c3dc631ea1b0226bfa3572fe9b95d72d08bd160cdd5fbc2fc96866adaa49a431","seed":"196d5c0aa7839623842c51f2e5593695ddb596bcd839c70af2940e8d00f31dd68b45876ae7aeefc6032e8b939b4feb8114ce9c403e4b83e28a49ea69a97360ca","priv":"9fbb966c19808bb2b7d07c420f4aa59f7a41cce08499c4da2bc216d857ce86d0","pub":"02650905aba484a16f7c1a2b1bcd0ed4f16f45d1770cce32ed127bc046d5f2c3e0","addr":"1441b38310ffb1135c2c48269746894accf627a0"},{"mnemonic":"gym term crawl benefit kite various pepper noble into slim try then","master":"e5826174e32bce315c7baa21ca97c613b4eb095d74651867671afd3848343668","seed":"198b6d6de96c726477cf8cdde784fc43a89dd46ee8fea27933ab8daf09826ad0d7bdaa0c50f8d5c574f6f2e6ef7adabd9c2382feaae061c9cb10a3ba22c5dcac","priv":"ec23afe15c13d5f0c86a47b18ca81761976442cd7c07975c88d6ad475771694f","pub":"0331ddb4db50ff58ac1709986111cbacada08344bab6210da4a2f23b0c3208e100","addr":"625e5b098af6c98677a9a2cba960e84c11dfcee1"},{"mnemonic":"pause web there legal eight plug wheat convince adapt radar rely inquiry","master":"b13d46f4a0c6ef2cac56cb9c522dc35b8d02f4ed4f09f524d206e9ea6e6e6082","seed":"5f34196fb26a7bf0a9063284f702d934c03eb2ac10f3dc230a999e9566d3561b9dc0a61d199e7d9642b06474c08f9e12e618ac5cc1d805ec9cb9489d460f377f","priv":"b410cd330abf2a25f36b24fcbf72f73e5c62786cb5c0c24fdbc3cdf6ceb892f6","pub":"03755fa255c3f111f778c270f991a5cc0fc24c0068d78355ce340258aa7a3b81ce","addr":"170438465b203b844f98cf54b49cdf17094afd80"},{"mnemonic":"thought morning dad seat payment ball club goat man urge forget remain","master":"af52a1f224909be5cd5e7be0b960a995c1d25652cc0c6791060b98e1aab4ca9e","seed":"1e9bd47b5411fcdb8145b9eb1e7092eb218774c85da6efa3756e9a55e5ddc2153eeb568139c638af44cfe6cdc2a570451ed68c801dc2ff726b45ed43e8fd0691","priv":"5e42b1c08965620e1e647e89fe87c9079060121f5a0b65a5ca8cc462fdd13b20","pub":"03a7ca8e9445a67a6884f58e0e79b1571b34b90dad6df4c0b8dfd103e500bcb20d","addr":"f44393294c3f1369012836ab432386f1af2cce44"},{"mnemonic":"twenty memory ten own runway grocery polar dog curious program gap country","master":"f08104e81f54a7bdb17ee647c06009667d4d1ac6efe286495bcf2327c229adcd","seed":"10d3111f871ce9bda4a790e148657f6dae8586d0d80379d40e56cbf180876ef7ea5f2a66f006a8a8a46c7de99a4e4f8f5fa4cd1a3756a38a71971298af917d21","priv":"db3cc8657599d42858ee1f1a7480e68ee8cfecc0fbcca01556c1fe5e8f3a0025","pub":"02add58efeceddf43db9f3d12b54dcc1f1369f152d427a7ad5e3c8de5de23a16e3","addr":"eb30fff2557ca87addcffc02d3a237fd28511799"},{"mnemonic":"elevator sock worry budget skull bitter faith taste skill physical mass heavy","master":"bb2b406a20bc8b38709251d1cabf4631428e2ac053154db69e2f1c6d236c4716","seed":"71fd4f050ec95c4147aed32ea34bc065e67635315b1077a0e9453d883b0a4519015ebd5de2ad0f2a628c20881567532f3b679541e23892eca14d5ebf4456a8b0","priv":"ae56d8b12dd0cc788ec4d5eed7153b108aad7606d2f3653ba5c61bae06dd1cf2","pub":"0347f3d0ed7552ac8d667036f4403911b7a98f71cc1730223e74fee4194d0aeebf","addr":"98198786f5e46f72ac47e88168ede1378404ee70"},{"mnemonic":"message power uncle glimpse repair coin wasp flower alpha claim federal tourist","master":"28f596f188bfd9a0f1ba2729260fc20ecc1c1b67a20bc8a4f7bc0e810a625ec5","seed":"5a23114eb877a016fcbc82146957d2b9880ac79582776fecad126fd6b5aa81343cdc69c46f29ad17e19411f0f4e78817338a9fd39a72efcbad31ab965f8782ea","priv":"1376caa21630e355fe38924afbacded452c9552eafbd5b60dbf090fedae3d793","pub":"02713f022ea80f4807af048cd254ed4dc5a1276c21e4a7436306f83731843a5402","addr":"8a1cdab91bb44b089a51f0a736e914a37cdf20e0"},{"mnemonic":"infant walk right wave helmet punch alone path since output fashion isolate","master":"0de852a741c097122fccfc397d9ec55223ec1a6ef395c1848097a45aa6a4f0c5","seed":"d1fbf777f64ac5ab0375876dab5e934794782c73e84dfcb19a291a6a083d6aa6d0d3de7e8c804a8c02875ea5fa54a06159538f98f9174bc6cf69ec94e3bc682c","priv":"0fa223b1f217baf7a296e483ded5e6ee97facd5841fb85c78b5ecc4db7681838","pub":"0276da67ef9f098a2ee3a3a18d4ca17705448694f895c6ffc97959fd6507e904cc","addr":"02aacee8fb5e56f4b39fcbf7253b7a1302b0d8d6"},{"mnemonic":"type squeeze vocal monkey baby scale behind knife cherry luggage struggle what","master":"1e156273aae1d8c0b58558726d2f19924b1d06659adbe3539134f58a8a1ff82a","seed":"333847666190d4b5c9535920c47a6f68c586aa3f587cb7349542c0a30950f7208b3467ed437cd815007b11a4326f20b34f45335ba64cf9bcf17ef71aa10b9b86","priv":"c307afbc58b3561c7d276502e1b81de8b01c196bbdc1ccbde5855e00707f58ca","pub":"031a16f0dfd054f5d97233ce07cf647ad598a84177baa82d2f89a7f23cd0f2a0d7","addr":"3b1d109cab9545dbbe82631dd4f903b43cd79bcd"},{"mnemonic":"elder shallow catch anchor slice hundred kangaroo stereo myth proud clarify open","master":"babfd17c1c9647175a7b2739eb700c3385be4948f97d1dcd50cd17fbd605d6d2","seed":"eeb063599bfcd2520f7f07b3eb885cb83953ef9931926db8d1e76b689954ca902c6edb785af6d579ffe89f9253f5864cf21d3f7373986a6c1259e4bd0bd16437","priv":"652f38771bbddf64d2040c1300c317c42739f50839b604cc8f34e050b4590a95","pub":"02608acfabfda5579dae5d9efd4a191925864aa656e55b039da9736a874d46b8cc","addr":"f14a9e2a34c1cd6b95fdd473ddd799429fc03def"},{"mnemonic":"screen slim squirrel fox stairs still close club day satisfy either sentence","master":"a0101753f4e05c8ab9bfb6224120ef9c1f99ebaebc31c5aae114f68387676f5a","seed":"c1ec85f49b1928ed7ac6dc781703a66ef39692ba39f5296d9da33f93fd68cd85b0eb57cfb6ea115ceba67df15e4d835d813e3bbeea0363ef513220b98768316e","priv":"91af59d9bb62c2a2f0bf1b5c8729f2be88cc82e141fa045e59748f2b156b9a03","pub":"03a76d83455b42964c021906265a4e006d2c81555c8591a641ac0c495cd0d05cdf","addr":"093ad2a9be7153222002d94eefadef04ca7ea811"},{"mnemonic":"insect deer physical dog aunt metal super soda antenna broken undo athlete","master":"d3a4a655aafd0dd18e196b2f4e57bd4b1d27fe521f9312104ab75ac92ad92e62","seed":"9975a73239f3e2543108bec6d75c5c9a24261c9b2ffd0e088f6bc8369804b70ce99ddbced3c4cc2e1cd955be824f5d881af09e5ed403d7da2a533c73d9d82df8","priv":"0a313ab091f7fda44e92ba2482b8fe1294646bc9d27865bfb34ccd702376328e","pub":"02ff6999ead46c520026b1faa27004851fe1b2295e5f8b79ee1e87b330c45216d5","addr":"e3ba9de7fc81b75eaf4c6ff126b434dfda0a5008"},{"mnemonic":"layer embody trade slice odor deny please small clerk device ceiling right","master":"2b39b4a5aa164609c2734c00c1029534c5d7f3bc6b94268758acb506bb139608","seed":"1bd10cd1d50db3dd8f9e76ecf39b846d3a2aa44be383868921b155c03ed3485d52236c49783f5334c60e473458be3b3f588b9ac3e814d144128d96fbc002393a","priv":"5953e09dbaa56a12eb5e69231835924c0e38d5c322a43c354152a0333f26756a","pub":"02254c4d6976965f7c6122efdd52f65ee9e25b87549789499b72bf5d7213829d04","addr":"603d5b893cc41223eff641fc1a374a3ce97138a7"},{"mnemonic":"token heavy lazy little dry glass riot hobby keen blur wise okay","master":"7d84cf25bd5f7dabbdb7beae83d1fd128390b3a0fbf2d56b44fd34a7e0d11539","seed":"8f144bce2e5c73f44e5dd62ef4695c6e3457ddc37f64d1552e5b46a771120ccac23cd592b27a135c3593f8f21eff22625ca7bae8581f4f8ed223e813f5d98a6d","priv":"37d2c3993b275606241307c7b2339e304180555df260f18f524abcc75abfb0f3","pub":"02aa996bf4d889c9b37aacbd07d8ac3ea69e535c065a4b4258844b10c2a08eab8d","addr":"4a3860dc280c75a00382f3d8f11cfa01fda90188"},{"mnemonic":"tray drink color across armor spawn vast skin debate huge surround play","master":"e0cb1eb09b82bcd37fa63260e49222cf13b0b07cc1568aeb8849b538bda65a1f","seed":"faab52fca3060d1903e861706b57ca50ca71befd2d5363031128235cbb80e53ec943362f2288fcd1c850e94cf4e7c38029dff1880dc3f8c8bd440b14ed15fd01","priv":"747aaf84f110aefb34026ca0492894ccb8e0d1b34c5b0f9a9027320289914b52","pub":"022d3e35a5f51a6be1d0aff686e66e2fe282e42a51044ddca65b8a7659b6386f3c","addr":"43057d3d99231163cca42fe248b9d350ad7ae146"},{"mnemonic":"ring act drill burden sunny someone riot spawn uncover sauce today jeans","master":"676a5a20f35054b4f7ceb22d38226df0b2fa192b6bbdce9a96fba2b51845322d","seed":"979a3caac9130fab128a59243447f5add05251ad385f0c0ecca60920cc954ec516479aaf4def728770606db840088242a8bd5c3758f1ecfa7d3f8d54beb5cd6e","priv":"0e3f2306a70147cb332877343ff260e18c37d807d1ada3db3545dc21cb7adf71","pub":"03374f7d18335d1677902e2fb7c7afb6c3646ab18bc76d12793b86e0097d2b79fe","addr":"4f65a8364edc65cc430f4916af41cbf339c34a4f"},{"mnemonic":"title reopen welcome pottery stand safe scrap little razor rate oval rabbit","master":"600c330dca29a426ecae0e5e6dfcb13e004efcfcab0fcecab676e42462caded3","seed":"7554d02d091605c47acf117773dfb96821e28c551c2c5e855803f79f7ec9b9e5a4a7273c605c2a53771e045bcada466d3b4a88d03a7fcc1644d990a8dcb21ff8","priv":"79621755dac86e6026853bcd0d4c032b48b7c5eabf81cbf8ca4e9d056fcec5a8","pub":"03f63693949fdc2b62cabc47059e8b1d9ba748800bf08a30001e19aee33627d189","addr":"ae0c6ad31b94b29d502a846e1e371356a96a4f2d"},{"mnemonic":"hat stereo gold maple advance wreck poet dawn excite midnight kind type","master":"661d8b63856089b6f3d6bb37558d4deba395c7ea7797d022db398c3224696316","seed":"b13cc53d42e9726cdd9fda4279a660d987dc3d302409a0ccc844731ae1b138495200bd1ddee3912124dbe826e62567a9b9fb57a33b638cbc4a56f8b55df3182f","priv":"548da8b9469029522189b9d4e30f6b58c75f234f18b99d4f4dffd027b6e022ed","pub":"032df4ae6e9e3ed444bc1fe3eba670f2d877de7e579309fe3e7a8ea3b5176999e1","addr":"f94c66a0851fbdb52cb7b6774c736cfe4f99edae"},{"mnemonic":"image wolf among domain where post bicycle perfect cloth october bonus plug","master":"1751c464935d8be5b1f43188a61f14d0f509cbe289d5e586f1c5057299c05d56","seed":"80bc37cd3dacb7020735655be8a001ea26bd8a5a74d950a5ba3f31603bd929531d6da39d06499927e5acaaef4845b3403e73e3bbc7a43434242dd2b432f17529","priv":"38db8c107323379d07ec59fa7b76ceb436a5430468562fbabdecf4bd0a06d58a","pub":"02c5e7d3d224db89285ff2f71c27a68b267f9fd799f05ee334084edd4b91d4071c","addr":"40551f9071d46824a15fba194d98425698145795"},{"mnemonic":"squirrel grit cross witness wagon defense marriage tonight absurd organ load sing","master":"d5739288f3d99e1759690e2d68e5ba543151cd58a0d55d0be52f0a4cfcdc2a3d","seed":"a3e09aa4755d4a4c48f4611a7a8c22040feca1694415b2a6976d2ce161102557f5e855d5195b0132c9e7f23e01b825465eaa10b19ed323647ea5beac8a635e75","priv":"055f00180e4bf6548ba7b525236f63444808c0052fabc4eb14cdad2debf499a7","pub":"03f9831a1213aedf436bdd9e898f1d571ed6a7858f0168d60afce7ac389dc27d86","addr":"8a1289c49f8d83275e4c2201c87ded060ab38a36"},{"mnemonic":"cloth diamond test stay also risk music unit beauty escape trip draw","master":"6d16a7ccf9577b8948afab2ac83cb12ea124e9cf86506e6d08f3fd685ba97a71","seed":"d67dbc3d1e00b7703a7a44b91ddb891d89128f59d2f298b2a48f464aaea9852b97fd3002569d9e4b8a1cebf0d7eef3b708a944b1cb745844fc01b71829bbb2ac","priv":"d52b78224b5e2b9d074b4141dba1956b33f66ec7e8e271a20786d04136d1755a","pub":"020fd792486b8d8777b9910bcb1c28c52fdbaf239e07885b94ebf85edca05f3609","addr":"f571651ea3de2e84b53da4af619b1c51acdf9c13"},{"mnemonic":"vanish slush budget question demise bargain inner push weasel clay project project","master":"11828853c3e89d3515ac8c838d2a5107079c93695c430e2d5383fff8a0a98de2","seed":"9f838e1b4140cefd6857ecda55690fdf36bf4bf0247833801a481130844a89d0483b05e9cd1042a855714f67298a3f9d8cc093e6bf9e86b4c7bf16223f4f89d8","priv":"2e5945a384de4ed1030a299e8dddd2c9ca20aff939641e3cdbb00f5619b186f0","pub":"03a52a0f153c92a5fcde0f004c4ab3166f040b6e7e609afee6c2d0e494c18e7a75","addr":"09e3386e3636e365d8bfd15e822b0cb50136b5ba"},{"mnemonic":"blind desk mobile debate orchard nerve crack tower little scrub twist fantasy","master":"4d677a558cc1d0911ccea1c14c817b8fea57668f9a81af43ed036a1bbbd8b6ba","seed":"eb67d96512b6136ce060c7b7800fe48a8fc2ebf50a6051f4be4255a5e974fa0443f0c5ce1efb0b0a87f227b0da5d740452313d86561a42262e5681864b529054","priv":"d54dea50a4dbc94530ed3c04771c6f4c71487cf3562e89b79684fd6ab7843846","pub":"032622eaf55666e30dc53d73a88517f24a08f6ad703f02db30e87368c5344cbb17","addr":"eaf15d884294d6b72b618c55206db3685e1b0532"},{"mnemonic":"thumb nurse there alcohol legal agent abandon sight pill street speed catalog","master":"1a041414d1258b30a589e61e6d8ba19a34ca2b2e8bca68962c0c9dad5863f5a4","seed":"1b539679974f7355ee02c9d6609640acdae476ea23bc7d5982604e20009bf3ec153f9ec82fcae5de92570d2bf94672047557a36b3ad3f3ec03b910038658b816","priv":"5ee3c0258920c32da893a0fa051593544fd3547c6e37123ef9d6edaea940dfc3","pub":"03e8714f4d3e9c3e342dae646deb62c31cf3a4bda119a820b0ff6810b8e3d85383","addr":"a3eeef1bfc965df2fe15abf7cbf19b381a458478"},{"mnemonic":"crew venture wall front gesture jaguar often arm fly scare lunar guide","master":"656a72d27ab1a5fb50e27fb598037dc2ebf60b1b9f0bf7612a8490c1efed6b39","seed":"1cd2a5e644dfe51e367da6784848ec64ab3c4965818dd3529f00efdc102388b02dedb2207052bfaabb32a4039f76594b006aec871dbe9856f2b71fe6f426d75b","priv":"67cc3ba8f7d83c6d08737e1b56dfe469c21500f20fac09e8bc096a091682ae73","pub":"03ca0d6eac7a2663451d29012c25bcf469d12c556f30a57a34fe6d66d27d506db4","addr":"5acc54542938330e6961c6ee770760c135ede717"},{"mnemonic":"survey never crew section reward cotton praise ketchup treat suit knock text","master":"7175659726fd0ffbbd37fd2c7e309589d32b271672ca5459b7e1daf5f2daa105","seed":"a5a37f251e3c745169bed474c8ae6599da847ea473da32b8ff922f2c710a3c31034dfc45dee514af90246bbb1317e21669ccaa0666d3c88c8f729fddfb95d240","priv":"fdd98704f53d7ad0e43ae71437626048fe23f71c24a67f31b9491b60c4db3c9e","pub":"026936de280e31c060bcbc777bf28ed1ccd0128be0c25f9d074378f72db1de0f4a","addr":"997434efd190bbf98541832fc48283ff736a067e"},{"mnemonic":"lonely physical plastic final cool beef cloth chaos dizzy enough whale farm","master":"79842f02a7d39d8f19373fb1ca3c73f1961c916628279a00c96a980cdeade871","seed":"f957d8197386bd4ed6c5000bbbd02f70d6b4b76953dc6a3e36f021d488cec54293198f64fe6d46c52041bd34efbceb1e6cce3184a42c8fd37903b924112ba2f6","priv":"d58df19dab225b29ea77bfbcda84c2f1982ccb6e1eb79011bde7adcc03b95050","pub":"024ed971b9763ad9aa8be27d9b75d9ff2f443594da5e3e0b7a598c71f6c2e0d759","addr":"f4d72185f769724b50be932caf960a1a3951ea84"},{"mnemonic":"can three trend breeze spatial puzzle stool cherry raccoon sauce bounce balcony","master":"e76d9d768fe3ead9a6c1b561649b292d8659a6778442f9451a8fdd52e35637d7","seed":"85aae0e7a3e2efd67741cb0d752a078b250deb53927bea3f384d72661889409389188f267d7be61629c6a85aa7dc5b2607a066f32ac39a2c5efc4720b4a72e7e","priv":"57a934f4fdbb619a40394cda13acd1fc61ed9f17e4b4fcbcac2248b5703eb71e","pub":"02004c3736772a2cb507231b7ab75bfc7c1d35ca9e49523f1076e7d0925acce8ce","addr":"859915a9f70f142a41b0d169e7ec342061fbebdf"},{"mnemonic":"gaze example quote much tourist pitch victory common lazy message random glad","master":"6fdb41e8f54d6f123c75856c1c13caccb01bbd7e84b1c3385fb5fdb885f72f09","seed":"bdb5196003c1d1d272367b12affaa4d0cb37fb3aeea88bde6992dfd3519af34e94729ebc9e8057b9e462c064292a7cac18eeb838ec0f71b082cfd66bece3c5e4","priv":"1f264f1e86de3b28ea8f4827dee679787e60e34e81271139a8e74870518bce27","pub":"035e75a0beff3188c9d5aea7a760b879413ef712d98354b702aedc3385d58c903d","addr":"67c21921fa2c47c5657ae2434c29f447511fbab2"},{"mnemonic":"taste panda wreck guard trend blush armor giant innocent palm trouble silly","master":"8f3c32829998fdb3355b3a88caf484eaf7d67122c991c2402d77eb3e5e4f8416","seed":"fcf9f308ac99d81e74329f60787fd311848a2e56384202c37c025bafeb7022e4b47ca24a680d07d073566c487f39c8c0dc4bf43569b73f30ba4a2c260ce98e28","priv":"463194496ba851f6455e8298a0d4c118341bb0183c73c2d7739ef2c5bee38e0e","pub":"034a87ade739d3da37c8f15928db9b064bd1d1af0c10ffbb9f2027f42061c9bdf2","addr":"b0afd62cbf962672d092732872a6ab2795c9132c"},{"mnemonic":"tragic enter actress believe nominee floor vehicle dinner bulb useful case bamboo","master":"66f8cb0425dd278236de1352e9b2e47fbb8662d1de9d31227c4f18873b6aaf4d","seed":"5f0f5113b93be9036f009972fc49d9fa444c0dc4f89ad2e5d590f33b2aee250194494bfff047f8c9cc0261208d0d842f4c8a320d68f852c0938b6dd472a9c819","priv":"3fcea63ea530b9539af1ea66f5ceca1acc508fcf21a0d5ac21a378af5aabfb37","pub":"0256ac4246f19dbd12af232b2fe00efd158624ea48728b3a647c8237b7b9c1fe56","addr":"13804f3f5f0ba3c8f769b2e3428962f4ae88e4b0"},{"mnemonic":"between grocery tool polar already roast cash budget fatigue museum obvious notable","master":"c13b5bb1840f804c9b1da51fdb788f9262fad64b4c576370ede2d9c4001de2fe","seed":"1e5a866e10ee3ed7e727f59673328eae03808cfdb1bd3c9f155a1ce8f7c9bee61fd8d68d6b995588c0264400780467313ba92a9c359edc48ca59dcfff62567c4","priv":"08d7d4fa44f89fddc836ea265b71e9985363cf4e9ba0cb5b1ef0bfcbd00e0aa4","pub":"03514e8e0c990a6a60b1138351255827c7c46e15c3bc25f55946276b5fc56d9068","addr":"0c759c31f5f142dac57e712c7a09c99a3a0875ba"},{"mnemonic":"combine unique pig mind pair area chase idea abstract grow into result","master":"e7d06819461fbfccd1e05b6d63507b179854fd75fe7fcce2cd04ad6eb89fd11d","seed":"a1863842b2a6d82dca20ece807c12c58f6c4d2d1fcfc2577baa368a3a45a7ccb0650009ab558bc8350b77f9a03f6155e8c35f76ebf9b30133dc732ef5abe69cb","priv":"a545f01810112491c613a35c829157cc6a3dbd30b4b51f1d1eaa53fefb61e09b","pub":"02008752e98ab20e0fc8c9859884f97423c2315f5f35d1d757907b0affda7da9de","addr":"353ac98ae22d3161ce81bed93d7a0d77abd9e11a"},{"mnemonic":"bonus voyage inject they glory wreck soldier anchor also job cattle random","master":"cc5593732d2681a1aed33672cfe74f24238443d1b118235550834e14bc720235","seed":"ae6175dae17f8ab7481092eac1ee7d4c08d9ffeb69850745a1507c63426aaee1ef3bc6ae7fad3152d9bcb58e77a14a9570a4c550078c963991b215db64a2e9eb","priv":"45118b84fd5c7802b71fead3d78e5953e1841ccb4d4cddc20aa154e9fbfcf467","pub":"02a0378a67714f50eb383b47f7ab67b32c2adc2b8376b12da9e656ef11da9172c7","addr":"aa4e5ff5d78486413eef80525d20fc0a46befd5c"},{"mnemonic":"axis grace advance retreat fence prison traffic shield visual evoke upper they","master":"b0f1e554c9c4c38355939ec8641548df255dc8260ee2beb02eea8436359731fe","seed":"42d47d86e0eba00ac90f92e464cb034b25e3e261618ccb7893524e6103b8ab8edac9262e7417ca55cec0e5b90f0405d6b43b920317597d8b67c34f909b308ad9","priv":"0e986b99de5e1403218a3d6e64eda2c6e980002fc9345795464c6e100c4d214f","pub":"028193d72358fde04b71d553794171a3f6800d2d20d1d4821c2d411d9dcab044f0","addr":"68ef0232b6199e173a31b522f73b8740807e7991"},{"mnemonic":"speed advice script dynamic company foam mimic conduct wasp soft stick insane","master":"b0f61b56e248b14dc116231490779949a829920a9caf582fe25df4459e65108d","seed":"7b8b72a1bff2551f2e704e68f364b8d578e24bd6c51fead9805c2c33bf463dd462c793f73b88ca6353e8385a5baeba2c91e4efd6ccc2b80351cfed9d9a6d7738","priv":"32e5a08edf79a3192b221f978e209fee7f7d64f83c28ff57f47ff5757b727b14","pub":"02fa4ba71ba618ce2f1508b0386ceb0e09e202722353d9724a597cd680130c53e3","addr":"713ae3fbba6df605c843147183dfbf3a3fdd86c4"},{"mnemonic":"punch fame nasty actual betray melt find wink cross hobby double there","master":"a7bb2a4a7cc93d7dc12efe29071329febba1c999c4e7766172d9e53fe29cb0c8","seed":"6876d29989880fd1bae26463cd01cb148c68ea842603822657d0bdc708a8987cd33453087febfeda2f3ea53f2fcd65ee1c5f89b0cfd8aefefee2c81ed32c91e0","priv":"731b30c783b7cfeb7458db1e0c0db2586216b6ba661f1adff761977c782d24ef","pub":"03ee75f400c95ecc4b852cd1ea2b434f5cbdd2f6eb8a881f0f24a3d1098a6ce778","addr":"96ce0c791931f867dc4fddd2f091a552f1e57d26"},{"mnemonic":"feed session repair glad envelope pepper faculty earn hour slender cost boat","master":"d8507e0bbacaa494dd65a38d82c02f00d168ec8bdff9991f78ed5fc13ba81d38","seed":"aa9ac398fd8c94bef20e9b9a94bdb81fcafaec2453efaa2929730145528495515d7632de9cf558313a35d50c0428a15f01efc831379a696f632705bba7394ce8","priv":"ef95d3d563a0e774c8d486adeb2d22f4fcf4cddd80cd2a05471b691c12cfe0fd","pub":"026b711c8ed8ea414276c9d7c7a92739a350cbf01372d41c2160c046e1459223be","addr":"72da6e869b7d435ff2507e658acb26e0a50e6303"},{"mnemonic":"person affair gesture cherry intact day wrestle crew okay express throw large","master":"84a10e3f12a6d24e76cd66e934116f9478d8b1bf912fc61c9e00058f7c489f6a","seed":"5dbd3c2fe715a4dd9ca5129df8fddac1f699429636a58bcc2379791af11dcd77bd9b84f3d62539bf5eb41eb8fc966304cf334cc46133b7e42104a18733514777","priv":"337a826c33caf41a74b465c6981986d629c13a71aeef4c0e7c2b78fc3dff613b","pub":"03edadf784d13c4e22b33b61222e20348cc68e245d8b143dde09d37963e9e01eef","addr":"916fd4d732155d78fd412b4cd78abb49bac56c19"},{"mnemonic":"nose talent woman drip regular endless bar resemble friend mean frog cage","master":"1beb38f144a90141600a34813e98ac3cca43009e23c542b3009f3e22988b9705","seed":"aa324508ec3951c30fa4b32ca7a4ea48773c572652076a2a7e6aadec3faee23c3388663002b086483f39a1b08fd50ff233ddefded05f583211686d0323dd4d64","priv":"67109cb296022e46fbd12569cbbaeecec1843479bc716f7ed07ff996561f8196","pub":"03239409138ec1b5a60e5d72f894e95d599be18978d9f43bf201c85bc20210b473","addr":"580cdfe5a38f37a644204cd1d4b0094dffb982d6"},{"mnemonic":"undo thrive relax ancient menu milk sand race bargain evidence steak tomorrow","master":"1db1b33c9f26783cf9743ec719022a1280c8257ba11b2b03f35455cdfeb10ddb","seed":"b9905331927ef09ae2dbf5bec382cf3f18bd9cc03bbd4d21e8f63cbde32cd22abf07bdea578a201558f2a1f09f2fec8e3c7557f731a57439f1e348bd7530d9f3","priv":"c91c34d1a5218ecbfb63990b636d8bcbf6d7ba4723b70c960597f1b4ffb2854b","pub":"03c7d4b726c2ef316d8e60f0941e2af09c0cc1a9967aed825c322b629f74ebbab0","addr":"cbc5acf5001cb4d88fe88404cf3d1a919b127aa5"},{"mnemonic":"relax owner update nice speak office assault pottery uphold clump since ball","master":"5540b4c874952470d93f8a94689bd58c03c8bff373c74890e70b63caf9b5fe48","seed":"c3e8c04ce0d472761c468cdc13d04cd8fee5333a806259657923aad79d9bab8333329353e69cd3fc67833a7041a2c49f3c2b0654a4d243415f3f2761a4f7fa29","priv":"882ea08c9157b6bbfd686007ad668de373f34dbeb08e5d983a447a12c9efad3e","pub":"022f8b50589f2413d294e33de8fcac751c4c6ae54b359ba428c4a1ae28cd2ff57f","addr":"6ec1ae2736cb2a9e1dae6b5d5c7d408347db2dce"},{"mnemonic":"immune find story sadness depend debris popular swallow egg gauge firm drop","master":"fa46f28a8f32770393d3a3fd934141823d48ae561d8952ef3ac87839867840c7","seed":"6b5234df2c1b9ecb85d8493849e66186f98a828287e133cffc210140d63bee412ec58ede1968c2999485ef80710a83a99e7ffe205c404c5bda7346369c16f6fa","priv":"77cc4d765ee74267ea50ce3637ff9916370802a4940bffc8f7b76aac869ef80d","pub":"037d1e64685d2229c9b49baf2245511b3dc26733e1275c36f60555e2eeee32aead","addr":"80d9e410145ca65c65f143804e7e13f0572693af"},{"mnemonic":"airport refuse lake shuffle borrow depend agree oven huge hen brand reward","master":"b21a47b26023f1ed1963f81a2ec424c88520055cb2d69c329c76e6a354cccf91","seed":"7ae802a81c37abaf146f9c7606409640c53a3502da921347dbc260fc4fa5a164ec458480038ac10a3dc2c5ec15c600e72e011392413e13b9daeea82c2e9ef611","priv":"748f3e6cb6caafe5a188d528557ec1c1e817f990394bea8a011e3cbf6d00a3ec","pub":"029f0f4e5bf957c569e9cbb814295acaa1bb8bbdd549844246f86656ab700cd35f","addr":"005b3c2696248d3e45b43c88e258b2dee69ae542"},{"mnemonic":"slim trap alone fetch people skate middle since yard frown during smile","master":"1db54486ad20e5fd82e7c5bcab652cd01632014d66ccf0f7d6c39bc0a337fd77","seed":"30c3948e518b8ca06625fd7a1318984997ff587aa865207b54d5c9c469386e66e06656fe020665501a1f0a07636a250ddf5c127d5bd9ec497052b9e4ff2dc37d","priv":"0ce3645a3f7a1ae02535852fbfee9c59609eeb226a975ae24c94b7a13acb4d85","pub":"03b3f40812780bd4f8a596c0131ced87b9b981e4950f5217f44de7f777b4d29b35","addr":"7777090b6e5ae18d4a146a0c9c17a1a34cde74da"},{"mnemonic":"vague melody fine buffalo spread nation reduce spirit humor fruit spin diary","master":"7a5951d167793eb5d42307c68a3997fec7c34d56562dcab752c2559b97507e3c","seed":"aeb4a2ee7a25712bb76b26c654f5a79b4e92c25689799de2a11283a668aabc3d967d111e2bd98691dc2b72adb66188888999e0ce03ab2bf1b18e8d5d7f8c528d","priv":"d2dd273a93786422dc68e61e67dc0c48402af5964f85d5d785476bbcc68e99c5","pub":"0347a23bf9c802d6d826367a34219ff155a720b068bb0cc4f9c679d350f35a978a","addr":"88679cd2c43e562c21738ba5ffc8bff82575bc6d"},{"mnemonic":"ahead glad fame hip era kite pyramid endless sponsor tissue winner kite","master":"eafe3d2af7a63b644668dfd23b7f0868a1d6527b630860f79838fc520896e64e","seed":"91f06eed5517fa2367c272a18362085775cc9d8f13b2358ab32d0c626abd87aefb8ffdd1f37712d4c39fb625ff4aa56cfe06a3054e162bb62fb03755a19f970a","priv":"c8d580087355904e691ad5292775989853e59ce1d41d224f97d2d4b96f8514d1","pub":"0342c4be0ea075609aa181fb83ffa189ec9744c2a7c54f7d3fa2273ba01ae127e8","addr":"ebd946e96a89c8932ec788d66f3fe8c482622831"},{"mnemonic":"clump earth diary ostrich section column practice rapid hotel mom client adjust","master":"c6be4ea8b2810f07731b7258f2a2cf4a4bd0722e43081957bd74ccb5955bed55","seed":"04c2178510fe5f7afe60cf8718bc5240da95cc2a79d28fb2bce756a2fb0995f25c5921addae1932dcc4b62ee68b330d3abfe190f212f809816ee7c6d5b816095","priv":"d2ecfc9fffd24c8299647fc2f23a16a2e5b35ec6092563ae731d4737159ce03d","pub":"027c615b33b69f5599cb800a85073582bb2180f20bedd1bb3e8384bada13ab8f92","addr":"df913518315ba257805f9ea9f78c859428d101d9"},{"mnemonic":"teach salt dinner dinner escape cheap gate major bind armor dash gallery","master":"954d52c8574645c888e4eea6ca661fd1ca4764ca9e4243bc75610571a24ec5ac","seed":"7c3753fb498e2a48af89e5a39153382eb9591eb8a5bb2cc5b8bf690bb6d1365162bccfbc9d5e3688f48352f1f8915c376dfacc3c3cad9315fa60cb303161ac77","priv":"c3a850ce632a7ab061e378596cb4c66a6880d41f6b09b0868d8c7e96bde490fe","pub":"02a615c68dd2bb66d3cc9d7e46a0fa00510542471a19b1d48fe05355acf38903b6","addr":"db50721f5b6e0907490990182793ae796756bc7b"},{"mnemonic":"cement casino erupt clever gasp benefit response invest diet banner month hill","master":"97c777e73bebf40d39c4efe8fb74db3cedcf2e1ebd366520515ee2823a9c4d28","seed":"9344a709e0d53322b928e3128d1bc707216eb0e1ebb137f74fbde6cd066f88b86088793a5794df8cfbd6efb12c843399e8ccb958446fa558573b013d33236436","priv":"96464373c492c388bc4a2c421ed0f5017fb426ac95e55f0f322703b28012cf90","pub":"03e71c89b2629c032b6c9a35b46d572dd0db3dde47bd5919bed8457885553148b1","addr":"493af641ce946561f6cb3116a135fe6e6b1b0f13"},{"mnemonic":"supreme news pyramid sheriff attract volume zone innocent hat grunt gorilla mango","master":"2ba0cd68329e2b19d5c24c1d3fca44513151fc4a634e52756290967989883b52","seed":"efbf7e16af697b4dd62a876f62f08698e29531c05018bb6da7ce441340b0278353d5d08a88cb93c4fd9bdb14fb85ab857ea3e8ef13b49dabb20beae2f13af3fa","priv":"15b89635f69b28cee0aa00d0609b99f1a1dd3c83e3bd57032987146cd47cebb8","pub":"021ae715a05c4849519acbe8dbf7ff4031d18f57de1bcf9cb1a06d50e5ebdbf661","addr":"e3087b309db8490b23629cbe4d113c1ea5bb525e"},{"mnemonic":"way chat van put negative minute tail dress spawn crunch beef moment","master":"e0dff85e10808c3ac560957a46f5f86abbfc62251c8fd4c61cb5e089a0841e7a","seed":"eb14b38f90886c1a1d47ac42205b564a649a0cf6edbd88cda1c488ee700aae8b735d7e947efc5711e2cc02b2254690ff4a69d149d2e13affd6d9a3915ac9dceb","priv":"7fb5464c8bc2e1583105d34c6850fb332a578fea35dff9528422c8b7f3156242","pub":"02745f0fbe0b23688e9691f9c4a088bf1342100fe3b9f7e405df79bddd57f8e6e1","addr":"66d90273421fadbab93fb9b05ea6e572f8af7050"},{"mnemonic":"tattoo strong tool weapon blue cricket kick holiday medal club stage reason","master":"bc82d196675dbad1c24d78f4e400a8956297c6113d4004356963ca88617597b3","seed":"9cf6193178f1a6391105c79cc6d3d2e2a4fe97f44738f8f716fb5b17a3eacd4061f9bb7f0411b08d77dc10b16b9599e45e8ffa55ff7f8e5c9274bab71bfe120f","priv":"5925547ee089b4638743f0fabe33f925780772a65b87b8315acf7f523d044482","pub":"03bba775f325b1ad28ec0adf66c8e15f90d70368fa021be5db199a5188c0621eb4","addr":"1f63ff4af01b5b5f33e60b82646a39917b6a7305"},{"mnemonic":"rug diagram spend zebra occur neglect choose relax face when spell stem","master":"d7932ffb8f6b751543caed7158318a05f4686646e636b5725b9b0419fb66912b","seed":"b73957a412d9e4c677edef4cb3a376c7355f78bba347a61f44c85f76b2c8a3d8ac2bd6c3b70643bf19b8487dcdce3055aaf86921e29e5e6f89700e0e2bf00546","priv":"c827dfe5f1880d9c462985b915ff78a1ab615ff0840f3f125f618cef25e14a5c","pub":"031bfd2158660168795f38f980951921f6fa1d522ad460ac5f93dfc4a2eac91f7d","addr":"b866f1e9b5b7b00fbb6076915a0a2931cba6e029"},{"mnemonic":"faith bless there mountain stand cannon sick abstract fiscal theory begin easy","master":"9af948584294b3951e6c664423a12fdfe29a31d41546b911f3fcdf664399aa48","seed":"17b6451f4b9765fdc3ed280fb5a6141b8003c8c9d8c73afce3192e15012fd18431850ebcaa07fa08da2c648f0f97f45e33ebdea6c99f2f23a9e244a297596499","priv":"e759b35d18e8b60726e882a11ea830e30ddff6752a19bec6983fdecf655726b0","pub":"03151da31179657f296184543a1360bcb92983a12788b268db0c20d895e6c449b1","addr":"54ec389ea177e1a4fe2f98cd83f27cce218b9081"},{"mnemonic":"combine fine crowd enter check mule toward damage fortune bless topple source","master":"b831b7a1b85edf1945c892dd332419e7f3a5125229cdfe1c73cc0e964abb4b5c","seed":"d9456b80f01787607d9c3adecdd6fa299132d748ae4fab843b3802c798ea1bc0395f9a1dc29e1badccc742f3c4fa081bdd7b6f9ca8980009b75c892438020b9f","priv":"d9d037b9baf0796d8a151935c172b1f775c1875b3811bcfd6c3f477e74c5c54e","pub":"03c720f00c921ab13307d3790f742f0a40436fad9d999087c267107ce50f8fe2b9","addr":"4b5a1c53f8442c375e9af35937ff0471155c0bee"},{"mnemonic":"shift nut floor scorpion property sun either total follow glide special apology","master":"1a4520e80df55ad59d95fca8dfab5f09753f6e26f7f38f654f32e4fa6f3ff963","seed":"a9df829ec832270d1ef0b0b04542e351ab9145baf086231fbe9636120c18c8d545ed138c37c0612d296c915340f982b1d83bd408301de79c08e4580ce0ce8fdd","priv":"27b1742305c3921c0cc041dc79d6e3c83112828f3fd49e18f31cb0b422bc1c80","pub":"032b322eedf502edf5e6c24ad80ad4bde37e04de012b9bf9c8caa41151a9ccf74f","addr":"2ce4a3aeb7e0fc52c31121651346959d1cfcc1be"}] diff --git a/keys/keybase.go b/keys/keybase.go deleted file mode 100644 index b55658d2f..000000000 --- a/keys/keybase.go +++ /dev/null @@ -1,362 +0,0 @@ -package keys - -import ( - "bufio" - "fmt" - "os" - "strings" - - "github.com/pkg/errors" - "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/keys/bip39" - "github.com/tendermint/go-crypto/keys/hd" - dbm "github.com/tendermint/tmlibs/db" -) - -var _ Keybase = dbKeybase{} - -// Language is a language to create the BIP 39 mnemonic in. -// Currently, only english is supported though. -// Find a list of all supported languages in the BIP 39 spec (word lists). -type Language int - -const ( - // English is the default language to create a mnemonic. - // It is the only supported language by this package. - English Language = iota + 1 - // Japanese is currently not supported. - Japanese - // Korean is currently not supported. - Korean - // Spanish is currently not supported. - Spanish - // ChineseSimplified is currently not supported. - ChineseSimplified - // ChineseTraditional is currently not supported. - ChineseTraditional - // French is currently not supported. - French - // Italian is currently not supported. - Italian -) - -var ( - // ErrUnsupportedSigningAlgo is raised when the caller tries to use a different signing scheme than secp256k1. - ErrUnsupportedSigningAlgo = errors.New("unsupported signing algo: only secp256k1 is supported") - // ErrUnsupportedLanguage is raised when the caller tries to use a different language than english for creating - // a mnemonic sentence. - ErrUnsupportedLanguage = errors.New("unsupported language: only english is supported") -) - -// dbKeybase combines encryption and storage implementation to provide -// a full-featured key manager -type dbKeybase struct { - db dbm.DB -} - -// New creates a new keybase instance using the passed DB for reading and writing keys. -func New(db dbm.DB) Keybase { - return dbKeybase{ - db: db, - } -} - -// CreateMnemonic generates a new key and persists it to storage, encrypted -// using the provided password. -// It returns the generated mnemonic and the key Info. -// It returns an error if it fails to -// generate a key for the given algo type, or if another key is -// already stored under the same name. -func (kb dbKeybase) CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, mnemonic string, err error) { - if language != English { - return nil, "", ErrUnsupportedLanguage - } - if algo != Secp256k1 { - err = ErrUnsupportedSigningAlgo - return - } - - // default number of words (24): - mnemonicS, err := bip39.NewMnemonic(bip39.FreshKey) - if err != nil { - return - } - mnemonic = strings.Join(mnemonicS, " ") - seed := bip39.MnemonicToSeed(mnemonic) - info, err = kb.persistDerivedKey(seed, passwd, name, hd.FullFundraiserPath) - return -} - -// CreateFundraiserKey converts a mnemonic to a private key and persists it, -// encrypted with the given password. -// TODO(ismail) -func (kb dbKeybase) CreateFundraiserKey(name, mnemonic, passwd string) (info Info, err error) { - words := strings.Split(mnemonic, " ") - if len(words) != 12 { - err = fmt.Errorf("recovering only works with 12 word (fundraiser) mnemonics, got: %v words", len(words)) - return - } - seed, err := bip39.MnemonicToSeedWithErrChecking(mnemonic) - if err != nil { - return - } - info, err = kb.persistDerivedKey(seed, passwd, name, hd.FullFundraiserPath) - return -} - -func (kb dbKeybase) Derive(name, mnemonic, passwd string, params hd.BIP44Params) (info Info, err error) { - seed, err := bip39.MnemonicToSeedWithErrChecking(mnemonic) - if err != nil { - return - } - info, err = kb.persistDerivedKey(seed, passwd, name, params.String()) - - return -} -// CreateLedger creates a new locally-stored reference to a Ledger keypair -// It returns the created key info and an error if the Ledger could not be queried -func (kb dbKeybase) CreateLedger(name string, path crypto.DerivationPath, algo SigningAlgo) (Info, error) { - if algo != Secp256k1 { - return nil, ErrUnsupportedSigningAlgo - } - priv, err := crypto.NewPrivKeyLedgerSecp256k1(path) - if err != nil { - return nil, err - } - pub := priv.PubKey() - return kb.writeLedgerKey(pub, path, name), nil -} - -// CreateOffline creates a new reference to an offline keypair -// It returns the created key info -func (kb dbKeybase) CreateOffline(name string, pub crypto.PubKey) (Info, error) { - return kb.writeOfflineKey(pub, name), nil -} - - -func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath string) (info Info, err error) { - // create master key and derive first key: - masterPriv, ch := hd.ComputeMastersFromSeed(seed) - derivedPriv, err := hd.DerivePrivateKeyForPath(masterPriv, ch, fullHdPath) - if err != nil { - return - } - - // if we have a password, use it to encrypt the private key and store it - // else store the public key only - if passwd != "" { - info = kb.writeLocalKey(crypto.PrivKeySecp256k1(derivedPriv), name, passwd) - } else { - pubk := crypto.PrivKeySecp256k1(derivedPriv).PubKey() - info = kb.writeOfflineKey(pubk, name) - } - return -} - -// List returns the keys from storage in alphabetical order. -func (kb dbKeybase) List() ([]Info, error) { - var res []Info - iter := kb.db.Iterator(nil, nil) - defer iter.Close() - for ; iter.Valid(); iter.Next() { - info, err := readInfo(iter.Value()) - if err != nil { - return nil, err - } - res = append(res, info) - } - return res, nil -} - -// Get returns the public information about one key. -func (kb dbKeybase) Get(name string) (Info, error) { - bs := kb.db.Get(infoKey(name)) - return readInfo(bs) -} - -// Sign signs the msg with the named key. -// It returns an error if the key doesn't exist or the decryption fails. -func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig crypto.Signature, pub crypto.PubKey, err error) { - info, err := kb.Get(name) - if err != nil { - return - } - var priv crypto.PrivKey - switch info.(type) { - case localInfo: - linfo := info.(localInfo) - if linfo.PrivKeyArmor == "" { - err = fmt.Errorf("private key not available") - return - } - priv, err = unarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase) - if err != nil { - return nil, nil, err - } - case ledgerInfo: - linfo := info.(ledgerInfo) - priv, err = crypto.NewPrivKeyLedgerSecp256k1(linfo.Path) - if err != nil { - return - } - case offlineInfo: - linfo := info.(offlineInfo) - fmt.Printf("Bytes to sign:\n%s", msg) - buf := bufio.NewReader(os.Stdin) - fmt.Printf("\nEnter Amino-encoded signature:\n") - // Will block until user inputs the signature - signed, err := buf.ReadString('\n') - if err != nil { - return nil, nil, err - } - cdc.MustUnmarshalBinary([]byte(signed), sig) - return sig, linfo.GetPubKey(), nil - } - sig, err = priv.Sign(msg) - if err != nil { - return nil, nil, err - } - pub = priv.PubKey() - return sig, pub, nil -} - -func (kb dbKeybase) Export(name string) (armor string, err error) { - bz := kb.db.Get(infoKey(name)) - if bz == nil { - return "", fmt.Errorf("no key to export with name %s", name) - } - return armorInfoBytes(bz), nil -} - -// ExportPubKey returns public keys in ASCII armored format. -// Retrieve a Info object by its name and return the public key in -// a portable format. -func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) { - bz := kb.db.Get(infoKey(name)) - if bz == nil { - return "", fmt.Errorf("no key to export with name %s", name) - } - info, err := readInfo(bz) - if err != nil { - return - } - return armorPubKeyBytes(info.GetPubKey().Bytes()), nil -} - -func (kb dbKeybase) Import(name string, armor string) (err error) { - bz := kb.db.Get(infoKey(name)) - if len(bz) > 0 { - return errors.New("Cannot overwrite data for name " + name) - } - infoBytes, err := unarmorInfoBytes(armor) - if err != nil { - return - } - kb.db.Set(infoKey(name), infoBytes) - return nil -} - -// ImportPubKey imports ASCII-armored public keys. -// Store a new Info object holding a public key only, i.e. it will -// not be possible to sign with it as it lacks the secret key. -func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) { - bz := kb.db.Get(infoKey(name)) - if len(bz) > 0 { - return errors.New("Cannot overwrite data for name " + name) - } - pubBytes, err := unarmorPubKeyBytes(armor) - if err != nil { - return - } - pubKey, err := crypto.PubKeyFromBytes(pubBytes) - if err != nil { - return - } - kb.writeOfflineKey(pubKey, name) - return -} - -// Delete removes key forever, but we must present the -// proper passphrase before deleting it (for security). -// A passphrase of 'yes' is used to delete stored -// references to offline and Ledger / HW wallet keys -func (kb dbKeybase) Delete(name, passphrase string) error { - // verify we have the proper password before deleting - info, err := kb.Get(name) - if err != nil { - return err - } - switch info.(type) { - case localInfo: - linfo := info.(localInfo) - _, err = unarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase) - if err != nil { - return err - } - kb.db.DeleteSync(infoKey(name)) - return nil - case ledgerInfo: - case offlineInfo: - if passphrase != "yes" { - return fmt.Errorf("enter exactly 'yes' to delete the key") - } - kb.db.DeleteSync(infoKey(name)) - return nil - } - return nil -} - -// Update changes the passphrase with which an already stored key is -// encrypted. -// -// oldpass must be the current passphrase used for encryption, -// newpass will be the only valid passphrase from this time forward. -func (kb dbKeybase) Update(name, oldpass, newpass string) error { - info, err := kb.Get(name) - if err != nil { - return err - } - switch info.(type) { - case localInfo: - linfo := info.(localInfo) - key, err := unarmorDecryptPrivKey(linfo.PrivKeyArmor, oldpass) - if err != nil { - return err - } - kb.writeLocalKey(key, name, newpass) - return nil - default: - return fmt.Errorf("locally stored key required") - } -} - -func (kb dbKeybase) writeLocalKey(priv crypto.PrivKey, name, passphrase string) Info { - // encrypt private key using passphrase - privArmor := encryptArmorPrivKey(priv, passphrase) - // make Info - pub := priv.PubKey() - info := newLocalInfo(name, pub, privArmor) - kb.writeInfo(info, name) - return info -} - -func (kb dbKeybase) writeLedgerKey(pub crypto.PubKey, path crypto.DerivationPath, name string) Info { - info := newLedgerInfo(name, pub, path) - kb.writeInfo(info, name) - return info -} - -func (kb dbKeybase) writeOfflineKey(pub crypto.PubKey, name string) Info { - info := newOfflineInfo(name, pub) - kb.writeInfo(info, name) - return info -} - -func (kb dbKeybase) writeInfo(info Info, name string) { - // write the info by key - kb.db.SetSync(infoKey(name), writeInfo(info)) -} - -func infoKey(name string) []byte { - return []byte(fmt.Sprintf("%s.info", name)) -} diff --git a/keys/keybase_test.go b/keys/keybase_test.go deleted file mode 100644 index a3957f8e9..000000000 --- a/keys/keybase_test.go +++ /dev/null @@ -1,383 +0,0 @@ -package keys_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/keys" - "github.com/tendermint/go-crypto/keys/hd" - - dbm "github.com/tendermint/tmlibs/db" -) - -// TestKeyManagement makes sure we can manipulate these keys well -func TestKeyManagement(t *testing.T) { - // make the storage with reasonable defaults - cstore := keys.New( - dbm.NewMemDB(), - ) - - algo := keys.Secp256k1 - n1, n2, n3 := "personal", "business", "other" - p1, p2 := "1234", "really-secure!@#$" - - // Check empty state - l, err := cstore.List() - require.Nil(t, err) - assert.Empty(t, l) - - _, _, err = cstore.CreateMnemonic(n1, keys.English, p1, keys.Ed25519) - assert.Error(t, err, "ed25519 keys are currently not supported by keybase") - - // create some keys - _, err = cstore.Get(n1) - assert.Error(t, err) - i, _, err := cstore.CreateMnemonic(n1, keys.English, p1, algo) - - require.NoError(t, err) - require.Equal(t, n1, i.GetName()) - _, _, err = cstore.CreateMnemonic(n2, keys.English, p2, algo) - require.NoError(t, err) - - // we can get these keys - i2, err := cstore.Get(n2) - assert.NoError(t, err) - _, err = cstore.Get(n3) - assert.NotNil(t, err) - - // list shows them in order - keyS, err := cstore.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - // note these are in alphabetical order - assert.Equal(t, n2, keyS[0].GetName()) - assert.Equal(t, n1, keyS[1].GetName()) - assert.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) - - // deleting a key removes it - err = cstore.Delete("bad name", "foo") - require.NotNil(t, err) - err = cstore.Delete(n1, p1) - require.NoError(t, err) - keyS, err = cstore.List() - require.NoError(t, err) - assert.Equal(t, 1, len(keyS)) - _, err = cstore.Get(n1) - assert.Error(t, err) - - // create an offline key - o1 := "offline" - priv1 := crypto.GenPrivKeyEd25519() - pub1 := priv1.PubKey() - i, err = cstore.CreateOffline(o1, pub1) - require.Nil(t, err) - require.Equal(t, pub1, i.GetPubKey()) - require.Equal(t, o1, i.GetName()) - keyS, err = cstore.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - - // delete the offline key - err = cstore.Delete(o1, "no") - require.NotNil(t, err) - err = cstore.Delete(o1, "yes") - require.NoError(t, err) - keyS, err = cstore.List() - require.NoError(t, err) - require.Equal(t, 1, len(keyS)) -} - -// TestSignVerify does some detailed checks on how we sign and validate -// signatures -func TestSignVerify(t *testing.T) { - cstore := keys.New( - dbm.NewMemDB(), - ) - algo := keys.Secp256k1 - - n1, n2, n3 := "some dude", "a dudette", "dude-ish" - p1, p2, p3 := "1234", "foobar", "foobar" - - // create two users and get their info - i1, _, err := cstore.CreateMnemonic(n1, keys.English, p1, algo) - require.Nil(t, err) - - i2, _, err := cstore.CreateMnemonic(n2, keys.English, p2, algo) - require.Nil(t, err) - - // Import a public key - armor, err := cstore.ExportPubKey(n2) - require.Nil(t, err) - cstore.ImportPubKey(n3, armor) - i3, err := cstore.Get(n3) - require.NoError(t, err) - require.Equal(t, i3.GetName(), n3) - - - // let's try to sign some messages - d1 := []byte("my first message") - d2 := []byte("some other important info!") - d3 := []byte("feels like I forgot something...") - - // try signing both data with both keys... - s11, pub1, err := cstore.Sign(n1, p1, d1) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s12, pub1, err := cstore.Sign(n1, p1, d2) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s21, pub2, err := cstore.Sign(n2, p2, d1) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - s22, pub2, err := cstore.Sign(n2, p2, d2) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - // let's try to validate and make sure it only works when everything is proper - cases := []struct { - key crypto.PubKey - data []byte - sig crypto.Signature - valid bool - }{ - // proper matches - {i1.GetPubKey(), d1, s11, true}, - // change data, pubkey, or signature leads to fail - {i1.GetPubKey(), d2, s11, false}, - {i2.GetPubKey(), d1, s11, false}, - {i1.GetPubKey(), d1, s21, false}, - // make sure other successes - {i1.GetPubKey(), d2, s12, true}, - {i2.GetPubKey(), d1, s21, true}, - {i2.GetPubKey(), d2, s22, true}, - } - - for i, tc := range cases { - valid := tc.key.VerifyBytes(tc.data, tc.sig) - assert.Equal(t, tc.valid, valid, "%d", i) - } - - // Now try to sign data with a secret-less key - _, _, err = cstore.Sign(n3, p3, d3) - assert.NotNil(t, err) -} - -func assertPassword(t *testing.T, cstore keys.Keybase, name, pass, badpass string) { - err := cstore.Update(name, badpass, pass) - assert.NotNil(t, err) - err = cstore.Update(name, pass, pass) - assert.Nil(t, err, "%+v", err) -} - -// TestExportImport tests exporting and importing keys. -func TestExportImport(t *testing.T) { - - // make the storage with reasonable defaults - db := dbm.NewMemDB() - cstore := keys.New( - db, - ) - - info, _, err := cstore.CreateMnemonic("john", keys.English,"secretcpw", keys.Secp256k1) - assert.NoError(t, err) - assert.Equal(t, info.GetName(), "john") - - john, err := cstore.Get("john") - assert.NoError(t, err) - assert.Equal(t, info.GetName(), "john") - johnAddr := info.GetPubKey().Address() - - armor, err := cstore.Export("john") - assert.NoError(t, err) - - err = cstore.Import("john2", armor) - assert.NoError(t, err) - - john2, err := cstore.Get("john2") - assert.NoError(t, err) - - assert.Equal(t, john.GetPubKey().Address(), johnAddr) - assert.Equal(t, john.GetName(), "john") - assert.Equal(t, john, john2) -} -// -func TestExportImportPubKey(t *testing.T) { - // make the storage with reasonable defaults - db := dbm.NewMemDB() - cstore := keys.New( - db, - ) - - // CreateMnemonic a private-public key pair and ensure consistency - notPasswd := "n9y25ah7" - info, _, err := cstore.CreateMnemonic("john", keys.English, notPasswd, keys.Secp256k1) - assert.Nil(t, err) - assert.NotEqual(t, info, "") - assert.Equal(t, info.GetName(), "john") - addr := info.GetPubKey().Address() - john, err := cstore.Get("john") - assert.NoError(t, err) - assert.Equal(t, john.GetName(), "john") - assert.Equal(t, john.GetPubKey().Address(), addr) - - // Export the public key only - armor, err := cstore.ExportPubKey("john") - assert.NoError(t, err) - // Import it under a different name - err = cstore.ImportPubKey("john-pubkey-only", armor) - assert.NoError(t, err) - // Ensure consistency - john2, err := cstore.Get("john-pubkey-only") - assert.NoError(t, err) - // Compare the public keys - assert.True(t, john.GetPubKey().Equals(john2.GetPubKey())) - // Ensure the original key hasn't changed - john, err = cstore.Get("john") - assert.NoError(t, err) - assert.Equal(t, john.GetPubKey().Address(), addr) - assert.Equal(t, john.GetName(), "john") - - // Ensure keys cannot be overwritten - err = cstore.ImportPubKey("john-pubkey-only", armor) - assert.NotNil(t, err) -} - -// TestAdvancedKeyManagement verifies update, import, export functionality -func TestAdvancedKeyManagement(t *testing.T) { - - // make the storage with reasonable defaults - cstore := keys.New( - dbm.NewMemDB(), - ) - - algo := keys.Secp256k1 - n1, n2 := "old-name", "new name" - p1, p2 := "1234", "foobar" - - // make sure key works with initial password - _, _, err := cstore.CreateMnemonic(n1, keys.English, p1, algo) - require.Nil(t, err, "%+v", err) - assertPassword(t, cstore, n1, p1, p2) - - // update password requires the existing password - err = cstore.Update(n1, "jkkgkg", p2) - assert.NotNil(t, err) - assertPassword(t, cstore, n1, p1, p2) - - // then it changes the password when correct - err = cstore.Update(n1, p1, p2) - assert.NoError(t, err) - // p2 is now the proper one! - assertPassword(t, cstore, n1, p2, p1) - - // exporting requires the proper name and passphrase - _, err = cstore.Export(n1 + ".notreal") - assert.NotNil(t, err) - _, err = cstore.Export(" " + n1) - assert.NotNil(t, err) - _, err = cstore.Export(n1 + " ") - assert.NotNil(t, err) - _, err = cstore.Export("") - assert.NotNil(t, err) - exported, err := cstore.Export(n1) - require.Nil(t, err, "%+v", err) - - // import succeeds - err = cstore.Import(n2, exported) - assert.NoError(t, err) - - // second import fails - err = cstore.Import(n2, exported) - assert.NotNil(t, err) -} - -// TestSeedPhrase verifies restoring from a seed phrase -func TestSeedPhrase(t *testing.T) { - - // make the storage with reasonable defaults - cstore := keys.New( - dbm.NewMemDB(), - ) - - algo := keys.Secp256k1 - n1, n2 := "lost-key", "found-again" - p1, p2 := "1234", "foobar" - - // make sure key works with initial password - info, mnemonic, err := cstore.CreateMnemonic(n1, keys.English, p1, algo) - require.Nil(t, err, "%+v", err) - assert.Equal(t, n1, info.GetName()) - assert.NotEmpty(t, mnemonic) - - // now, let us delete this key - err = cstore.Delete(n1, p1) - require.Nil(t, err, "%+v", err) - _, err = cstore.Get(n1) - require.NotNil(t, err) - - // let us re-create it from the mnemonic-phrase - params := *hd.NewFundraiserParams(0 ,0 ) - newInfo, err := cstore.Derive(n2,mnemonic, p2, params) - require.NoError(t, err) - assert.Equal(t, n2, newInfo.GetName()) - assert.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) - assert.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) -} - -func ExampleNew() { - // Select the encryption and storage for your cryptostore - cstore := keys.New( - dbm.NewMemDB(), - ) - - sec := keys.Secp256k1 - - // Add keys and see they return in alphabetical order - bob, _, err := cstore.CreateMnemonic("Bob", keys.English, "friend", sec) - if err != nil { - // this should never happen - fmt.Println(err) - } else { - // return info here just like in List - fmt.Println(bob.GetName()) - } - cstore.CreateMnemonic("Alice", keys.English, "secret", sec) - cstore.CreateMnemonic("Carl", keys.English, "mitm", sec) - info, _ := cstore.List() - for _, i := range info { - fmt.Println(i.GetName()) - } - - // We need to use passphrase to generate a signature - tx := []byte("deadbeef") - sig, pub, err := cstore.Sign("Bob", "friend", tx) - if err != nil { - fmt.Println("don't accept real passphrase") - } - - // and we can validate the signature with publicly available info - binfo, _ := cstore.Get("Bob") - if !binfo.GetPubKey().Equals(bob.GetPubKey()) { - fmt.Println("Get and Create return different keys") - } - - if pub.Equals(binfo.GetPubKey()) { - fmt.Println("signed by Bob") - } - if !pub.VerifyBytes(tx, sig) { - fmt.Println("invalid signature") - } - - // Output: - // Bob - // Alice - // Bob - // Carl - // signed by Bob -} diff --git a/keys/keys.go b/keys/keys.go deleted file mode 100644 index b3fad70f3..000000000 --- a/keys/keys.go +++ /dev/null @@ -1,12 +0,0 @@ -package keys - -// SigningAlgo defines an algorithm to derive key-pairs which can be used for cryptographic signing. -type SigningAlgo string - -const ( - // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. - Secp256k1 = SigningAlgo("secp256k1") - // Ed25519 represents the Ed25519 signature system. - // It is currently not supported for end-user keys (wallets/ledgers). - Ed25519 = SigningAlgo("ed25519") -) \ No newline at end of file diff --git a/keys/keys.toml b/keys/keys.toml deleted file mode 100644 index f9eb95e1c..000000000 --- a/keys/keys.toml +++ /dev/null @@ -1,2 +0,0 @@ -output = "text" -keydir = ".mykeys" diff --git a/keys/mintkey.go b/keys/mintkey.go deleted file mode 100644 index 264a9747d..000000000 --- a/keys/mintkey.go +++ /dev/null @@ -1,115 +0,0 @@ -package keys - -import ( - "encoding/hex" - "fmt" - - cmn "github.com/tendermint/tmlibs/common" - - "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/keys/bcrypt" -) - -const ( - blockTypePrivKey = "TENDERMINT PRIVATE KEY" - blockTypeKeyInfo = "TENDERMINT KEY INFO" - blockTypePubKey = "TENDERMINT PUBLIC KEY" -) - -func armorInfoBytes(bz []byte) string { - return armorBytes(bz, blockTypeKeyInfo) -} - -func armorPubKeyBytes(bz []byte) string { - return armorBytes(bz, blockTypePubKey) -} - -func armorBytes(bz []byte, blockType string) string { - header := map[string]string{ - "type": "Info", - "version": "0.0.0", - } - return crypto.EncodeArmor(blockType, header, bz) -} - -func unarmorInfoBytes(armorStr string) (bz []byte, err error) { - return unarmorBytes(armorStr, blockTypeKeyInfo) -} - -func unarmorPubKeyBytes(armorStr string) (bz []byte, err error) { - return unarmorBytes(armorStr, blockTypePubKey) -} - -func unarmorBytes(armorStr, blockType string) (bz []byte, err error) { - bType, header, bz, err := crypto.DecodeArmor(armorStr) - if err != nil { - return - } - if bType != blockType { - err = fmt.Errorf("Unrecognized armor type %q, expected: %q", bType, blockType) - return - } - if header["version"] != "0.0.0" { - err = fmt.Errorf("Unrecognized version: %v", header["version"]) - return - } - return -} - -func encryptArmorPrivKey(privKey crypto.PrivKey, passphrase string) string { - saltBytes, encBytes := encryptPrivKey(privKey, passphrase) - header := map[string]string{ - "kdf": "bcrypt", - "salt": fmt.Sprintf("%X", saltBytes), - } - armorStr := crypto.EncodeArmor(blockTypePrivKey, header, encBytes) - return armorStr -} - -func unarmorDecryptPrivKey(armorStr string, passphrase string) (crypto.PrivKey, error) { - var privKey crypto.PrivKey - blockType, header, encBytes, err := crypto.DecodeArmor(armorStr) - if err != nil { - return privKey, err - } - if blockType != blockTypePrivKey { - return privKey, fmt.Errorf("Unrecognized armor type: %v", blockType) - } - if header["kdf"] != "bcrypt" { - return privKey, fmt.Errorf("Unrecognized KDF type: %v", header["KDF"]) - } - if header["salt"] == "" { - return privKey, fmt.Errorf("Missing salt bytes") - } - saltBytes, err := hex.DecodeString(header["salt"]) - if err != nil { - return privKey, fmt.Errorf("Error decoding salt: %v", err.Error()) - } - privKey, err = decryptPrivKey(saltBytes, encBytes, passphrase) - return privKey, err -} - -func encryptPrivKey(privKey crypto.PrivKey, passphrase string) (saltBytes []byte, encBytes []byte) { - saltBytes = crypto.CRandBytes(16) - key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 12) // TODO parameterize. 12 is good today (2016) - if err != nil { - cmn.Exit("Error generating bcrypt key from passphrase: " + err.Error()) - } - key = crypto.Sha256(key) // Get 32 bytes - privKeyBytes := privKey.Bytes() - return saltBytes, crypto.EncryptSymmetric(privKeyBytes, key) -} - -func decryptPrivKey(saltBytes []byte, encBytes []byte, passphrase string) (privKey crypto.PrivKey, err error) { - key, err := bcrypt.GenerateFromPassword(saltBytes, []byte(passphrase), 12) // TODO parameterize. 12 is good today (2016) - if err != nil { - cmn.Exit("Error generating bcrypt key from passphrase: " + err.Error()) - } - key = crypto.Sha256(key) // Get 32 bytes - privKeyBytes, err := crypto.DecryptSymmetric(encBytes, key) - if err != nil { - return privKey, err - } - privKey, err = crypto.PrivKeyFromBytes(privKeyBytes) - return privKey, err -} diff --git a/keys/types.go b/keys/types.go deleted file mode 100644 index 09fbb399e..000000000 --- a/keys/types.go +++ /dev/null @@ -1,142 +0,0 @@ -package keys - -import ( - crypto "github.com/tendermint/go-crypto" - "github.com/tendermint/go-crypto/keys/hd" -) - -// Keybase exposes operations on a generic keystore -type Keybase interface { - - // CRUD on the keystore - List() ([]Info, error) - Get(name string) (Info, error) - Delete(name, passphrase string) error - - // Sign some bytes, looking up the private key to use - Sign(name, passphrase string, msg []byte) (crypto.Signature, crypto.PubKey, error) - - // CreateMnemonic creates a new mnemonic, and derives a hierarchical deterministic - // key from that. - CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, seed string, err error) - // CreateFundraiserKey takes a mnemonic and derives, a password - CreateFundraiserKey(name, mnemonic, passwd string) (info Info, err error) - // Derive derives a key from the passed mnemonic using a BIP44 path. - Derive(name, mnemonic, passwd string, params hd.BIP44Params) (Info, error) - // Create, store, and return a new Ledger key reference - CreateLedger(name string, path crypto.DerivationPath, algo SigningAlgo) (info Info, err error) - - // Create, store, and return a new offline key reference - CreateOffline(name string, pubkey crypto.PubKey) (info Info, err error) - - // The following operations will *only* work on locally-stored keys - Update(name, oldpass, newpass string) error - Import(name string, armor string) (err error) - ImportPubKey(name string, armor string) (err error) - Export(name string) (armor string, err error) - ExportPubKey(name string) (armor string, err error) -} - -// Info is the publicly exposed information about a keypair -type Info interface { - // Human-readable type for key listing - GetType() string - // Name of the key - GetName() string - // Public key - GetPubKey() crypto.PubKey -} - -var _ Info = &localInfo{} -var _ Info = &ledgerInfo{} -var _ Info = &offlineInfo{} - -// localInfo is the public information about a locally stored key -type localInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - PrivKeyArmor string `json:"privkey.armor"` -} - -func newLocalInfo(name string, pub crypto.PubKey, privArmor string) Info { - return &localInfo{ - Name: name, - PubKey: pub, - PrivKeyArmor: privArmor, - } -} - -func (i localInfo) GetType() string { - return "local" -} - -func (i localInfo) GetName() string { - return i.Name -} - -func (i localInfo) GetPubKey() crypto.PubKey { - return i.PubKey -} - -// ledgerInfo is the public information about a Ledger key -type ledgerInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - Path crypto.DerivationPath `json:"path"` -} - -func newLedgerInfo(name string, pub crypto.PubKey, path crypto.DerivationPath) Info { - return &ledgerInfo{ - Name: name, - PubKey: pub, - Path: path, - } -} - -func (i ledgerInfo) GetType() string { - return "ledger" -} - -func (i ledgerInfo) GetName() string { - return i.Name -} - -func (i ledgerInfo) GetPubKey() crypto.PubKey { - return i.PubKey -} - -// offlineInfo is the public information about an offline key -type offlineInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` -} - -func newOfflineInfo(name string, pub crypto.PubKey) Info { - return &offlineInfo{ - Name: name, - PubKey: pub, - } -} - -func (i offlineInfo) GetType() string { - return "offline" -} - -func (i offlineInfo) GetName() string { - return i.Name -} - -func (i offlineInfo) GetPubKey() crypto.PubKey { - return i.PubKey -} - -// encoding info -func writeInfo(i Info) []byte { - return cdc.MustMarshalBinary(i) -} - -// decoding info -func readInfo(bz []byte) (info Info, err error) { - err = cdc.UnmarshalBinary(bz, &info) - return -} diff --git a/keys/wire.go b/keys/wire.go deleted file mode 100644 index 7cde0dd45..000000000 --- a/keys/wire.go +++ /dev/null @@ -1,16 +0,0 @@ -package keys - -import ( - amino "github.com/tendermint/go-amino" - crypto "github.com/tendermint/go-crypto" -) - -var cdc = amino.NewCodec() - -func init() { - crypto.RegisterAmino(cdc) - cdc.RegisterInterface((*Info)(nil), nil) - cdc.RegisterConcrete(localInfo{}, "crypto/keys/localInfo", nil) - cdc.RegisterConcrete(ledgerInfo{}, "crypto/keys/ledgerInfo", nil) - cdc.RegisterConcrete(offlineInfo{}, "crypto/keys/offlineInfo", nil) -} From 7ebc7c08e7de58540762d6ab2fc688677bef80c9 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 20 Jun 2018 14:30:57 -0700 Subject: [PATCH 272/273] delete keys package - also delete ledger code and deps (thx cwgoes) Signed-off-by: Liamsi --- Gopkg.toml | 12 ----- Makefile | 2 +- amino.go | 2 - encode_test.go | 1 - ledger_common.go | 19 ------- ledger_secp256k1.go | 124 -------------------------------------------- ledger_test.go | 63 ---------------------- 7 files changed, 1 insertion(+), 222 deletions(-) delete mode 100644 ledger_common.go delete mode 100644 ledger_secp256k1.go delete mode 100644 ledger_test.go diff --git a/Gopkg.toml b/Gopkg.toml index 92bfecacd..a614df866 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -28,10 +28,6 @@ name = "github.com/btcsuite/btcutil" branch = "master" -[[constraint]] - name = "github.com/pkg/errors" - version = "0.8.0" - [[constraint]] name = "github.com/stretchr/testify" version = "1.2.1" @@ -48,14 +44,6 @@ name = "github.com/tendermint/tmlibs" version = "0.8.1" -[[constraint]] - name = "github.com/tyler-smith/go-bip39" - branch = "master" - -[[constraint]] - name = "github.com/zondax/ledger-goclient" - revision = "065cbf938a16f20335c40cfe180f9cd4955c6a5a" - [prune] go-tests = true unused-packages = true diff --git a/Makefile b/Makefile index 96f4ae06d..a4fd3c37f 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ get_vendor_deps: ### Testing test: - go test -p 1 $(shell go list ./... | grep -v vendor) + CGO_ENABLED=0 go test -p 1 $(shell go list ./... | grep -v vendor) ######################################## ### Formatting, linting, and vetting diff --git a/amino.go b/amino.go index 63e4c4ac3..2a57afdee 100644 --- a/amino.go +++ b/amino.go @@ -28,8 +28,6 @@ func RegisterAmino(cdc *amino.Codec) { "tendermint/PrivKeyEd25519", nil) cdc.RegisterConcrete(PrivKeySecp256k1{}, "tendermint/PrivKeySecp256k1", nil) - cdc.RegisterConcrete(PrivKeyLedgerSecp256k1{}, - "tendermint/PrivKeyLedgerSecp256k1", nil) cdc.RegisterInterface((*Signature)(nil), nil) cdc.RegisterConcrete(SignatureEd25519{}, diff --git a/encode_test.go b/encode_test.go index 025b09c80..a122f20e2 100644 --- a/encode_test.go +++ b/encode_test.go @@ -50,7 +50,6 @@ func ExamplePrintRegisteredTypes() { //| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE987 | 0x21 | | //| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288910 | 0x40 | | //| PrivKeySecp256k1 | tendermint/PrivKeySecp256k1 | 0xE1B0F79B | 0x20 | | - //| PrivKeyLedgerSecp256k1 | tendermint/PrivKeyLedgerSecp256k1 | 0x10CAB393 | variable | | //| SignatureEd25519 | tendermint/SignatureEd25519 | 0x2031EA53 | 0x40 | | //| SignatureSecp256k1 | tendermint/SignatureSecp256k1 | 0x7FC4A495 | variable | | } diff --git a/ledger_common.go b/ledger_common.go deleted file mode 100644 index 39f15464a..000000000 --- a/ledger_common.go +++ /dev/null @@ -1,19 +0,0 @@ -package crypto - -import ( - ledger "github.com/zondax/ledger-goclient" -) - -var device *ledger.Ledger - -// Ledger derivation path -type DerivationPath = []uint32 - -// getLedger gets a copy of the device, and caches it -func getLedger() (*ledger.Ledger, error) { - var err error - if device == nil { - device, err = ledger.FindLedger() - } - return device, err -} diff --git a/ledger_secp256k1.go b/ledger_secp256k1.go deleted file mode 100644 index 21dfbb8b5..000000000 --- a/ledger_secp256k1.go +++ /dev/null @@ -1,124 +0,0 @@ -package crypto - -import ( - "fmt" - - secp256k1 "github.com/btcsuite/btcd/btcec" - ledger "github.com/zondax/ledger-goclient" -) - -func pubkeyLedgerSecp256k1(device *ledger.Ledger, path DerivationPath) (pub PubKey, err error) { - key, err := device.GetPublicKeySECP256K1(path) - if err != nil { - return nil, fmt.Errorf("error fetching public key: %v", err) - } - var p PubKeySecp256k1 - // Reserialize in the 33-byte compressed format - cmp, err := secp256k1.ParsePubKey(key[:], secp256k1.S256()) - copy(p[:], cmp.SerializeCompressed()) - pub = p - return -} - -func signLedgerSecp256k1(device *ledger.Ledger, path DerivationPath, msg []byte) (sig Signature, err error) { - bsig, err := device.SignSECP256K1(path, msg) - if err != nil { - return sig, err - } - sig = SignatureSecp256k1FromBytes(bsig) - return -} - -// PrivKeyLedgerSecp256k1 implements PrivKey, calling the ledger nano -// we cache the PubKey from the first call to use it later -type PrivKeyLedgerSecp256k1 struct { - // PubKey should be private, but we want to encode it via go-amino - // so we can view the address later, even without having the ledger - // attached - CachedPubKey PubKey - Path DerivationPath -} - -// NewPrivKeyLedgerSecp256k1 will generate a new key and store the -// public key for later use. -func NewPrivKeyLedgerSecp256k1(path DerivationPath) (PrivKey, error) { - var pk PrivKeyLedgerSecp256k1 - pk.Path = path - // cache the pubkey for later use - pubKey, err := pk.getPubKey() - if err != nil { - return nil, err - } - pk.CachedPubKey = pubKey - return &pk, err -} - -// ValidateKey allows us to verify the sanity of a key -// after loading it from disk -func (pk PrivKeyLedgerSecp256k1) ValidateKey() error { - // getPubKey will return an error if the ledger is not - pub, err := pk.getPubKey() - if err != nil { - return err - } - // verify this matches cached address - if !pub.Equals(pk.CachedPubKey) { - return fmt.Errorf("cached key does not match retrieved key") - } - return nil -} - -// AssertIsPrivKeyInner fulfils PrivKey Interface -func (pk *PrivKeyLedgerSecp256k1) AssertIsPrivKeyInner() {} - -// Bytes fulfils PrivKey Interface - but it stores the cached pubkey so we can verify -// the same key when we reconnect to a ledger -func (pk PrivKeyLedgerSecp256k1) Bytes() []byte { - return cdc.MustMarshalBinaryBare(pk) -} - -// Sign calls the ledger and stores the PubKey for future use -// -// Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, -// returning an error, so this should only trigger if the privkey is held -// in memory for a while before use. -func (pk PrivKeyLedgerSecp256k1) Sign(msg []byte) (Signature, error) { - dev, err := getLedger() - if err != nil { - return nil, err - } - sig, err := signLedgerSecp256k1(dev, pk.Path, msg) - if err != nil { - return nil, err - } - return sig, nil -} - -// PubKey returns the stored PubKey -func (pk PrivKeyLedgerSecp256k1) PubKey() PubKey { - return pk.CachedPubKey -} - -// getPubKey reads the pubkey the ledger itself -// since this involves IO, it may return an error, which is not exposed -// in the PubKey interface, so this function allows better error handling -func (pk PrivKeyLedgerSecp256k1) getPubKey() (key PubKey, err error) { - dev, err := getLedger() - if err != nil { - return key, fmt.Errorf("cannot connect to Ledger device - error: %v", err) - } - key, err = pubkeyLedgerSecp256k1(dev, pk.Path) - if err != nil { - return key, fmt.Errorf("please open Cosmos app on the Ledger device - error: %v", err) - } - return key, err -} - -// Equals fulfils PrivKey Interface - makes sure both keys refer to the -// same -func (pk PrivKeyLedgerSecp256k1) Equals(other PrivKey) bool { - if ledger, ok := other.(*PrivKeyLedgerSecp256k1); ok { - return pk.CachedPubKey.Equals(ledger.CachedPubKey) - } - return false -} diff --git a/ledger_test.go b/ledger_test.go deleted file mode 100644 index 83390cc36..000000000 --- a/ledger_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package crypto - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestRealLedgerSecp256k1(t *testing.T) { - - if os.Getenv("WITH_LEDGER") == "" { - t.Skip("Set WITH_LEDGER to run code on real ledger") - } - msg := []byte("kuhehfeohg") - - path := DerivationPath{44, 60, 0, 0, 0} - - priv, err := NewPrivKeyLedgerSecp256k1(path) - require.Nil(t, err, "%+v", err) - pub := priv.PubKey() - sig, err := priv.Sign(msg) - require.Nil(t, err) - - valid := pub.VerifyBytes(msg, sig) - assert.True(t, valid) - - // now, let's serialize the key and make sure it still works - bs := priv.Bytes() - priv2, err := PrivKeyFromBytes(bs) - require.Nil(t, err, "%+v", err) - - // make sure we get the same pubkey when we load from disk - pub2 := priv2.PubKey() - require.Equal(t, pub, pub2) - - // signing with the loaded key should match the original pubkey - sig, err = priv2.Sign(msg) - require.Nil(t, err) - valid = pub.VerifyBytes(msg, sig) - assert.True(t, valid) - - // make sure pubkeys serialize properly as well - bs = pub.Bytes() - bpub, err := PubKeyFromBytes(bs) - require.NoError(t, err) - assert.Equal(t, pub, bpub) -} - -// TestRealLedgerErrorHandling calls. These tests assume -// the ledger is not plugged in.... -func TestRealLedgerErrorHandling(t *testing.T) { - if os.Getenv("WITH_LEDGER") != "" { - t.Skip("Skipping on WITH_LEDGER as it tests unplugged cases") - } - - // first, try to generate a key, must return an error - // (no panic) - path := DerivationPath{44, 60, 0, 0, 0} - _, err := NewPrivKeyLedgerSecp256k1(path) - require.Error(t, err) -} From c7a842a4e2c339aa5dd812735211ffbcc25bce24 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 20 Jun 2018 23:31:57 +0200 Subject: [PATCH 273/273] Update Gopkg.lock --- Gopkg.lock | 67 +++++------------------------------------------------- 1 file changed, 6 insertions(+), 61 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 83fe33bd7..7dbe6ae72 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,18 +1,6 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. -[[projects]] - branch = "master" - name = "github.com/bartekn/go-bip39" - packages = ["."] - revision = "a05967ea095d81c8fe4833776774cfaff8e5036c" - -[[projects]] - branch = "master" - name = "github.com/brejski/hid" - packages = ["."] - revision = "06112dcfcc50a7e0e4fd06e17f9791e788fdaafc" - [[projects]] branch = "master" name = "github.com/btcsuite/btcd" @@ -63,18 +51,6 @@ revision = "1adfc126b41513cc696b209667c8656ea7aac67c" version = "v1.0.0" -[[projects]] - branch = "master" - name = "github.com/golang/snappy" - packages = ["."] - revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" - -[[projects]] - branch = "master" - name = "github.com/jmhodges/levigo" - packages = ["."] - revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" - [[projects]] branch = "master" name = "github.com/kr/logfmt" @@ -102,25 +78,6 @@ revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" version = "v1.2.2" -[[projects]] - branch = "master" - name = "github.com/syndtr/goleveldb" - packages = [ - "leveldb", - "leveldb/cache", - "leveldb/comparer", - "leveldb/errors", - "leveldb/filter", - "leveldb/iterator", - "leveldb/journal", - "leveldb/memdb", - "leveldb/opt", - "leveldb/storage", - "leveldb/table", - "leveldb/util" - ] - revision = "e2150783cd35f5b607daca48afd8c57ec54cc995" - [[projects]] branch = "master" name = "github.com/tendermint/ed25519" @@ -134,31 +91,19 @@ [[projects]] name = "github.com/tendermint/go-amino" packages = ["."] - revision = "1715b7b78c65d6adcc5937315be4710234cefe09" - version = "0.10.0-rc2" + revision = "2106ca61d91029c931fd54968c2bb02dc96b1412" + version = "0.10.1" [[projects]] name = "github.com/tendermint/tmlibs" packages = [ "common", - "db", "log", "test" ] revision = "692f1d86a6e2c0efa698fd1e4541b68c74ffaf38" version = "v0.8.4" -[[projects]] - branch = "master" - name = "github.com/tyler-smith/go-bip39" - packages = ["."] - revision = "8e7a99b3e716f36d3b080a9a70f9eb45abe4edcc" - -[[projects]] - name = "github.com/zondax/ledger-goclient" - packages = ["."] - revision = "065cbf938a16f20335c40cfe180f9cd4955c6a5a" - [[projects]] branch = "master" name = "golang.org/x/crypto" @@ -168,25 +113,25 @@ "chacha20poly1305", "hkdf", "internal/chacha20", + "internal/subtle", "nacl/secretbox", "openpgp/armor", "openpgp/errors", - "pbkdf2", "poly1305", "ripemd160", "salsa20/salsa" ] - revision = "8ac0e0d97ce45cd83d1d7243c060cb8461dda5e9" + revision = "7f39a6fea4fe9364fb61e1def6a268a51b4f3a06" [[projects]] branch = "master" name = "golang.org/x/sys" packages = ["cpu"] - revision = "a9e25c09b96b8870693763211309e213c6ef299d" + revision = "ad87a3a340fa7f3bed189293fbfa7a9b7e021ae1" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "684746f2b651a722ee32eae056b437baf7a2213d68ddbfcefe04a1c3df27c93b" + inputs-digest = "027b22b86396a971d5d5c1d298947f531f39743975d65a22e98601140aa1b1a1" solver-name = "gps-cdcl" solver-version = 1