Initial import
This commit is contained in:
commit
c2193d519c
20 changed files with 2897 additions and 0 deletions
4
.gitignore
vendored
Executable file
4
.gitignore
vendored
Executable file
|
@ -0,0 +1,4 @@
|
|||
*.gem
|
||||
Gemfile.lock
|
||||
lib/*.bundle
|
||||
tmp/
|
2
Gemfile
Executable file
2
Gemfile
Executable file
|
@ -0,0 +1,2 @@
|
|||
source 'https://rubygems.org'
|
||||
gemspec
|
674
LICENSE.txt
Executable file
674
LICENSE.txt
Executable file
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
80
README.md
Executable file
80
README.md
Executable file
|
@ -0,0 +1,80 @@
|
|||
# BLAKE2b for Ruby
|
||||
|
||||
BLAKE2 is a cryptographic hash function faster than MD5, SHA-1, SHA-2, and SHA-3, yet is at least as secure as the latest standard SHA-3. BLAKE2 has been adopted by many projects due to its high speed, security, and simplicity.
|
||||
|
||||
More info at: [https://blake2.net](https://blake2.net).
|
||||
|
||||
## SUMMARY
|
||||
|
||||
This gem is a C-extension for using BLAKE2b in Ruby. BLAKE2b (or just BLAKE2) is optimized for 64-bit platforms—including NEON-enabled ARMs—and produces digests of any size between 1 and 64 bytes.
|
||||
|
||||
The C code for this gem is taken from the [official reference C implementation](https://github.com/BLAKE2/BLAKE2) as of commit [ca4c89314abff54e3806b44e4a08164f8204f09a](https://github.com/BLAKE2/BLAKE2/tree/ca4c89314abff54e3806b44e4a08164f8204f09a).
|
||||
|
||||
## INSTALL
|
||||
|
||||
```
|
||||
gem install blake2b
|
||||
```
|
||||
|
||||
## USAGE
|
||||
|
||||
``` ruby
|
||||
require 'blake2b'
|
||||
|
||||
# The UTF-8 String (Required) that you want to digest.
|
||||
input = 'abc'
|
||||
|
||||
# The main application of keyed BLAKE2 is as a message authentication code (MAC)
|
||||
# By default `Blake2::Key.none` is used.
|
||||
key = Blake2b::Key.none
|
||||
# key = Blake2::Key.from_string("foo bar baz")
|
||||
# key = Blake2::Key.from_hex('DEADBEAF')
|
||||
# key = Blake2::Key.from_bytes([222, 173, 190, 175])
|
||||
|
||||
# The output length in Bytes of the Hash, Max and Default is 32.
|
||||
out_len = 32
|
||||
|
||||
# HEX OUTPUT
|
||||
############
|
||||
|
||||
Blake2b.hex(input)
|
||||
=> "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"
|
||||
|
||||
Blake2b.hex(input, key)
|
||||
=> "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"
|
||||
|
||||
Blake2b.hex(input, key, out_len)
|
||||
=> "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"
|
||||
|
||||
# BYTES OUTPUT
|
||||
##############
|
||||
|
||||
Blake2b.bytes(input)
|
||||
=> [80, 140, 94, ...]
|
||||
|
||||
Blake2b.bytes(input, key)
|
||||
=> [80, 140, 94, ...]
|
||||
|
||||
Blake2b.bytes(input, key, out_len)
|
||||
=> [80, 140, 94, ...]
|
||||
|
||||
```
|
||||
|
||||
## DEVELOPMENT
|
||||
|
||||
After checking out the repo, run `bundle` to install dependencies. Then,
|
||||
run `rake full` to build and test, or `rake test` to only run the tests.
|
||||
|
||||
To install this gem onto your local machine, run `bundle exec rake install`.
|
||||
|
||||
## Future
|
||||
|
||||
Hopefully this gem will not be required once Ruby [issue #12802](https://bugs.ruby-lang.org/issues/12802) is resolved. Blake2 will either be included natively into MRI or available through the OpenSSL library.
|
||||
|
||||
## License
|
||||
|
||||
Blake2b is based heavily on [Blake2](https://github.com/franckverrot/blake2) by Franck Verrot, Copyright 2014.
|
||||
|
||||
Blake2b is copyright 2018, Mauricio Gomes.
|
||||
|
||||
The original work (Blake2) and the modified work (Blake2b) are licensed GPL v3.0. See LICENSE.txt for details.
|
46
Rakefile
Executable file
46
Rakefile
Executable file
|
@ -0,0 +1,46 @@
|
|||
require 'bundler/gem_tasks'
|
||||
require 'rake/testtask'
|
||||
require 'rake/extensiontask'
|
||||
|
||||
spec = Gem::Specification.load('blake2b.gemspec')
|
||||
|
||||
Rake::ExtensionTask.new('blake2b_ext', spec) do |ext|
|
||||
ext.source_pattern = '*.{c,h}'
|
||||
end
|
||||
|
||||
Rake::TestTask.new do |t|
|
||||
t.libs << 'test'
|
||||
t.pattern = 'test/**/*_test.rb'
|
||||
t.verbose = true
|
||||
t.warning = true
|
||||
end
|
||||
|
||||
task default: :full
|
||||
|
||||
desc 'clean, compile, and run the full test suite'
|
||||
task full: %w(clean compile test)
|
||||
|
||||
def gemspec
|
||||
@gemspec ||= begin
|
||||
file = File.expand_path('../blake2.gemspec', __FILE__)
|
||||
eval(File.read(file), binding, file)
|
||||
end
|
||||
end
|
||||
|
||||
desc "Validate the gemspec"
|
||||
task :gemspec do
|
||||
gemspec.validate
|
||||
end
|
||||
|
||||
desc "Build the gem"
|
||||
task :gem => [:gemspec, :build] do
|
||||
mkdir_p "pkg"
|
||||
sh "gem build blake2.gemspec"
|
||||
mv "#{gemspec.full_name}.gem", "pkg"
|
||||
|
||||
require 'digest/sha2'
|
||||
built_gem_path = "pkg/#{gemspec.full_name}.gem"
|
||||
checksum = Digest::SHA512.new.hexdigest(File.read(built_gem_path))
|
||||
checksum_path = "checksums/#{gemspec.version}.sha512"
|
||||
File.open(checksum_path, 'w' ) {|f| f.write(checksum) }
|
||||
end
|
25
blake2b.gemspec
Executable file
25
blake2b.gemspec
Executable file
|
@ -0,0 +1,25 @@
|
|||
# coding: utf-8
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = "blake2b"
|
||||
spec.version = "0.9.0"
|
||||
spec.authors = ["Franck Verrot", "Mauricio Gomes"]
|
||||
spec.email = ["mauricio@edge14.com"]
|
||||
spec.homepage = "https://github.com/mgomes/blake2b"
|
||||
spec.license = "GPL-3.0"
|
||||
|
||||
spec.summary = "A cryptographic hash function faster than MD5, SHA-1, SHA-2, and SHA-3 for 64-bit systems."
|
||||
spec.required_ruby_version = ">= 2.1.0"
|
||||
spec.description = "A cryptographic hash function faster than MD5, SHA-1, SHA-2, and SHA-3 for 64-bit systems."
|
||||
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
||||
|
||||
spec.extensions << "ext/blake2_ext/extconf.rb"
|
||||
|
||||
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
||||
spec.require_paths = ["lib"]
|
||||
|
||||
spec.add_development_dependency "rake-compiler", "~> 0.9"
|
||||
spec.add_development_dependency "bundler" , "~> 1.5"
|
||||
spec.add_development_dependency "rake" , "~> 11.1"
|
||||
spec.add_development_dependency "minitest" , "~> 5.8"
|
||||
spec.add_development_dependency "pry" , "~> 0.10"
|
||||
end
|
160
ext/blake2b_ext/blake2-impl.h
Executable file
160
ext/blake2b_ext/blake2-impl.h
Executable file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
#ifndef BLAKE2_IMPL_H
|
||||
#define BLAKE2_IMPL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_INLINE __inline
|
||||
#elif defined(__GNUC__)
|
||||
#define BLAKE2_INLINE __inline__
|
||||
#else
|
||||
#define BLAKE2_INLINE
|
||||
#endif
|
||||
#else
|
||||
#define BLAKE2_INLINE inline
|
||||
#endif
|
||||
|
||||
static BLAKE2_INLINE uint32_t load32( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint32_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint32_t )( p[0] ) << 0) |
|
||||
(( uint32_t )( p[1] ) << 8) |
|
||||
(( uint32_t )( p[2] ) << 16) |
|
||||
(( uint32_t )( p[3] ) << 24) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load64( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint64_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint64_t )( p[0] ) << 0) |
|
||||
(( uint64_t )( p[1] ) << 8) |
|
||||
(( uint64_t )( p[2] ) << 16) |
|
||||
(( uint64_t )( p[3] ) << 24) |
|
||||
(( uint64_t )( p[4] ) << 32) |
|
||||
(( uint64_t )( p[5] ) << 40) |
|
||||
(( uint64_t )( p[6] ) << 48) |
|
||||
(( uint64_t )( p[7] ) << 56) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint16_t load16( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint16_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint16_t )( p[0] ) << 0) |
|
||||
(( uint16_t )( p[1] ) << 8) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store16( void *dst, uint16_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
*p++ = ( uint8_t )w; w >>= 8;
|
||||
*p++ = ( uint8_t )w;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store32( void *dst, uint32_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store64( void *dst, uint64_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
p[4] = (uint8_t)(w >> 32);
|
||||
p[5] = (uint8_t)(w >> 40);
|
||||
p[6] = (uint8_t)(w >> 48);
|
||||
p[7] = (uint8_t)(w >> 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load48( const void *src )
|
||||
{
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint64_t )( p[0] ) << 0) |
|
||||
(( uint64_t )( p[1] ) << 8) |
|
||||
(( uint64_t )( p[2] ) << 16) |
|
||||
(( uint64_t )( p[3] ) << 24) |
|
||||
(( uint64_t )( p[4] ) << 32) |
|
||||
(( uint64_t )( p[5] ) << 40) ;
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store48( void *dst, uint64_t w )
|
||||
{
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
p[4] = (uint8_t)(w >> 32);
|
||||
p[5] = (uint8_t)(w >> 40);
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 32 - c ) );
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 64 - c ) );
|
||||
}
|
||||
|
||||
/* prevents compiler optimizing out memset() */
|
||||
static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
|
||||
{
|
||||
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
|
||||
memset_v(v, 0, n);
|
||||
}
|
||||
|
||||
#endif
|
195
ext/blake2b_ext/blake2.h
Executable file
195
ext/blake2b_ext/blake2.h
Executable file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
#ifndef BLAKE2_H
|
||||
#define BLAKE2_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
|
||||
#else
|
||||
#define BLAKE2_PACKED(x) x __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum blake2s_constant
|
||||
{
|
||||
BLAKE2S_BLOCKBYTES = 64,
|
||||
BLAKE2S_OUTBYTES = 32,
|
||||
BLAKE2S_KEYBYTES = 32,
|
||||
BLAKE2S_SALTBYTES = 8,
|
||||
BLAKE2S_PERSONALBYTES = 8
|
||||
};
|
||||
|
||||
enum blake2b_constant
|
||||
{
|
||||
BLAKE2B_BLOCKBYTES = 128,
|
||||
BLAKE2B_OUTBYTES = 64,
|
||||
BLAKE2B_KEYBYTES = 64,
|
||||
BLAKE2B_SALTBYTES = 16,
|
||||
BLAKE2B_PERSONALBYTES = 16
|
||||
};
|
||||
|
||||
typedef struct blake2s_state__
|
||||
{
|
||||
uint32_t h[8];
|
||||
uint32_t t[2];
|
||||
uint32_t f[2];
|
||||
uint8_t buf[BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2s_state;
|
||||
|
||||
typedef struct blake2b_state__
|
||||
{
|
||||
uint64_t h[8];
|
||||
uint64_t t[2];
|
||||
uint64_t f[2];
|
||||
uint8_t buf[BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2b_state;
|
||||
|
||||
typedef struct blake2sp_state__
|
||||
{
|
||||
blake2s_state S[8][1];
|
||||
blake2s_state R[1];
|
||||
uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
} blake2sp_state;
|
||||
|
||||
typedef struct blake2bp_state__
|
||||
{
|
||||
blake2b_state S[4][1];
|
||||
blake2b_state R[1];
|
||||
uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
} blake2bp_state;
|
||||
|
||||
|
||||
BLAKE2_PACKED(struct blake2s_param__
|
||||
{
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint16_t xof_length; /* 14 */
|
||||
uint8_t node_depth; /* 15 */
|
||||
uint8_t inner_length; /* 16 */
|
||||
/* uint8_t reserved[0]; */
|
||||
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
|
||||
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
|
||||
});
|
||||
|
||||
typedef struct blake2s_param__ blake2s_param;
|
||||
|
||||
BLAKE2_PACKED(struct blake2b_param__
|
||||
{
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint32_t xof_length; /* 16 */
|
||||
uint8_t node_depth; /* 17 */
|
||||
uint8_t inner_length; /* 18 */
|
||||
uint8_t reserved[14]; /* 32 */
|
||||
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
|
||||
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
|
||||
});
|
||||
|
||||
typedef struct blake2b_param__ blake2b_param;
|
||||
|
||||
typedef struct blake2xs_state__
|
||||
{
|
||||
blake2s_state S[1];
|
||||
blake2s_param P[1];
|
||||
} blake2xs_state;
|
||||
|
||||
typedef struct blake2xb_state__
|
||||
{
|
||||
blake2b_state S[1];
|
||||
blake2b_param P[1];
|
||||
} blake2xb_state;
|
||||
|
||||
/* Padded structs result in a compile-time error */
|
||||
enum {
|
||||
BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
|
||||
BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
|
||||
};
|
||||
|
||||
/* Streaming API */
|
||||
int blake2s_init( blake2s_state *S, size_t outlen );
|
||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
|
||||
int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
|
||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2b_init( blake2b_state *S, size_t outlen );
|
||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
|
||||
int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
|
||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2sp_init( blake2sp_state *S, size_t outlen );
|
||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
|
||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2bp_init( blake2bp_state *S, size_t outlen );
|
||||
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
|
||||
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
|
||||
|
||||
/* Variable output length API */
|
||||
int blake2xs_init( blake2xs_state *S, const size_t outlen );
|
||||
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
|
||||
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
|
||||
|
||||
int blake2xb_init( blake2xb_state *S, const size_t outlen );
|
||||
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
|
||||
int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
|
||||
|
||||
/* Simple API */
|
||||
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
/* This is simply an alias for blake2b */
|
||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
379
ext/blake2b_ext/blake2b-ref.c
Normal file
379
ext/blake2b_ext/blake2b-ref.c
Normal file
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
static const uint64_t blake2b_IV[8] =
|
||||
{
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
static const uint8_t blake2b_sigma[12][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
|
||||
};
|
||||
|
||||
|
||||
static void blake2b_set_lastnode( blake2b_state *S )
|
||||
{
|
||||
S->f[1] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static int blake2b_is_lastblock( const blake2b_state *S )
|
||||
{
|
||||
return S->f[0] != 0;
|
||||
}
|
||||
|
||||
static void blake2b_set_lastblock( blake2b_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2b_set_lastnode( S );
|
||||
|
||||
S->f[0] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
|
||||
{
|
||||
S->t[0] += inc;
|
||||
S->t[1] += ( S->t[0] < inc );
|
||||
}
|
||||
|
||||
static void blake2b_init0( blake2b_state *S )
|
||||
{
|
||||
size_t i;
|
||||
memset( S, 0, sizeof( blake2b_state ) );
|
||||
|
||||
for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
|
||||
}
|
||||
|
||||
/* init xors IV with input parameter block */
|
||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
||||
{
|
||||
const uint8_t *p = ( const uint8_t * )( P );
|
||||
size_t i;
|
||||
|
||||
blake2b_init0( S );
|
||||
|
||||
/* IV XOR ParamBlock */
|
||||
for( i = 0; i < 8; ++i )
|
||||
S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
|
||||
|
||||
S->outlen = P->digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int blake2b_init( blake2b_state *S, size_t outlen )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store32( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2b_init_param( S, P );
|
||||
}
|
||||
|
||||
|
||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
|
||||
|
||||
if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store32( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
|
||||
if( blake2b_init_param( S, P ) < 0 ) return -1;
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
|
||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define G(r,i,a,b,c,d) \
|
||||
do { \
|
||||
a = a + b + m[blake2b_sigma[r][2*i+0]]; \
|
||||
d = rotr64(d ^ a, 32); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 24); \
|
||||
a = a + b + m[blake2b_sigma[r][2*i+1]]; \
|
||||
d = rotr64(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 63); \
|
||||
} while(0)
|
||||
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
|
||||
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
|
||||
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
|
||||
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
|
||||
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
|
||||
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
|
||||
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
|
||||
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
|
||||
} while(0)
|
||||
|
||||
static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
|
||||
{
|
||||
uint64_t m[16];
|
||||
uint64_t v[16];
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < 16; ++i ) {
|
||||
m[i] = load64( block + i * sizeof( m[i] ) );
|
||||
}
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
v[i] = S->h[i];
|
||||
}
|
||||
|
||||
v[ 8] = blake2b_IV[0];
|
||||
v[ 9] = blake2b_IV[1];
|
||||
v[10] = blake2b_IV[2];
|
||||
v[11] = blake2b_IV[3];
|
||||
v[12] = blake2b_IV[4] ^ S->t[0];
|
||||
v[13] = blake2b_IV[5] ^ S->t[1];
|
||||
v[14] = blake2b_IV[6] ^ S->f[0];
|
||||
v[15] = blake2b_IV[7] ^ S->f[1];
|
||||
|
||||
ROUND( 0 );
|
||||
ROUND( 1 );
|
||||
ROUND( 2 );
|
||||
ROUND( 3 );
|
||||
ROUND( 4 );
|
||||
ROUND( 5 );
|
||||
ROUND( 6 );
|
||||
ROUND( 7 );
|
||||
ROUND( 8 );
|
||||
ROUND( 9 );
|
||||
ROUND( 10 );
|
||||
ROUND( 11 );
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
|
||||
int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
|
||||
{
|
||||
const unsigned char * in = (const unsigned char *)pin;
|
||||
if( inlen > 0 )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = BLAKE2B_BLOCKBYTES - left;
|
||||
if( inlen > fill )
|
||||
{
|
||||
S->buflen = 0;
|
||||
memcpy( S->buf + left, in, fill ); /* Fill buffer */
|
||||
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
|
||||
blake2b_compress( S, S->buf ); /* Compress */
|
||||
in += fill; inlen -= fill;
|
||||
while(inlen > BLAKE2B_BLOCKBYTES) {
|
||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
||||
blake2b_compress( S, in );
|
||||
in += BLAKE2B_BLOCKBYTES;
|
||||
inlen -= BLAKE2B_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
memcpy( S->buf + S->buflen, in, inlen );
|
||||
S->buflen += inlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen )
|
||||
{
|
||||
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
||||
size_t i;
|
||||
|
||||
if( out == NULL || outlen < S->outlen )
|
||||
return -1;
|
||||
|
||||
if( blake2b_is_lastblock( S ) )
|
||||
return -1;
|
||||
|
||||
blake2b_increment_counter( S, S->buflen );
|
||||
blake2b_set_lastblock( S );
|
||||
memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
|
||||
blake2b_compress( S, S->buf );
|
||||
|
||||
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
|
||||
store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
|
||||
|
||||
memcpy( out, buffer, S->outlen );
|
||||
secure_zero_memory(buffer, sizeof(buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* inlen, at least, should be uint64_t. Others can be size_t. */
|
||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2b_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if ( NULL == in && inlen > 0 ) return -1;
|
||||
|
||||
if ( NULL == out ) return -1;
|
||||
|
||||
if( NULL == key && keylen > 0 ) return -1;
|
||||
|
||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
|
||||
|
||||
if( keylen > BLAKE2B_KEYBYTES ) return -1;
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( blake2b_init( S, outlen ) < 0 ) return -1;
|
||||
}
|
||||
|
||||
blake2b_update( S, ( const uint8_t * )in, inlen );
|
||||
blake2b_final( S, out, outlen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
|
||||
return blake2b(out, outlen, in, inlen, key, keylen);
|
||||
}
|
||||
|
||||
#if defined(SUPERCOP)
|
||||
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
||||
{
|
||||
return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLAKE2B_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2B_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step;
|
||||
|
||||
for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
|
||||
key[i] = ( uint8_t )i;
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
buf[i] = ( uint8_t )i;
|
||||
|
||||
/* Test simple API */
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
{
|
||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||
blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
|
||||
|
||||
if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
|
||||
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
|
||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||
blake2b_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = i;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
405
ext/blake2b_ext/blake2s-ref.c
Executable file
405
ext/blake2b_ext/blake2s-ref.c
Executable file
|
@ -0,0 +1,405 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
static const uint32_t blake2s_IV[8] =
|
||||
{
|
||||
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
||||
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
||||
};
|
||||
|
||||
static const uint8_t blake2s_sigma[10][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
};
|
||||
|
||||
static inline int blake2s_set_lastnode( blake2s_state *S )
|
||||
{
|
||||
S->f[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_clear_lastnode( blake2s_state *S )
|
||||
{
|
||||
S->f[1] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static inline int blake2s_is_lastblock( const blake2s_state *S )
|
||||
{
|
||||
return S->f[0] != 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_set_lastblock( blake2s_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2s_set_lastnode( S );
|
||||
|
||||
S->f[0] = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_clear_lastblock( blake2s_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2s_clear_lastnode( S );
|
||||
|
||||
S->f[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
|
||||
{
|
||||
S->t[0] += inc;
|
||||
S->t[1] += ( S->t[0] < inc );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parameter-related functions
|
||||
static inline int blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length )
|
||||
{
|
||||
P->digest_length = digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout )
|
||||
{
|
||||
P->fanout = fanout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth )
|
||||
{
|
||||
P->depth = depth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length )
|
||||
{
|
||||
store32( &P->leaf_length, leaf_length );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset )
|
||||
{
|
||||
store48( P->node_offset, node_offset );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth )
|
||||
{
|
||||
P->node_depth = node_depth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length )
|
||||
{
|
||||
P->inner_length = inner_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] )
|
||||
{
|
||||
memcpy( P->salt, salt, BLAKE2S_SALTBYTES );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] )
|
||||
{
|
||||
memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blake2s_init0( blake2s_state *S )
|
||||
{
|
||||
memset( S, 0, sizeof( blake2s_state ) );
|
||||
|
||||
for( int i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* init2 xors IV with input parameter block */
|
||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
|
||||
{
|
||||
blake2s_init0( S );
|
||||
const uint32_t *p = ( const uint32_t * )( P );
|
||||
|
||||
/* IV XOR ParamBlock */
|
||||
for( size_t i = 0; i < 8; ++i )
|
||||
S->h[i] ^= load32( &p[i] );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Sequential blake2s initialization
|
||||
int blake2s_init( blake2s_state *S, const uint8_t outlen )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
|
||||
/* Move interval verification here? */
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
|
||||
|
||||
P->digest_length = outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store48( &P->node_offset, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
// memset(P->reserved, 0, sizeof(P->reserved) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2s_init_param( S, P );
|
||||
}
|
||||
|
||||
int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
|
||||
|
||||
if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
P->digest_length = outlen;
|
||||
P->key_length = keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store48( &P->node_offset, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
// memset(P->reserved, 0, sizeof(P->reserved) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
|
||||
if( blake2s_init_param( S, P ) < 0 ) return -1;
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
|
||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] )
|
||||
{
|
||||
uint32_t m[16];
|
||||
uint32_t v[16];
|
||||
|
||||
for( size_t i = 0; i < 16; ++i )
|
||||
m[i] = load32( block + i * sizeof( m[i] ) );
|
||||
|
||||
for( size_t i = 0; i < 8; ++i )
|
||||
v[i] = S->h[i];
|
||||
|
||||
v[ 8] = blake2s_IV[0];
|
||||
v[ 9] = blake2s_IV[1];
|
||||
v[10] = blake2s_IV[2];
|
||||
v[11] = blake2s_IV[3];
|
||||
v[12] = S->t[0] ^ blake2s_IV[4];
|
||||
v[13] = S->t[1] ^ blake2s_IV[5];
|
||||
v[14] = S->f[0] ^ blake2s_IV[6];
|
||||
v[15] = S->f[1] ^ blake2s_IV[7];
|
||||
#define G(r,i,a,b,c,d) \
|
||||
do { \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
|
||||
d = rotr32(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 12); \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
|
||||
d = rotr32(d ^ a, 8); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 7); \
|
||||
} while(0)
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
|
||||
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
|
||||
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
|
||||
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
|
||||
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
|
||||
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
|
||||
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
|
||||
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
|
||||
} while(0)
|
||||
ROUND( 0 );
|
||||
ROUND( 1 );
|
||||
ROUND( 2 );
|
||||
ROUND( 3 );
|
||||
ROUND( 4 );
|
||||
ROUND( 5 );
|
||||
ROUND( 6 );
|
||||
ROUND( 7 );
|
||||
ROUND( 8 );
|
||||
ROUND( 9 );
|
||||
|
||||
for( size_t i = 0; i < 8; ++i )
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen )
|
||||
{
|
||||
while( inlen > 0 )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
|
||||
|
||||
if( inlen > fill )
|
||||
{
|
||||
memcpy( S->buf + left, in, fill ); // Fill buffer
|
||||
S->buflen += fill;
|
||||
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||
blake2s_compress( S, S->buf ); // Compress
|
||||
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
|
||||
S->buflen -= BLAKE2S_BLOCKBYTES;
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
}
|
||||
else // inlen <= fill
|
||||
{
|
||||
memcpy( S->buf + left, in, inlen );
|
||||
S->buflen += inlen; // Be lazy, do not compress
|
||||
in += inlen;
|
||||
inlen -= inlen;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen )
|
||||
{
|
||||
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
|
||||
|
||||
if( out == NULL || outlen == 0 || outlen > BLAKE2S_OUTBYTES )
|
||||
return -1;
|
||||
|
||||
if( blake2s_is_lastblock( S ) )
|
||||
return -1;
|
||||
|
||||
|
||||
if( S->buflen > BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||
blake2s_compress( S, S->buf );
|
||||
S->buflen -= BLAKE2S_BLOCKBYTES;
|
||||
memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
|
||||
}
|
||||
|
||||
blake2s_increment_counter( S, ( uint32_t )S->buflen );
|
||||
blake2s_set_lastblock( S );
|
||||
memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
|
||||
blake2s_compress( S, S->buf );
|
||||
|
||||
for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
|
||||
store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
|
||||
|
||||
memcpy( out, buffer, outlen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
|
||||
{
|
||||
blake2s_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if ( NULL == in && inlen > 0 ) return -1;
|
||||
|
||||
if ( NULL == out ) return -1;
|
||||
|
||||
if ( NULL == key && keylen > 0) return -1;
|
||||
|
||||
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
|
||||
|
||||
if( keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( blake2s_init( S, outlen ) < 0 ) return -1;
|
||||
}
|
||||
|
||||
blake2s_update( S, ( const uint8_t * )in, inlen );
|
||||
blake2s_final( S, out, outlen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SUPERCOP)
|
||||
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
||||
{
|
||||
return blake2s( out, in, NULL, BLAKE2S_OUTBYTES, inlen, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLAKE2S_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
uint8_t key[BLAKE2S_KEYBYTES];
|
||||
uint8_t buf[KAT_LENGTH];
|
||||
|
||||
for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i )
|
||||
key[i] = ( uint8_t )i;
|
||||
|
||||
for( size_t i = 0; i < KAT_LENGTH; ++i )
|
||||
buf[i] = ( uint8_t )i;
|
||||
|
||||
for( size_t i = 0; i < KAT_LENGTH; ++i )
|
||||
{
|
||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||
blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES );
|
||||
|
||||
if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
||||
{
|
||||
puts( "error" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
3
ext/blake2b_ext/extconf.rb
Executable file
3
ext/blake2b_ext/extconf.rb
Executable file
|
@ -0,0 +1,3 @@
|
|||
require 'mkmf'
|
||||
$CFLAGS += ' -std=c99'
|
||||
create_makefile 'blake2b_ext'
|
108
ext/blake2b_ext/rbext.c
Executable file
108
ext/blake2b_ext/rbext.c
Executable file
|
@ -0,0 +1,108 @@
|
|||
#include <ruby/ruby.h>
|
||||
#include <ruby/encoding.h>
|
||||
#include "blake2.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t key_length;
|
||||
uint8_t *key_bytes;
|
||||
|
||||
uint8_t output_length;
|
||||
uint8_t *output;
|
||||
|
||||
VALUE to_hex;
|
||||
VALUE to_bytes;
|
||||
} Blake2;
|
||||
|
||||
VALUE cBlake2;
|
||||
|
||||
static void blake2_free(Blake2 *blake2) {
|
||||
free(blake2->key_bytes);
|
||||
free(blake2->output);
|
||||
|
||||
rb_gc_mark(blake2->to_hex);
|
||||
rb_gc_mark(blake2->to_bytes);
|
||||
|
||||
ruby_xfree(blake2);
|
||||
}
|
||||
|
||||
static VALUE blake2_alloc(VALUE klass) {
|
||||
Blake2 *blake2_obj = (Blake2 *)ruby_xmalloc(sizeof(Blake2));
|
||||
|
||||
return Data_Wrap_Struct(klass, NULL, blake2_free, blake2_obj);
|
||||
}
|
||||
|
||||
VALUE m_blake2_initialize(VALUE self, VALUE _len, VALUE _key) {
|
||||
Blake2 *blake2;
|
||||
Data_Get_Struct(self, Blake2, blake2);
|
||||
int i;
|
||||
|
||||
ID bytes_method = rb_intern("bytes");
|
||||
blake2->to_hex = ID2SYM(rb_intern("to_hex"));
|
||||
blake2->to_bytes = ID2SYM(rb_intern("to_bytes"));
|
||||
|
||||
VALUE key_bytes_ary = rb_funcall(_key, bytes_method, 0);
|
||||
blake2->key_length = RARRAY_LEN(key_bytes_ary);
|
||||
blake2->key_bytes = (uint8_t*)malloc(blake2->key_length * sizeof(uint8_t));
|
||||
|
||||
for(i = 0; i < blake2->key_length; i++) {
|
||||
VALUE byte = rb_ary_entry(key_bytes_ary, i);
|
||||
blake2->key_bytes[i] = NUM2INT(byte);
|
||||
}
|
||||
|
||||
blake2->output_length = NUM2INT(_len);
|
||||
blake2->output = (uint8_t*)malloc(blake2->output_length * sizeof(uint8_t));
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
VALUE m_blake2_digest(VALUE self, VALUE _input, VALUE _representation) {
|
||||
Blake2 *blake2;
|
||||
|
||||
char *input = RSTRING_PTR(_input);
|
||||
int input_length = RSTRING_LEN(_input);
|
||||
int i;
|
||||
|
||||
Data_Get_Struct(self, Blake2, blake2);
|
||||
|
||||
blake2b(blake2->output, input, blake2->key_bytes,
|
||||
blake2->output_length, input_length, blake2->key_length);
|
||||
|
||||
VALUE result;
|
||||
|
||||
if(_representation == blake2->to_bytes) {
|
||||
result = rb_ary_new2(blake2->output_length);
|
||||
|
||||
for(i = 0; i < blake2->output_length; i++) {
|
||||
rb_ary_push(result, INT2NUM(blake2->output[i]));
|
||||
}
|
||||
} else if(_representation == blake2->to_hex) {
|
||||
int ary_len = blake2->output_length * sizeof(char) * 2;
|
||||
char *c_str = (char*)malloc(ary_len + 1);
|
||||
|
||||
for(i = 0; i < blake2->output_length; i++) {
|
||||
sprintf(c_str + (i * 2), "%02x", blake2->output[i]);
|
||||
}
|
||||
c_str[ary_len] = 0;
|
||||
|
||||
result = rb_str_new(c_str, ary_len);
|
||||
|
||||
if(RSTRING_LEN(result) != ary_len) {
|
||||
rb_raise(rb_eRuntimeError, "m_blake2_digest: sizes don't match. Ary: %d != %d", RSTRING_LEN(result), ary_len);
|
||||
}
|
||||
|
||||
free(c_str);
|
||||
} else {
|
||||
rb_raise(rb_eArgError, "unknown representation :%"PRIsVALUE"", _representation);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Init_blake2_ext() {
|
||||
cBlake2 = rb_define_class("Blake2b", rb_cObject);
|
||||
rb_define_alloc_func(cBlake2, blake2_alloc);
|
||||
|
||||
rb_define_private_method(cBlake2, "initialize", RUBY_METHOD_FUNC(m_blake2_initialize), 2);
|
||||
rb_define_method(cBlake2, "digest", RUBY_METHOD_FUNC(m_blake2_digest), 2);
|
||||
}
|
29
lib/blake2b.rb
Executable file
29
lib/blake2b.rb
Executable file
|
@ -0,0 +1,29 @@
|
|||
require 'blake2b_ext'
|
||||
require 'blake2b/key'
|
||||
|
||||
class Blake2b
|
||||
def self.hex(input, key = Blake2::Key.none, out_len = 32)
|
||||
check_if_valid!(input, key, out_len)
|
||||
Blake2b.new(out_len, key).digest(input, :to_hex)
|
||||
end
|
||||
|
||||
def self.bytes(input, key = Blake2::Key.none, out_len = 32)
|
||||
check_if_valid!(input, key, out_len)
|
||||
Blake2b.new(out_len, key).digest(input, :to_bytes)
|
||||
end
|
||||
|
||||
def self.check_if_valid!(input, key, out_len)
|
||||
unless input.is_a?(String)
|
||||
raise ArgumentError, 'input arg must be a String'
|
||||
end
|
||||
|
||||
unless key.is_a?(Blake2::Key)
|
||||
raise ArgumentError, 'key arg must be a Blake2b::Key'
|
||||
end
|
||||
|
||||
unless out_len.is_a?(Integer) && out_len.between?(1, 32)
|
||||
raise ArgumentError, 'out_len arg must be an Integer between 1 and 32 inclusive'
|
||||
end
|
||||
end
|
||||
private_class_method :check_if_valid!
|
||||
end
|
55
lib/blake2b/key.rb
Executable file
55
lib/blake2b/key.rb
Executable file
|
@ -0,0 +1,55 @@
|
|||
class Blake2b
|
||||
# Validate and normalize an HMAC key, provided in different formats,
|
||||
# into an Array of Integer Bytes.
|
||||
class Key
|
||||
attr_reader :bytes
|
||||
|
||||
def initialize(bytes)
|
||||
@bytes = bytes
|
||||
end
|
||||
|
||||
# Create a blank Key
|
||||
#
|
||||
# @return [Blake2b::Key] a Blake2::Key object with a `bytes` attr
|
||||
def self.none
|
||||
new([])
|
||||
end
|
||||
|
||||
# Create a key from an ASCII String
|
||||
#
|
||||
# @param str [String] an ASCII String key
|
||||
# @return [Blake2b::Key] a Blake2::Key object with a `bytes` attr
|
||||
def self.from_string(str)
|
||||
if str.is_a?(String) && str.ascii_only?
|
||||
new(str.bytes)
|
||||
else
|
||||
raise ArgumentError, 'key must be an ASCII String'
|
||||
end
|
||||
end
|
||||
|
||||
# Create a key from a Hex String [a-fA-F0-9]
|
||||
#
|
||||
# @param str [String] a Hex String key
|
||||
# @return [Blake2b::Key] a Blake2::Key object with a `bytes` attr
|
||||
def self.from_hex(str)
|
||||
if str.is_a?(String) && str.match(/^[a-fA-F0-9]+$/)
|
||||
new([str].pack('H*').bytes)
|
||||
else
|
||||
raise ArgumentError, 'key must be a Hex String [a-fA-F0-9]'
|
||||
end
|
||||
end
|
||||
|
||||
# Create a key from Array of Integer (0-255) Bytes.
|
||||
# This simply validates and passes through the Array.
|
||||
#
|
||||
# @param str [Array] an Array of Integer (0-255) Bytes
|
||||
# @return [Blake2b::Key] a Blake2b::Key object with a `bytes` attr
|
||||
def self.from_bytes(bytes)
|
||||
if bytes.all? { |b| b.is_a?(Integer) && b.between?(0, 255) }
|
||||
new(bytes)
|
||||
else
|
||||
raise ArgumentError, 'key must be a Byte Array of Integers (0-255)'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
42
test/blake2/key_test.rb
Executable file
42
test/blake2/key_test.rb
Executable file
|
@ -0,0 +1,42 @@
|
|||
require 'test_helper'
|
||||
|
||||
class KeyTest < MiniTest::Test
|
||||
def test_none
|
||||
key = Blake2::Key.none
|
||||
assert_equal [], key.bytes
|
||||
end
|
||||
|
||||
def test_from_string
|
||||
key = Blake2::Key.from_string('foo bar baz')
|
||||
assert_equal [102, 111, 111, 32, 98, 97, 114, 32, 98, 97, 122], key.bytes
|
||||
end
|
||||
|
||||
def test_from_string_raises_on_non_ascii_string
|
||||
assert_raises(ArgumentError) { Blake2::Key.from_string('💩') }
|
||||
end
|
||||
|
||||
def test_from_hex
|
||||
key = Blake2::Key.from_hex('DEADBEAF')
|
||||
assert_equal [222, 173, 190, 175], key.bytes
|
||||
end
|
||||
|
||||
def test_from_hex_raises_on_non_hex_string
|
||||
assert_raises(ArgumentError) { Blake2::Key.from_hex('DEADBEAFZZ') }
|
||||
end
|
||||
|
||||
def test_from_bytes_hex
|
||||
key = Blake2::Key.from_bytes([0xDE, 0xAD, 0xBE, 0xAF])
|
||||
assert_equal [222, 173, 190, 175], key.bytes
|
||||
end
|
||||
|
||||
def test_from_bytes_int
|
||||
key = Blake2::Key.from_bytes([222, 173, 190, 175])
|
||||
assert_equal [222, 173, 190, 175], key.bytes
|
||||
end
|
||||
|
||||
def test_from_hex_raises_on_non_valid_byte_array
|
||||
assert_raises(ArgumentError) { Blake2::Key.from_bytes([-1]) }
|
||||
assert_raises(ArgumentError) { Blake2::Key.from_bytes([256]) }
|
||||
assert_raises(ArgumentError) { Blake2::Key.from_bytes(['foo']) }
|
||||
end
|
||||
end
|
60
test/blake2b_api_test.rb
Executable file
60
test/blake2b_api_test.rb
Executable file
|
@ -0,0 +1,60 @@
|
|||
require 'test_helper'
|
||||
|
||||
class Blake2bTest < MiniTest::Test
|
||||
def test_hex_with_input_only
|
||||
res = Blake2b.hex('abc')
|
||||
assert_kind_of String, res
|
||||
assert_equal '508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982', res
|
||||
end
|
||||
|
||||
def test_hex_with_input_and_key
|
||||
res = Blake2b.hex('abc', Blake2b::Key.none)
|
||||
assert_kind_of String, res
|
||||
assert_equal '508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982', res
|
||||
end
|
||||
|
||||
def test_hex_with_input_key_and_length
|
||||
res = Blake2b.hex('abc', Blake2b::Key.none, 32)
|
||||
assert_kind_of String, res
|
||||
assert_equal '508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982', res
|
||||
end
|
||||
|
||||
def test_bytes_with_input_only
|
||||
res = Blake2b.bytes('abc')
|
||||
assert_kind_of Array, res
|
||||
assert_equal [80, 140, 94, 140, 50, 124, 20, 226, 225, 167, 43, 163, 78, 235, 69, 47, 55, 69, 139, 32, 158, 214, 58, 41, 77, 153, 155, 76, 134, 103, 89, 130], res
|
||||
end
|
||||
|
||||
def test_bytes_with_input_and_key
|
||||
res = Blake2b.bytes('abc', Blake2b::Key.none)
|
||||
assert_kind_of Array, res
|
||||
assert_equal [80, 140, 94, 140, 50, 124, 20, 226, 225, 167, 43, 163, 78, 235, 69, 47, 55, 69, 139, 32, 158, 214, 58, 41, 77, 153, 155, 76, 134, 103, 89, 130], res
|
||||
end
|
||||
|
||||
def test_bytes_with_input_key_and_length
|
||||
res = Blake2b.bytes('abc', Blake2b::Key.none, 32)
|
||||
assert_kind_of Array, res
|
||||
assert_equal [80, 140, 94, 140, 50, 124, 20, 226, 225, 167, 43, 163, 78, 235, 69, 47, 55, 69, 139, 32, 158, 214, 58, 41, 77, 153, 155, 76, 134, 103, 89, 130], res
|
||||
end
|
||||
|
||||
def test_input_raises_on_non_string
|
||||
assert_raises(ArgumentError) { Blake2b.hex(nil) }
|
||||
assert_raises(ArgumentError) { Blake2b.bytes(nil) }
|
||||
end
|
||||
|
||||
def test_key_raises_on_non_key
|
||||
assert_raises(ArgumentError) { Blake2b.hex('abc', []) }
|
||||
assert_raises(ArgumentError) { Blake2b.bytes('abc', []) }
|
||||
end
|
||||
|
||||
def test_length_raises_on_invalid
|
||||
assert_raises(ArgumentError) { Blake2b.hex('abc', Blake2b::Key.none, -1) }
|
||||
assert_raises(ArgumentError) { Blake2b.hex('abc', Blake2b::Key.none, 0) }
|
||||
assert_raises(ArgumentError) { Blake2b.hex('abc', Blake2b::Key.none, 33) }
|
||||
assert_raises(ArgumentError) { Blake2b.hex('abc', Blake2b::Key.none, '32') }
|
||||
assert_raises(ArgumentError) { Blake2b.bytes('abc', Blake2b::Key.none, -1) }
|
||||
assert_raises(ArgumentError) { Blake2b.bytes('abc', Blake2b::Key.none, 0) }
|
||||
assert_raises(ArgumentError) { Blake2b.bytes('abc', Blake2b::Key.none, 33) }
|
||||
assert_raises(ArgumentError) { Blake2b.bytes('abc', Blake2b::Key.none, '32') }
|
||||
end
|
||||
end
|
25
test/blake2b_test.rb
Executable file
25
test/blake2b_test.rb
Executable file
|
@ -0,0 +1,25 @@
|
|||
require 'test_helper'
|
||||
|
||||
class Blake2bTest < MiniTest::Test
|
||||
def setup
|
||||
out_len = 32
|
||||
key = Blake2b::Key.from_string('foo bar baz')
|
||||
|
||||
@digestor = Blake2b.new(out_len, key)
|
||||
|
||||
@input = 'hello world'
|
||||
@expected = '95670379036532875f58bf23fbcb549675b656bd639a6124a614ccd8a980b180'
|
||||
end
|
||||
|
||||
def test_to_hex
|
||||
res = @digestor.digest(@input, :to_hex)
|
||||
assert_kind_of String, res
|
||||
assert_equal @expected, res
|
||||
end
|
||||
|
||||
def test_to_bytes
|
||||
res = @digestor.digest(@input, :to_bytes)
|
||||
assert_kind_of Array, res
|
||||
assert_equal [@expected].pack('H*').bytes, res
|
||||
end
|
||||
end
|
593
test/blake2b_vector_test.rb
Executable file
593
test/blake2b_vector_test.rb
Executable file
|
@ -0,0 +1,593 @@
|
|||
# rubocop:disable MethodLength, ClassLength, WordArray, LineLength
|
||||
require 'test_helper'
|
||||
|
||||
# These test vectors are taken from blake2s-js npm package
|
||||
# https://github.com/dchest/blake2s-js/blob/master/test/test.js
|
||||
#
|
||||
class Blake2bVectorTest < MiniTest::Test
|
||||
def setup
|
||||
@golden = [
|
||||
'69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9',
|
||||
'e34d74dbaf4ff4c6abd871cc220451d2ea2648846c7757fbaac82fe51ad64bea',
|
||||
'ddad9ab15dac4549ba42f49d262496bef6c0bae1dd342a8808f8ea267c6e210c',
|
||||
'e8f91c6ef232a041452ab0e149070cdd7dd1769e75b3a5921be37876c45c9900',
|
||||
'0cc70e00348b86ba2944d0c32038b25c55584f90df2304f55fa332af5fb01e20',
|
||||
'ec1964191087a4fe9df1c795342a02ffc191a5b251764856ae5b8b5769f0c6cd',
|
||||
'e1fa51618d7df4eb70cf0d5a9e906f806e9d19f7f4f01e3b621288e4120405d6',
|
||||
'598001fafbe8f94ec66dc827d012cfcbba2228569f448e89ea2208c8bf769293',
|
||||
'c7e887b546623635e93e0495598f1726821996c2377705b93a1f636f872bfa2d',
|
||||
'c315a437dd28062a770d481967136b1b5eb88b21ee53d0329c5897126e9db02c',
|
||||
'bb473deddc055fea6228f207da575347bb00404cd349d38c18026307a224cbff',
|
||||
'687e1873a8277591bb33d9adf9a13912efefe557cafc39a7952623e47255f16d',
|
||||
'1ac7ba754d6e2f94e0e86c46bfb262abbb74f450ef456d6b4d97aa80ce6da767',
|
||||
'012c97809614816b5d9494477d4b687d15b96eb69c0e8074a8516f31224b5c98',
|
||||
'91ffd26cfa4da5134c7ea262f7889c329f61f6a657225cc212f40056d986b3f4',
|
||||
'd97c828d8182a72180a06a78268330673f7c4e0635947c04c02323fd45c0a52d',
|
||||
'efc04cdc391c7e9119bd38668a534e65fe31036d6a62112e44ebeb11f9c57080',
|
||||
'992cf5c053442a5fbc4faf583e04e50bb70d2f39fbb6a503f89e56a63e18578a',
|
||||
'38640e9f21983e67b539caccae5ecf615ae2764f75a09c9c59b76483c1fbc735',
|
||||
'213dd34c7efe4fb27a6b35f6b4000d1fe03281af3c723e5c9f94747a5f31cd3b',
|
||||
'ec246eeeb9ced3f7ad33ed28660dd9bb0732513db4e2fa278b60cde3682a4ccd',
|
||||
'ac9b61d446648c3005d7892bf3a8719f4c8181cfdcbc2b79fef10a279b911095',
|
||||
'7bf8b22959e34e3a43f7079223e83a9754617d391e213dfd808e41b9bead4ce7',
|
||||
'68d4b5d4fa0e302b64ccc5af792913ac4c88ec95c07ddf40694256eb88ce9f3d',
|
||||
'b2c2420f05f9abe36315919336b37e4e0fa33ff7e76a492767006fdb5d935462',
|
||||
'134f61bbd0bbb69aed5343904551a3e6c1aa7dcdd77e903e7023eb7c60320aa7',
|
||||
'4693f9bff7d4f3986a7d176e6e06f72ad1490d805c99e25347b8de77b4db6d9b',
|
||||
'853e26f741953b0fd5bdb424e8ab9e8b3750eaa8ef61e47902c91e554e9c73b9',
|
||||
'f7de536361abaa0e158156cf0ea4f63a99b5e4054f8fa4c9d45f6285cad55694',
|
||||
'4c230608860a99ae8d7bd5c2cc17fa52096b9a61bedb17cb7617864ad29ca7a6',
|
||||
'aeb920ea87952dadb1fb759291e3388139a872865001886ed84752e93c250c2a',
|
||||
'aba4ad9b480b9df3d08ca5e87b0c2440d4e4ea21224c2eb42cbae469d089b931',
|
||||
'05825607d7fdf2d82ef4c3c8c2aea961ad98d60edff7d018983e21204c0d93d1',
|
||||
'a742f8b6af82d8a6ca2357c5f1cf91defbd066267d75c048b352366585025962',
|
||||
'2bcac89599000b42c95ae23835a713704ed79789c84fef149a874ff733f017a2',
|
||||
'ac1ed07d048f105a9e5b7ab85b09a492d5baff14b8bfb0e9fd789486eea2b974',
|
||||
'e48d0ecfaf497d5b27c25d99e156cb0579d440d6e31fb62473696dbf95e010e4',
|
||||
'12a91fadf8b21644fd0f934f3c4a8f62ba862ffd20e8e961154c15c13884ed3d',
|
||||
'7cbee96e139897dc98fbef3be81ad4d964d235cb12141fb66727e6e5df73a878',
|
||||
'ebf66abb597ae572a7297cb0871e355accafad8377b8e78bf164ce2a18de4baf',
|
||||
'71b933b07e4ff7818ce059d008829e453c6ff02ec0a7db393fc2d870f37a7286',
|
||||
'7cf7c51331220b8d3ebaed9c29398a16d98156e2613cb088f2b0e08a1be4cf4f',
|
||||
'3e41a108e0f64ad276b979e1ce068279e16f7bc7e4aa1d211e17b81161df1602',
|
||||
'886502a82ab47ba8d86710aa9de3d46ea65c47af6ee8de450cceb8b11b045f50',
|
||||
'c021bc5f0954fee94f46ea09487e10a84840d02f64810bc08d9e551f7d416814',
|
||||
'2030516e8a5fe19ae79c336fce26382a749d3fd0ec91e537d4bd2358c12dfb22',
|
||||
'556698dac8317fd36dfbdf25a79cb112d5425860605cbaf507f23bf7e9f42afe',
|
||||
'2f867ba67773fdc3e92fced99a6409ad39d0b880fde8f109a81730c4451d0178',
|
||||
'172ec218f119dfae98896dff29dd9876c94af87417f9ae4c7014bb4e4b96afc7',
|
||||
'3f85814a18195f879aa962f95d26bd82a278f2b82320218f6b3bd6f7f667a6d9',
|
||||
'1b618fbaa566b3d498c12e982c9ec52e4da85a8c54f38f34c090394f23c184c1',
|
||||
'0c758fb5692ffd41a3575d0af00cc7fbf2cbe5905a58323a88ae4244f6e4c993',
|
||||
'a931360cad628c7f12a6c1c4b753b0f4062aef3ce65a1ae3f19369dadf3ae23d',
|
||||
'cbac7d773b1e3b3c6691d7abb7e9df045c8ba19268ded153207f5e804352ec5d',
|
||||
'23a196d3802ed3c1b384019a82325840d32f71950c4580b03445e0898e14053c',
|
||||
'f4495470f226c8c214be08fdfad4bc4a2a9dbea9136a210df0d4b64929e6fc14',
|
||||
'e290dd270b467f34ab1c002d340fa016257ff19e5833fdbbf2cb401c3b2817de',
|
||||
'9fc7b5ded3c15042b2a6582dc39be016d24a682d5e61ad1eff9c63309848f706',
|
||||
'8cca67a36d17d5e6341cb592fd7bef9926c9e3aa1027ea11a7d8bd260b576e04',
|
||||
'409392f560f86831da4373ee5e0074260595d7bc24183b60ed700d4583d3f6f0',
|
||||
'2802165de090915546f3398cd849164a19f92adbc361adc99b0f20c8ea071054',
|
||||
'ad839168d9f8a4be95ba9ef9a692f07256ae43fe6f9864e290691b0256ce50a9',
|
||||
'75fdaa5038c284b86d6e8affe8b2807e467b86600e79af3689fbc06328cbf894',
|
||||
'e57cb79487dd57902432b250733813bd96a84efce59f650fac26e6696aefafc3',
|
||||
'56f34e8b96557e90c1f24b52d0c89d51086acf1b00f634cf1dde9233b8eaaa3e',
|
||||
'1b53ee94aaf34e4b159d48de352c7f0661d0a40edff95a0b1639b4090e974472',
|
||||
'05705e2a81757c14bd383ea98dda544eb10e6bc07bae435e2518dbe133525375',
|
||||
'd8b2866e8a309db53e529ec32911d82f5ca16cff76216891a9676aa31aaa6c42',
|
||||
'f5041c241270eb04c71ec2c95d4c38d803b1237b0f29fd4db3eb397669e88699',
|
||||
'9a4ce077c349322f595e0ee79ed0da5fab66752cbfef8f87d0e9d0723c7530dd',
|
||||
'657b09f3d0f52b5b8f2f97163a0edf0c04f075408a07bbeb3a4101a891990d62',
|
||||
'1e3f7bd5a58fa533344aa8ed3ac122bb9e70d4ef50d004530821948f5fe6315a',
|
||||
'80dccf3fd83dfd0d35aa28585922ab89d5313997673eaf905cea9c0b225c7b5f',
|
||||
'8a0d0fbf6377d83bb08b514b4b1c43acc95d751714f8925645cb6bc856ca150a',
|
||||
'9fa5b487738ad2844cc6348a901918f659a3b89e9c0dfeead30dd94bcf42ef8e',
|
||||
'80832c4a1677f5ea2560f668e9354dd36997f03728cfa55e1b38337c0c9ef818',
|
||||
'ab37ddb683137e74080d026b590b96ae9bb447722f305a5ac570ec1df9b1743c',
|
||||
'3ee735a694c2559b693aa68629361e15d12265ad6a3dedf488b0b00fac9754ba',
|
||||
'd6fcd23219b647e4cbd5eb2d0ad01ec8838a4b2901fc325cc3701981ca6c888b',
|
||||
'0520ec2f5bf7a755dacb50c6bf233e3515434763db0139ccd9faefbb8207612d',
|
||||
'aff3b75f3f581264d7661662b92f5ad37c1d32bd45ff81a4ed8adc9ef30dd989',
|
||||
'd0dd650befd3ba63dc25102c627c921b9cbeb0b130686935b5c927cb7ccd5e3b',
|
||||
'e1149816b10a8514fb3e2cab2c08bee9f73ce76221701246a589bbb67302d8a9',
|
||||
'7da3f441de9054317e72b5dbf979da01e6bceebb8478eae6a22849d90292635c',
|
||||
'1230b1fc8a7d9215edc2d4a2decbdd0a6e216c924278c91fc5d10e7d60192d94',
|
||||
'5750d716b4808f751febc38806ba170bf6d5199a7816be514e3f932fbe0cb871',
|
||||
'6fc59b2f10feba954aa6820b3ca987ee81d5cc1da3c63ce827301c569dfb39ce',
|
||||
'c7c3fe1eebdc7b5a939326e8ddb83e8bf2b780b65678cb62f208b040abdd35e2',
|
||||
'0c75c1a15cf34a314ee478f4a5ce0b8a6b36528ef7a820696c3e4246c5a15864',
|
||||
'216dc12a108569a3c7cdde4aed43a6c330139dda3ccc4a108905db3861899050',
|
||||
'a57be6ae6756f28b02f59dadf7e0d7d8807f10fa15ced1ad3585521a1d995a89',
|
||||
'816aef875953716cd7a581f732f53dd435dab66d09c361d2d6592de17755d8a8',
|
||||
'9a76893226693b6ea97e6a738f9d10fb3d0b43ae0e8b7d8123ea76ce97989c7e',
|
||||
'8daedb9a271529dbb7dc3b607fe5eb2d3211770758dd3b0a3593d2d7954e2d5b',
|
||||
'16dbc0aa5dd2c774f505100f733786d8a175fcbbb59c43e1fbff3e1eaf31cb4a',
|
||||
'8606cb899c6aeaf51b9db0fe4924a9fd5dabc19f8826f2bc1c1d7da14d2c2c99',
|
||||
'8479731aeda57bd37eadb51a507e307f3bd95e69dbca94f3bc21726066ad6dfd',
|
||||
'58473a9ea82efa3f3b3d8fc83ed8863127b33ae8deae6307201edb6dde61de29',
|
||||
'9a9255d53af116de8ba27ce35b4c7e15640657a0fcb888c70d95431dacd8f830',
|
||||
'9eb05ffba39fd8596a45493e18d2510bf3ef065c51d6e13abe66aa57e05cfdb7',
|
||||
'81dcc3a505eace3f879d8f702776770f9df50e521d1428a85daf04f9ad2150e0',
|
||||
'e3e3c4aa3acbbc85332af9d564bc24165e1687f6b1adcbfae77a8f03c72ac28c',
|
||||
'6746c80b4eb56aea45e64e7289bba3edbf45ecf8206481ff6302122984cd526a',
|
||||
'2b628e52764d7d62c0868b212357cdd12d9149822f4e9845d918a08d1ae990c0',
|
||||
'e4bfe80d58c91994613909dc4b1a12496896c004af7b5701483de45d2823d78e',
|
||||
'ebb4ba150cef2734345b5d641bbed03a21eafae933c99e009212ef04574a8530',
|
||||
'3966ec73b154acc697ac5cf5b24b40bdb0db9e398836d76d4b880e3b2af1aa27',
|
||||
'ef7e4831b3a84636518d6e4bfce64a43db2a5dda9cca2b44f39033bdc40d6243',
|
||||
'7abf6acf5c8e549ddbb15ae8d8b388c1c197e698737c9785501ed1f94930b7d9',
|
||||
'88018ded66813f0ca95def474c630692019967b9e36888dadd94124719b682f6',
|
||||
'3930876b9fc7529036b008b1b8bb997522a441635a0c25ec02fb6d9026e55a97',
|
||||
'0a4049d57e833b5695fac93dd1fbef3166b44b12ad11248662383ae051e15827',
|
||||
'81dcc0678bb6a765e48c3209654fe90089ce44ff5618477e39ab286476df052b',
|
||||
'e69b3a36a4461912dc08346b11ddcb9db796f885fd01936e662fe29297b099a4',
|
||||
'5ac6503b0d8da6917646e6dcc87edc58e94245324cc204f4dd4af01563acd427',
|
||||
'df6dda21359a30bc271780971c1abd56a6ef167e480887888e73a86d3bf605e9',
|
||||
'e8e6e47071e7b7df2580f225cfbbedf84ce67746626628d33097e4b7dc571107',
|
||||
'53e40ead62051e19cb9ba8133e3e5c1ce00ddcad8acf342a224360b0acc14777',
|
||||
'9ccd53fe80be786aa984638462fb28afdf122b34d78f4687ec632bb19de2371a',
|
||||
'cbd48052c48d788466a3e8118c56c97fe146e5546faaf93e2bc3c47e45939753',
|
||||
'256883b14e2af44dadb28e1b34b2ac0f0f4c91c34ec9169e29036158acaa95b9',
|
||||
'4471b91ab42db7c4dd8490ab95a2ee8d04e3ef5c3d6fc71ac74b2b26914d1641',
|
||||
'a5eb08038f8f1155ed86e631906fc13095f6bba41de5d4e795758ec8c8df8af1',
|
||||
'dc1db64ed8b48a910e060a6b866374c578784e9ac49ab2774092ac71501934ac',
|
||||
'285413b2f2ee873d34319ee0bbfbb90f32da434cc87e3db5ed121bb398ed964b',
|
||||
'0216e0f81f750f26f1998bc3934e3e124c9945e685a60b25e8fbd9625ab6b599',
|
||||
'38c410f5b9d4072050755b31dca89fd5395c6785eeb3d790f320ff941c5a93bf',
|
||||
'f18417b39d617ab1c18fdf91ebd0fc6d5516bb34cf39364037bce81fa04cecb1',
|
||||
'1fa877de67259d19863a2a34bcc6962a2b25fcbf5cbecd7ede8f1fa36688a796',
|
||||
'5bd169e67c82c2c2e98ef7008bdf261f2ddf30b1c00f9e7f275bb3e8a28dc9a2',
|
||||
'c80abeebb669ad5deeb5f5ec8ea6b7a05ddf7d31ec4c0a2ee20b0b98caec6746',
|
||||
'e76d3fbda5ba374e6bf8e50fadc3bbb9ba5c206ebdec89a3a54cf3dd84a07016',
|
||||
'7bba9dc5b5db2071d17752b1044c1eced96aaf2dd46e9b433750e8ea0dcc1870',
|
||||
'f29b1b1ab9bab163018ee3da15232cca78ec52dbc34eda5b822ec1d80fc21bd0',
|
||||
'9ee3e3e7e900f1e11d308c4b2b3076d272cf70124f9f51e1da60f37846cdd2f4',
|
||||
'70ea3b0176927d9096a18508cd123a290325920a9d00a89b5de04273fbc76b85',
|
||||
'67de25c02a4aaba23bdc973c8bb0b5796d47cc0659d43dff1f97de174963b68e',
|
||||
'b2168e4e0f18b0e64100b517ed95257d73f0620df885c13d2ecf79367b384cee',
|
||||
'2e7dec2428853b2c71760745541f7afe9825b5dd77df06511d8441a94bacc927',
|
||||
'ca9ffac4c43f0b48461dc5c263bea3f6f00611ceacabf6f895ba2b0101dbb68d',
|
||||
'7410d42d8fd1d5e9d2f5815cb93417998828ef3c4230bfbd412df0a4a7a2507a',
|
||||
'5010f684516dccd0b6ee0852c2512b4dc0066cf0d56f35302978db8ae32c6a81',
|
||||
'acaab585f7b79b719935ceb89523ddc54827f75c56883856154a56cdcd5ee988',
|
||||
'666de5d1440fee7331aaf0123a62ef2d8ba57453a0769635ac6cd01e633f7712',
|
||||
'a6f98658f6eabaf902d8b3871a4b101d16196e8a4b241e1558fe29966e103e8d',
|
||||
'891546a8b29f3047ddcfe5b00e45fd55756373105ea8637dfcff547b6ea9535f',
|
||||
'18dfbc1ac5d25b0761137dbd22c17c829d0f0ef1d82344e9c89c286694da24e8',
|
||||
'b54b9b67f8fed54bbf5a2666dbdf4b23cff1d1b6f4afc985b2e6d3305a9ff80f',
|
||||
'7db442e132ba59bc1289aa98b0d3e806004f8ec12811af1e2e33c69bfde729e1',
|
||||
'250f37cdc15e817d2f160d9956c71fe3eb5db74556e4adf9a4ffafba74010396',
|
||||
'4ab8a3dd1ddf8ad43dab13a27f66a6544f290597fa96040e0e1db9263aa479f8',
|
||||
'ee61727a0766df939ccdc860334044c79a3c9b156200bc3aa32973483d8341ae',
|
||||
'3f68c7ec63ac11ebb98f94b339b05c104984fda50103060144e5a2bfccc9da95',
|
||||
'056f29816b8af8f56682bc4d7cf094111da7733e726cd13d6b3e8ea03e92a0d5',
|
||||
'f5ec43a28acbeff1f3318a5bcac7c66ddb5230b79db2d105bcbe15f3c1148d69',
|
||||
'2a6960ad1d8dd547555cfbd5e4600f1eaa1c8eda34de0374ec4a26eaaaa33b4e',
|
||||
'dcc1ea7baab93384f76b796866199754742f7b96d6b4c120165c04a6c4f5ce10',
|
||||
'13d5df179221379c6a78c07c793ff53487cae6bf9fe882541ab0e735e3eada3b',
|
||||
'8c59e4407641a01e8ff91f9980dc236f4ecd6fcf52589a099a961633967714e1',
|
||||
'833b1ac6a251fd08fd6d908fea2a4ee1e040bca93fc1a38ec3820e0c10bd82ea',
|
||||
'a244f927f3b40b8f6c391570c765418f2f6e708eac9006c51a7feff4af3b2b9e',
|
||||
'3d99ed9550cf1196e6c4d20c259620f858c3d703374c128ce7b590310c83046d',
|
||||
'2b35c47d7b87761f0ae43ac56ac27b9f25830367b595be8c240e94600c6e3312',
|
||||
'5d11ed37d24dc767305cb7e1467d87c065ac4bc8a426de38991ff59aa8735d02',
|
||||
'b836478e1ca0640dce6fd910a5096272c8330990cd97864ac2bf14ef6b23914a',
|
||||
'9100f946d6ccde3a597f90d39fc1215baddc7413643d85c21c3eee5d2dd32894',
|
||||
'da70eedd23e663aa1a74b9766935b479222a72afba5c795158dad41a3bd77e40',
|
||||
'f067ed6a0dbd43aa0a9254e69fd66bdd8acb87de936c258cfb02285f2c11fa79',
|
||||
'715c99c7d57580cf9753b4c1d795e45a83fbb228c0d36fbe20faf39bdd6d4e85',
|
||||
'e457d6ad1e67cb9bbd17cbd698fa6d7dae0c9b7ad6cbd6539634e32a719c8492',
|
||||
'ece3ea8103e02483c64a70a4bdcee8ceb6278f2533f3f48dbeedfba94531d4ae',
|
||||
'388aa5d3667a97c68d3d56f8f3ee8d3d36091f17fe5d1b0d5d84c93b2ffe40bd',
|
||||
'8b6b31b9ad7c3d5cd84bf98947b9cdb59df8a25ff738101013be4fd65e1dd1a3',
|
||||
'066291f6bbd25f3c853db7d8b95c9a1cfb9bf1c1c99fb95a9b7869d90f1c2903',
|
||||
'a707efbccdceed42967a66f5539b93ed7560d467304016c4780d7755a565d4c4',
|
||||
'38c53dfb70be7e792b07a6a35b8a6a0aba02c5c5f38baf5c823fdfd9e42d657e',
|
||||
'f2911386501d9ab9d720cf8ad10503d5634bf4b7d12b56dfb74fecc6e4093f68',
|
||||
'c6f2bdd52b81e6e4f6595abd4d7fb31f651169d00ff326926b34947b28a83959',
|
||||
'293d94b18c98bb3223366b8ce74c28fbdf28e1f84a3350b0eb2d1804a577579b',
|
||||
'2c2fa5c0b51533165bc375c22e2781768270a383985d13bd6b67b6fd67f889eb',
|
||||
'caa09b82b72562e43f4b2275c091918e624d911661cc811bb5faec51f6088ef7',
|
||||
'24761e45e674395379fb17729c78cb939e6f74c5dffb9c961f495982c3ed1fe3',
|
||||
'55b70a82131ec94888d7ab54a7c515255c3938bb10bc784dc9b67f076e341a73',
|
||||
'6ab9057b977ebc3ca4d4ce74506c25cccdc566497c450b5415a39486f8657a03',
|
||||
'24066deee0ecee15a45f0a326d0f8dbc79761ebb93cf8c0377af440978fcf994',
|
||||
'20000d3f66ba76860d5a950688b9aa0d76cfea59b005d859914b1a46653a939b',
|
||||
'b92daa79603e3bdbc3bfe0f419e409b2ea10dc435beefe2959da16895d5dca1c',
|
||||
'e947948705b206d572b0e8f62f66a6551cbd6bc305d26ce7539a12f9aadf7571',
|
||||
'3d67c1b3f9b23910e3d35e6b0f2ccf44a0b540a45c18ba3c36264dd48e96af6a',
|
||||
'c7558babda04bccb764d0bbf3358425141902d22391d9f8c59159fec9e49b151',
|
||||
'0b732bb035675a50ff58f2c242e4710aece64670079c13044c79c9b7491f7000',
|
||||
'd120b5ef6d57ebf06eaf96bc933c967b16cbe6e2bf00741c30aa1c54ba64801f',
|
||||
'58d212ad6f58aef0f80116b441e57f6195bfef26b61463edec1183cdb04fe76d',
|
||||
'b8836f51d1e29bdfdba325565360268b8fad627473edecef7eaefee837c74003',
|
||||
'c547a3c124ae5685ffa7b8edaf96ec86f8b2d0d50cee8be3b1f0c76763069d9c',
|
||||
'5d168b769a2f67853d6295f7568be40bb7a16b8d65ba87635d1978d2ab11ba2a',
|
||||
'a2f675dc7302638cb60201064ca55077714d71fe096a315f2fe7401277caa5af',
|
||||
'c8aab5cd0160ae78cd2e8ac5fb0e093cdb5c4b6052a0a97bb04216826fa7a437',
|
||||
'ff68ca4035bfeb43fbf145fddd5e43f1cea54f11f7bee13058f027329a4a5fa4',
|
||||
'1d4e5487ae3c740f2ba6e541ac91bc2bfcd2999c518d807b426748803a350fd4',
|
||||
'6d244e1a06ce4ef578dd0f63aff0936706735119ca9c8d22d86c801414ab9741',
|
||||
'decf7329dbcc827b8fc524c9431e8998029ece12ce93b7b2f3e769a941fb8cea',
|
||||
'2fafcc0f2e63cbd07755be7b75ecea0adff9aa5ede2a52fdab4dfd0374cd483f',
|
||||
'aa85010dd46a546b535ef4cf5f07d65161e89828f3a77db7b9b56f0df59aae45',
|
||||
'07e8e1ee732cb0d356c9c0d1069c89d17adf6a9a334f745ec7867332548ca8e9',
|
||||
'0e01e81cada8162bfd5f8a8c818a6c69fedf02ceb5208523cbe5313b89ca1053',
|
||||
'6bb6c6472655084399852e00249f8cb247896d392b02d73b7f0dd818e1e29b07',
|
||||
'42d4636e2060f08f41c882e76b396b112ef627cc24c43dd5f83a1d1a7ead711a',
|
||||
'4858c9a188b0234fb9a8d47d0b4133650a030bd0611b87c3892e94951f8df852',
|
||||
'3fab3e36988d445a51c8783e531be3a02be40cd04796cfb61d40347442d3f794',
|
||||
'ebabc49636bd433d2ec8f0e518732ef8fa21d4d071cc3bc46cd79fa38a28b810',
|
||||
'a1d0343523b893fca84f47feb4a64d350a17d8eef5497ece697d02d79178b591',
|
||||
'262ebfd9130b7d28760d08ef8bfd3b86cdd3b2113d2caef7ea951a303dfa3846',
|
||||
'f76158edd50a154fa78203ed2362932fcb8253aae378903eded1e03f7021a257',
|
||||
'26178e950ac722f67ae56e571b284c0207684a6334a17748a94d260bc5f55274',
|
||||
'c378d1e493b40ef11fe6a15d9c2737a37809634c5abad5b33d7e393b4ae05d03',
|
||||
'984bd8379101be8fd80612d8ea2959a7865ec9718523550107ae3938df32011b',
|
||||
'c6f25a812a144858ac5ced37a93a9f4759ba0b1c0fdc431dce35f9ec1f1f4a99',
|
||||
'924c75c94424ff75e74b8b4e94358958b027b171df5e57899ad0d4dac37353b6',
|
||||
'0af35892a63f45931f6846ed190361cd073089e077165714b50b81a2e3dd9ba1',
|
||||
'cc80cefb26c3b2b0daef233e606d5ffc80fa17427d18e30489673e06ef4b87f7',
|
||||
'c2f8c8117447f3978b0818dcf6f70116ac56fd184dd1278494e103fc6d74a887',
|
||||
'bdecf6bfc1ba0df6e862c831992207796acc797968358828c06e7a51e090098f',
|
||||
'24d1a26e3dab02fe4572d2aa7dbd3ec30f0693db26f273d0ab2cb0c13b5e6451',
|
||||
'ec56f58b09299a300b140565d7d3e68782b6e2fbeb4b7ea97ac057989061dd3f',
|
||||
'11a437c1aba3c119ddfab31b3e8c841deeeb913ef57f7e48f2c9cf5a28fa42bc',
|
||||
'53c7e6114b850a2cb496c9b3c69a623eaea2cb1d33dd817e4765edaa6823c228',
|
||||
'154c3e96fee5db14f8773e18af14857913509da999b46cdd3d4c169760c83ad2',
|
||||
'40b9916f093e027a8786641818920620472fbcf68f701d1b680632e6996bded3',
|
||||
'24c4cbba07119831a726b05305d96da02ff8b148f0da440fe233bcaa32c72f6f',
|
||||
'5d201510250020b783689688abbf8ecf2594a96a08f2bfec6ce0574465dded71',
|
||||
'043b97e336ee6fdbbe2b50f22af83275a4084805d2d5645962454b6c9b8053a0',
|
||||
'564835cbaea774948568be36cf52fcdd83934eb0a27512dbe3e2db47b9e6635a',
|
||||
'f21c33f47bde40a2a101c9cde8027aaf61a3137de2422b30035a04c270894183',
|
||||
'9db0ef74e66cbb842eb0e07343a03c5c567e372b3f23b943c788a4f250f67891',
|
||||
'ab8d08655ff1d3fe8758d562235fd23e7cf9dcaad658872a49e5d3183b6ccebd',
|
||||
'6f27f77e7bcf46a1e963ade0309733543031dccdd47caac174d7d27ce8077e8b',
|
||||
'e3cd54da7e444caa6207569525a670ebae1278de4e3fe2684b3e33f5ef90cc1b',
|
||||
'b2c3e33a51d22c4c08fc0989c873c9cc4150579b1e6163fa694ad51d53d712dc',
|
||||
'be7fda983e13189b4c77e0a80920b6e0e0ea80c3b84dbe7e7117d253f48112f4',
|
||||
'b6008c28fae08aa427e5bd3aad36f10021f16c77cfeabed07f97cc7dc1f1284a',
|
||||
'6e4e6760c538f2e97b3adbfbbcde57f8966b7ea8fcb5bf7efec913fd2a2b0c55',
|
||||
'4ae51fd1834aa5bd9a6f7ec39fc663338dc5d2e20761566d90cc68b1cb875ed8',
|
||||
'b673aad75ab1fdb5401abfa1bf89f3add2ebc468df3624a478f4fe859d8d55e2',
|
||||
'13c9471a9855913539836660398da0f3f99ada08479c69d1b7fcaa3461dd7e59',
|
||||
'2c11f4a7f99a1d23a58bb636350fe849f29cbac1b2a1112d9f1ed5bc5b313ccd',
|
||||
'c7d3c0706b11ae741c05a1ef150dd65b5494d6d54c9a86e2617854e6aeeebbd9',
|
||||
'194e10c93893afa064c3ac04c0dd808d791c3d4b7556e89d8d9cb225c4b33339',
|
||||
'6fc4988b8f78546b1688991845908f134b6a482e6994b3d48317bf08db292185',
|
||||
'5665beb8b0955525813b5981cd142ed4d03fba38a6f3e5ad268e0cc270d1cd11',
|
||||
'b883d68f5fe51936431ba4256738053b1d0426d4cb64b16e83badc5e9fbe3b81',
|
||||
'53e7b27ea59c2f6dbb50769e43554df35af89f4822d0466b007dd6f6deafff02',
|
||||
'1f1a0229d4640f01901588d9dec22d13fc3eb34a61b32938efbf5334b2800afa',
|
||||
'c2b405afa0fa6668852aee4d88040853fab800e72b57581418e5506f214c7d1f',
|
||||
'c08aa1c286d709fdc7473744977188c895ba011014247e4efa8d07e78fec695c',
|
||||
'f03f5789d3336b80d002d59fdf918bdb775b00956ed5528e86aa994acb38fe2d'
|
||||
]
|
||||
|
||||
@golden_keyed = [
|
||||
'48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49',
|
||||
'40d15fee7c328830166ac3f918650f807e7e01e177258cdc0a39b11f598066f1',
|
||||
'6bb71300644cd3991b26ccd4d274acd1adeab8b1d7914546c1198bbe9fc9d803',
|
||||
'1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b',
|
||||
'f6c3fbadb4cc687a0064a5be6e791bec63b868ad62fba61b3757ef9ca52e05b2',
|
||||
'49c1f21188dfd769aea0e911dd6b41f14dab109d2b85977aa3088b5c707e8598',
|
||||
'fdd8993dcd43f696d44f3cea0ff35345234ec8ee083eb3cada017c7f78c17143',
|
||||
'e6c8125637438d0905b749f46560ac89fd471cf8692e28fab982f73f019b83a9',
|
||||
'19fc8ca6979d60e6edd3b4541e2f967ced740df6ec1eaebbfe813832e96b2974',
|
||||
'a6ad777ce881b52bb5a4421ab6cdd2dfba13e963652d4d6d122aee46548c14a7',
|
||||
'f5c4b2ba1a00781b13aba0425242c69cb1552f3f71a9a3bb22b4a6b4277b46dd',
|
||||
'e33c4c9bd0cc7e45c80e65c77fa5997fec7002738541509e68a9423891e822a3',
|
||||
'fba16169b2c3ee105be6e1e650e5cbf40746b6753d036ab55179014ad7ef6651',
|
||||
'f5c4bec6d62fc608bf41cc115f16d61c7efd3ff6c65692bbe0afffb1fede7475',
|
||||
'a4862e76db847f05ba17ede5da4e7f91b5925cf1ad4ba12732c3995742a5cd6e',
|
||||
'65f4b860cd15b38ef814a1a804314a55be953caa65fd758ad989ff34a41c1eea',
|
||||
'19ba234f0a4f38637d1839f9d9f76ad91c8522307143c97d5f93f69274cec9a7',
|
||||
'1a67186ca4a5cb8e65fca0e2ecbc5ddc14ae381bb8bffeb9e0a103449e3ef03c',
|
||||
'afbea317b5a2e89c0bd90ccf5d7fd0ed57fe585e4be3271b0a6bf0f5786b0f26',
|
||||
'f1b01558ce541262f5ec34299d6fb4090009e3434be2f49105cf46af4d2d4124',
|
||||
'13a0a0c86335635eaa74ca2d5d488c797bbb4f47dc07105015ed6a1f3309efce',
|
||||
'1580afeebebb346f94d59fe62da0b79237ead7b1491f5667a90e45edf6ca8b03',
|
||||
'20be1a875b38c573dd7faaa0de489d655c11efb6a552698e07a2d331b5f655c3',
|
||||
'be1fe3c4c04018c54c4a0f6b9a2ed3c53abe3a9f76b4d26de56fc9ae95059a99',
|
||||
'e3e3ace537eb3edd8463d9ad3582e13cf86533ffde43d668dd2e93bbdbd7195a',
|
||||
'110c50c0bf2c6e7aeb7e435d92d132ab6655168e78a2decdec3330777684d9c1',
|
||||
'e9ba8f505c9c80c08666a701f3367e6cc665f34b22e73c3c0417eb1c2206082f',
|
||||
'26cd66fca02379c76df12317052bcafd6cd8c3a7b890d805f36c49989782433a',
|
||||
'213f3596d6e3a5d0e9932cd2159146015e2abc949f4729ee2632fe1edb78d337',
|
||||
'1015d70108e03be1c702fe97253607d14aee591f2413ea6787427b6459ff219a',
|
||||
'3ca989de10cfe609909472c8d35610805b2f977734cf652cc64b3bfc882d5d89',
|
||||
'b6156f72d380ee9ea6acd190464f2307a5c179ef01fd71f99f2d0f7a57360aea',
|
||||
'c03bc642b20959cbe133a0303e0c1abff3e31ec8e1a328ec8565c36decff5265',
|
||||
'2c3e08176f760c6264c3a2cd66fec6c3d78de43fc192457b2a4a660a1e0eb22b',
|
||||
'f738c02f3c1b190c512b1a32deabf353728e0e9ab034490e3c3409946a97aeec',
|
||||
'8b1880df301cc963418811088964839287ff7fe31c49ea6ebd9e48bdeee497c5',
|
||||
'1e75cb21c60989020375f1a7a242839f0b0b68973a4c2a05cf7555ed5aaec4c1',
|
||||
'62bf8a9c32a5bccf290b6c474d75b2a2a4093f1a9e27139433a8f2b3bce7b8d7',
|
||||
'166c8350d3173b5e702b783dfd33c66ee0432742e9b92b997fd23c60dc6756ca',
|
||||
'044a14d822a90cacf2f5a101428adc8f4109386ccb158bf905c8618b8ee24ec3',
|
||||
'387d397ea43a994be84d2d544afbe481a2000f55252696bba2c50c8ebd101347',
|
||||
'56f8ccf1f86409b46ce36166ae9165138441577589db08cbc5f66ca29743b9fd',
|
||||
'9706c092b04d91f53dff91fa37b7493d28b576b5d710469df79401662236fc03',
|
||||
'877968686c068ce2f7e2adcff68bf8748edf3cf862cfb4d3947a3106958054e3',
|
||||
'8817e5719879acf7024787eccdb271035566cfa333e049407c0178ccc57a5b9f',
|
||||
'8938249e4b50cadaccdf5b18621326cbb15253e33a20f5636e995d72478de472',
|
||||
'f164abba4963a44d107257e3232d90aca5e66a1408248c51741e991db5227756',
|
||||
'd05563e2b1cba0c4a2a1e8bde3a1a0d9f5b40c85a070d6f5fb21066ead5d0601',
|
||||
'03fbb16384f0a3866f4c3117877666efbf124597564b293d4aab0d269fabddfa',
|
||||
'5fa8486ac0e52964d1881bbe338eb54be2f719549224892057b4da04ba8b3475',
|
||||
'cdfabcee46911111236a31708b2539d71fc211d9b09c0d8530a11e1dbf6eed01',
|
||||
'4f82de03b9504793b82a07a0bdcdff314d759e7b62d26b784946b0d36f916f52',
|
||||
'259ec7f173bcc76a0994c967b4f5f024c56057fb79c965c4fae41875f06a0e4c',
|
||||
'193cc8e7c3e08bb30f5437aa27ade1f142369b246a675b2383e6da9b49a9809e',
|
||||
'5c10896f0e2856b2a2eee0fe4a2c1633565d18f0e93e1fab26c373e8f829654d',
|
||||
'f16012d93f28851a1eb989f5d0b43f3f39ca73c9a62d5181bff237536bd348c3',
|
||||
'2966b3cfae1e44ea996dc5d686cf25fa053fb6f67201b9e46eade85d0ad6b806',
|
||||
'ddb8782485e900bc60bcf4c33a6fd585680cc683d516efa03eb9985fad8715fb',
|
||||
'4c4d6e71aea05786413148fc7a786b0ecaf582cff1209f5a809fba8504ce662c',
|
||||
'fb4c5e86d7b2229b99b8ba6d94c247ef964aa3a2bae8edc77569f28dbbff2d4e',
|
||||
'e94f526de9019633ecd54ac6120f23958d7718f1e7717bf329211a4faeed4e6d',
|
||||
'cbd6660a10db3f23f7a03d4b9d4044c7932b2801ac89d60bc9eb92d65a46c2a0',
|
||||
'8818bbd3db4dc123b25cbba5f54c2bc4b3fcf9bf7d7a7709f4ae588b267c4ece',
|
||||
'c65382513f07460da39833cb666c5ed82e61b9e998f4b0c4287cee56c3cc9bcd',
|
||||
'8975b0577fd35566d750b362b0897a26c399136df07bababbde6203ff2954ed4',
|
||||
'21fe0ceb0052be7fb0f004187cacd7de67fa6eb0938d927677f2398c132317a8',
|
||||
'2ef73f3c26f12d93889f3c78b6a66c1d52b649dc9e856e2c172ea7c58ac2b5e3',
|
||||
'388a3cd56d73867abb5f8401492b6e2681eb69851e767fd84210a56076fb3dd3',
|
||||
'af533e022fc9439e4e3cb838ecd18692232adf6fe9839526d3c3dd1b71910b1a',
|
||||
'751c09d41a9343882a81cd13ee40818d12eb44c6c7f40df16e4aea8fab91972a',
|
||||
'5b73ddb68d9d2b0aa265a07988d6b88ae9aac582af83032f8a9b21a2e1b7bf18',
|
||||
'3da29126c7c5d7f43e64242a79feaa4ef3459cdeccc898ed59a97f6ec93b9dab',
|
||||
'566dc920293da5cb4fe0aa8abda8bbf56f552313bff19046641e3615c1e3ed3f',
|
||||
'4115bea02f73f97f629e5c5590720c01e7e449ae2a6697d4d2783321303692f9',
|
||||
'4ce08f4762468a7670012164878d68340c52a35e66c1884d5c864889abc96677',
|
||||
'81ea0b7804124e0c22ea5fc71104a2afcb52a1fa816f3ecb7dcb5d9dea1786d0',
|
||||
'fe362733b05f6bedaf9379d7f7936ede209b1f8323c3922549d9e73681b5db7b',
|
||||
'eff37d30dfd20359be4e73fdf40d27734b3df90a97a55ed745297294ca85d09f',
|
||||
'172ffc67153d12e0ca76a8b6cd5d4731885b39ce0cac93a8972a18006c8b8baf',
|
||||
'c47957f1cc88e83ef9445839709a480a036bed5f88ac0fcc8e1e703ffaac132c',
|
||||
'30f3548370cfdceda5c37b569b6175e799eef1a62aaa943245ae7669c227a7b5',
|
||||
'c95dcb3cf1f27d0eef2f25d2413870904a877c4a56c2de1e83e2bc2ae2e46821',
|
||||
'd5d0b5d705434cd46b185749f66bfb5836dcdf6ee549a2b7a4aee7f58007caaf',
|
||||
'bbc124a712f15d07c300e05b668389a439c91777f721f8320c1c9078066d2c7e',
|
||||
'a451b48c35a6c7854cfaae60262e76990816382ac0667e5a5c9e1b46c4342ddf',
|
||||
'b0d150fb55e778d01147f0b5d89d99ecb20ff07e5e6760d6b645eb5b654c622b',
|
||||
'34f737c0ab219951eee89a9f8dac299c9d4c38f33fa494c5c6eefc92b6db08bc',
|
||||
'1a62cc3a00800dcbd99891080c1e098458193a8cc9f970ea99fbeff00318c289',
|
||||
'cfce55ebafc840d7ae48281c7fd57ec8b482d4b704437495495ac414cf4a374b',
|
||||
'6746facf71146d999dabd05d093ae586648d1ee28e72617b99d0f0086e1e45bf',
|
||||
'571ced283b3f23b4e750bf12a2caf1781847bd890e43603cdc5976102b7bb11b',
|
||||
'cfcb765b048e35022c5d089d26e85a36b005a2b80493d03a144e09f409b6afd1',
|
||||
'4050c7a27705bb27f42089b299f3cbe5054ead68727e8ef9318ce6f25cd6f31d',
|
||||
'184070bd5d265fbdc142cd1c5cd0d7e414e70369a266d627c8fba84fa5e84c34',
|
||||
'9edda9a4443902a9588c0d0ccc62b930218479a6841e6fe7d43003f04b1fd643',
|
||||
'e412feef7908324a6da1841629f35d3d358642019310ec57c614836b63d30763',
|
||||
'1a2b8edff3f9acc1554fcbae3cf1d6298c6462e22e5eb0259684f835012bd13f',
|
||||
'288c4ad9b9409762ea07c24a41f04f69a7d74bee2d95435374bde946d7241c7b',
|
||||
'805691bb286748cfb591d3aebe7e6f4e4dc6e2808c65143cc004e4eb6fd09d43',
|
||||
'd4ac8d3a0afc6cfa7b460ae3001baeb36dadb37da07d2e8ac91822df348aed3d',
|
||||
'c376617014d20158bced3d3ba552b6eccf84e62aa3eb650e90029c84d13eea69',
|
||||
'c41f09f43cecae7293d6007ca0a357087d5ae59be500c1cd5b289ee810c7b082',
|
||||
'03d1ced1fba5c39155c44b7765cb760c78708dcfc80b0bd8ade3a56da8830b29',
|
||||
'09bde6f152218dc92c41d7f45387e63e5869d807ec70b821405dbd884b7fcf4b',
|
||||
'71c9036e18179b90b37d39e9f05eb89cc5fc341fd7c477d0d7493285faca08a4',
|
||||
'5916833ebb05cd919ca7fe83b692d3205bef72392b2cf6bb0a6d43f994f95f11',
|
||||
'f63aab3ec641b3b024964c2b437c04f6043c4c7e0279239995401958f86bbe54',
|
||||
'f172b180bfb09740493120b6326cbdc561e477def9bbcfd28cc8c1c5e3379a31',
|
||||
'cb9b89cc18381dd9141ade588654d4e6a231d5bf49d4d59ac27d869cbe100cf3',
|
||||
'7bd8815046fdd810a923e1984aaebdcdf84d87c8992d68b5eeb460f93eb3c8d7',
|
||||
'607be66862fd08ee5b19facac09dfdbcd40c312101d66e6ebd2b841f1b9a9325',
|
||||
'9fe03bbe69ab1834f5219b0da88a08b30a66c5913f0151963c360560db0387b3',
|
||||
'90a83585717b75f0e9b725e055eeeeb9e7a028ea7e6cbc07b20917ec0363e38c',
|
||||
'336ea0530f4a7469126e0218587ebbde3358a0b31c29d200f7dc7eb15c6aadd8',
|
||||
'a79e76dc0abca4396f0747cd7b748df913007626b1d659da0c1f78b9303d01a3',
|
||||
'44e78a773756e0951519504d7038d28d0213a37e0ce375371757bc996311e3b8',
|
||||
'77ac012a3f754dcfeab5eb996be9cd2d1f96111b6e49f3994df181f28569d825',
|
||||
'ce5a10db6fccdaf140aaa4ded6250a9c06e9222bc9f9f3658a4aff935f2b9f3a',
|
||||
'ecc203a7fe2be4abd55bb53e6e673572e0078da8cd375ef430cc97f9f80083af',
|
||||
'14a5186de9d7a18b0412b8563e51cc5433840b4a129a8ff963b33a3c4afe8ebb',
|
||||
'13f8ef95cb86e6a638931c8e107673eb76ba10d7c2cd70b9d9920bbeed929409',
|
||||
'0b338f4ee12f2dfcb78713377941e0b0632152581d1332516e4a2cab1942cca4',
|
||||
'eaab0ec37b3b8ab796e9f57238de14a264a076f3887d86e29bb5906db5a00e02',
|
||||
'23cb68b8c0e6dc26dc27766ddc0a13a99438fd55617aa4095d8f969720c872df',
|
||||
'091d8ee30d6f2968d46b687dd65292665742de0bb83dcc0004c72ce10007a549',
|
||||
'7f507abc6d19ba00c065a876ec5657868882d18a221bc46c7a6912541f5bc7ba',
|
||||
'a0607c24e14e8c223db0d70b4d30ee88014d603f437e9e02aa7dafa3cdfbad94',
|
||||
'ddbfea75cc467882eb3483ce5e2e756a4f4701b76b445519e89f22d60fa86e06',
|
||||
'0c311f38c35a4fb90d651c289d486856cd1413df9b0677f53ece2cd9e477c60a',
|
||||
'46a73a8dd3e70f59d3942c01df599def783c9da82fd83222cd662b53dce7dbdf',
|
||||
'ad038ff9b14de84a801e4e621ce5df029dd93520d0c2fa38bff176a8b1d1698c',
|
||||
'ab70c5dfbd1ea817fed0cd067293abf319e5d7901c2141d5d99b23f03a38e748',
|
||||
'1fffda67932b73c8ecaf009a3491a026953babfe1f663b0697c3c4ae8b2e7dcb',
|
||||
'b0d2cc19472dd57f2b17efc03c8d58c2283dbb19da572f7755855aa9794317a0',
|
||||
'a0d19a6ee33979c325510e276622df41f71583d07501b87071129a0ad94732a5',
|
||||
'724642a7032d1062b89e52bea34b75df7d8fe772d9fe3c93ddf3c4545ab5a99b',
|
||||
'ade5eaa7e61f672d587ea03dae7d7b55229c01d06bc0a5701436cbd18366a626',
|
||||
'013b31ebd228fcdda51fabb03bb02d60ac20ca215aafa83bdd855e3755a35f0b',
|
||||
'332ed40bb10dde3c954a75d7b8999d4b26a1c063c1dc6e32c1d91bab7bbb7d16',
|
||||
'c7a197b3a05b566bcc9facd20e441d6f6c2860ac9651cd51d6b9d2cdeeea0390',
|
||||
'bd9cf64ea8953c037108e6f654914f3958b68e29c16700dc184d94a21708ff60',
|
||||
'8835b0ac021151df716474ce27ce4d3c15f0b2dab48003cf3f3efd0945106b9a',
|
||||
'3bfefa3301aa55c080190cffda8eae51d9af488b4c1f24c3d9a75242fd8ea01d',
|
||||
'08284d14993cd47d53ebaecf0df0478cc182c89c00e1859c84851686ddf2c1b7',
|
||||
'1ed7ef9f04c2ac8db6a864db131087f27065098e69c3fe78718d9b947f4a39d0',
|
||||
'c161f2dcd57e9c1439b31a9dd43d8f3d7dd8f0eb7cfac6fb25a0f28e306f0661',
|
||||
'c01969ad34c52caf3dc4d80d19735c29731ac6e7a92085ab9250c48dea48a3fc',
|
||||
'1720b3655619d2a52b3521ae0e49e345cb3389ebd6208acaf9f13fdacca8be49',
|
||||
'756288361c83e24c617cf95c905b22d017cdc86f0bf1d658f4756c7379873b7f',
|
||||
'e7d0eda3452693b752abcda1b55e276f82698f5f1605403eff830bea0071a394',
|
||||
'2c82ecaa6b84803e044af63118afe544687cb6e6c7df49ed762dfd7c8693a1bc',
|
||||
'6136cbf4b441056fa1e2722498125d6ded45e17b52143959c7f4d4e395218ac2',
|
||||
'721d3245aafef27f6a624f47954b6c255079526ffa25e9ff77e5dcff473b1597',
|
||||
'9dd2fbd8cef16c353c0ac21191d509eb28dd9e3e0d8cea5d26ca839393851c3a',
|
||||
'b2394ceacdebf21bf9df2ced98e58f1c3a4bbbff660dd900f62202d6785cc46e',
|
||||
'57089f222749ad7871765f062b114f43ba20ec56422a8b1e3f87192c0ea718c6',
|
||||
'e49a9459961cd33cdf4aae1b1078a5dea7c040e0fea340c93a724872fc4af806',
|
||||
'ede67f720effd2ca9c88994152d0201dee6b0a2d2c077aca6dae29f73f8b6309',
|
||||
'e0f434bf22e3088039c21f719ffc67f0f2cb5e98a7a0194c76e96bf4e8e17e61',
|
||||
'277c04e2853484a4eba910ad336d01b477b67cc200c59f3c8d77eef8494f29cd',
|
||||
'156d5747d0c99c7f27097d7b7e002b2e185cb72d8dd7eb424a0321528161219f',
|
||||
'20ddd1ed9b1ca803946d64a83ae4659da67fba7a1a3eddb1e103c0f5e03e3a2c',
|
||||
'f0af604d3dabbf9a0f2a7d3dda6bd38bba72c6d09be494fcef713ff10189b6e6',
|
||||
'9802bb87def4cc10c4a5fd49aa58dfe2f3fddb46b4708814ead81d23ba95139b',
|
||||
'4f8ce1e51d2fe7f24043a904d898ebfc91975418753413aa099b795ecb35cedb',
|
||||
'bddc6514d7ee6ace0a4ac1d0e068112288cbcf560454642705630177cba608bd',
|
||||
'd635994f6291517b0281ffdd496afa862712e5b3c4e52e4cd5fdae8c0e72fb08',
|
||||
'878d9ca600cf87e769cc305c1b35255186615a73a0da613b5f1c98dbf81283ea',
|
||||
'a64ebe5dc185de9fdde7607b6998702eb23456184957307d2fa72e87a47702d6',
|
||||
'ce50eab7b5eb52bdc9ad8e5a480ab780ca9320e44360b1fe37e03f2f7ad7de01',
|
||||
'eeddb7c0db6e30abe66d79e327511e61fcebbc29f159b40a86b046ecf0513823',
|
||||
'787fc93440c1ec96b5ad01c16cf77916a1405f9426356ec921d8dff3ea63b7e0',
|
||||
'7f0d5eab47eefda696c0bf0fbf86ab216fce461e9303aba6ac374120e890e8df',
|
||||
'b68004b42f14ad029f4c2e03b1d5eb76d57160e26476d21131bef20ada7d27f4',
|
||||
'b0c4eb18ae250b51a41382ead92d0dc7455f9379fc9884428e4770608db0faec',
|
||||
'f92b7a870c059f4d46464c824ec96355140bdce681322cc3a992ff103e3fea52',
|
||||
'5364312614813398cc525d4c4e146edeb371265fba19133a2c3d2159298a1742',
|
||||
'f6620e68d37fb2af5000fc28e23b832297ecd8bce99e8be4d04e85309e3d3374',
|
||||
'5316a27969d7fe04ff27b283961bffc3bf5dfb32fb6a89d101c6c3b1937c2871',
|
||||
'81d1664fdf3cb33c24eebac0bd64244b77c4abea90bbe8b5ee0b2aafcf2d6a53',
|
||||
'345782f295b0880352e924a0467b5fbc3e8f3bfbc3c7e48b67091fb5e80a9442',
|
||||
'794111ea6cd65e311f74ee41d476cb632ce1e4b051dc1d9e9d061a19e1d0bb49',
|
||||
'2a85daf6138816b99bf8d08ba2114b7ab07975a78420c1a3b06a777c22dd8bcb',
|
||||
'89b0d5f289ec16401a069a960d0b093e625da3cf41ee29b59b930c5820145455',
|
||||
'd0fdcb543943fc27d20864f52181471b942cc77ca675bcb30df31d358ef7b1eb',
|
||||
'b17ea8d77063c709d4dc6b879413c343e3790e9e62ca85b7900b086f6b75c672',
|
||||
'e71a3e2c274db842d92114f217e2c0eac8b45093fdfd9df4ca7162394862d501',
|
||||
'c0476759ab7aa333234f6b44f5fd858390ec23694c622cb986e769c78edd733e',
|
||||
'9ab8eabb1416434d85391341d56993c55458167d4418b19a0f2ad8b79a83a75b',
|
||||
'7992d0bbb15e23826f443e00505d68d3ed7372995a5c3e498654102fbcd0964e',
|
||||
'c021b30085151435df33b007ccecc69df1269f39ba25092bed59d932ac0fdc28',
|
||||
'91a25ec0ec0d9a567f89c4bfe1a65a0e432d07064b4190e27dfb81901fd3139b',
|
||||
'5950d39a23e1545f301270aa1a12f2e6c453776e4d6355de425cc153f9818867',
|
||||
'd79f14720c610af179a3765d4b7c0968f977962dbf655b521272b6f1e194488e',
|
||||
'e9531bfc8b02995aeaa75ba27031fadbcbf4a0dab8961d9296cd7e84d25d6006',
|
||||
'34e9c26a01d7f16181b454a9d1623c233cb99d31c694656e9413aca3e918692f',
|
||||
'd9d7422f437bd439ddd4d883dae2a08350173414be78155133fff1964c3d7972',
|
||||
'4aee0c7aaf075414ff1793ead7eaca601775c615dbd60b640b0a9f0ce505d435',
|
||||
'6bfdd15459c83b99f096bfb49ee87b063d69c1974c6928acfcfb4099f8c4ef67',
|
||||
'9fd1c408fd75c336193a2a14d94f6af5adf050b80387b4b010fb29f4cc72707c',
|
||||
'13c88480a5d00d6c8c7ad2110d76a82d9b70f4fa6696d4e5dd42a066dcaf9920',
|
||||
'820e725ee25fe8fd3a8d5abe4c46c3ba889de6fa9191aa22ba67d5705421542b',
|
||||
'32d93a0eb02f42fbbcaf2bad0085b282e46046a4df7ad10657c9d6476375b93e',
|
||||
'adc5187905b1669cd8ec9c721e1953786b9d89a9bae30780f1e1eab24a00523c',
|
||||
'e90756ff7f9ad810b239a10ced2cf9b2284354c1f8c7e0accc2461dc796d6e89',
|
||||
'1251f76e56978481875359801db589a0b22f86d8d634dc04506f322ed78f17e8',
|
||||
'3afa899fd980e73ecb7f4d8b8f291dc9af796bc65d27f974c6f193c9191a09fd',
|
||||
'aa305be26e5deddc3c1010cbc213f95f051c785c5b431e6a7cd048f161787528',
|
||||
'8ea1884ff32e9d10f039b407d0d44e7e670abd884aeee0fb757ae94eaa97373d',
|
||||
'd482b2155d4dec6b4736a1f1617b53aaa37310277d3fef0c37ad41768fc235b4',
|
||||
'4d413971387e7a8898a8dc2a27500778539ea214a2dfe9b3d7e8ebdce5cf3db3',
|
||||
'696e5d46e6c57e8796e4735d08916e0b7929b3cf298c296d22e9d3019653371c',
|
||||
'1f5647c1d3b088228885865c8940908bf40d1a8272821973b160008e7a3ce2eb',
|
||||
'b6e76c330f021a5bda65875010b0edf09126c0f510ea849048192003aef4c61c',
|
||||
'3cd952a0beada41abb424ce47f94b42be64e1ffb0fd0782276807946d0d0bc55',
|
||||
'98d92677439b41b7bb513312afb92bcc8ee968b2e3b238cecb9b0f34c9bb63d0',
|
||||
'ecbca2cf08ae57d517ad16158a32bfa7dc0382eaeda128e91886734c24a0b29d',
|
||||
'942cc7c0b52e2b16a4b89fa4fc7e0bf609e29a08c1a8543452b77c7bfd11bb28',
|
||||
'8a065d8b61a0dffb170d5627735a76b0e9506037808cba16c345007c9f79cf8f',
|
||||
'1b9fa19714659c78ff413871849215361029ac802b1cbcd54e408bd87287f81f',
|
||||
'8dab071bcd6c7292a9ef727b4ae0d86713301da8618d9a48adce55f303a869a1',
|
||||
'8253e3e7c7b684b9cb2beb014ce330ff3d99d17abbdbabe4f4d674ded53ffc6b',
|
||||
'f195f321e9e3d6bd7d074504dd2ab0e6241f92e784b1aa271ff648b1cab6d7f6',
|
||||
'27e4cc72090f241266476a7c09495f2db153d5bcbd761903ef79275ec56b2ed8',
|
||||
'899c2405788e25b99a1846355e646d77cf400083415f7dc5afe69d6e17c00023',
|
||||
'a59b78c4905744076bfee894de707d4f120b5c6893ea0400297d0bb834727632',
|
||||
'59dc78b105649707a2bb4419c48f005400d3973de3736610230435b10424b24f',
|
||||
'c0149d1d7e7a6353a6d906efe728f2f329fe14a4149a3ea77609bc42b975ddfa',
|
||||
'a32f241474a6c16932e9243be0cf09bcdc7e0ca0e7a6a1b9b1a0f01e41502377',
|
||||
'b239b2e4f81841361c1339f68e2c359f929af9ad9f34e01aab4631ad6d5500b0',
|
||||
'85fb419c7002a3e0b4b6ea093b4c1ac6936645b65dac5ac15a8528b7b94c1754',
|
||||
'9619720625f190b93a3fad186ab314189633c0d3a01e6f9bc8c4a8f82f383dbf',
|
||||
'7d620d90fe69fa469a6538388970a1aa09bb48a2d59b347b97e8ce71f48c7f46',
|
||||
'294383568596fb37c75bbacd979c5ff6f20a556bf8879cc72924855df9b8240e',
|
||||
'16b18ab314359c2b833c1c6986d48c55a9fc97cde9a3c1f10a3177140f73f738',
|
||||
'8cbbdd14bc33f04cf45813e4a153a273d36adad5ce71f499eeb87fb8ac63b729',
|
||||
'69c9a498db174ecaefcc5a3ac9fdedf0f813a5bec727f1e775babdec7718816e',
|
||||
'b462c3be40448f1d4f80626254e535b08bc9cdcff599a768578d4b2881a8e3f0',
|
||||
'553e9d9c5f360ac0b74a7d44e5a391dad4ced03e0c24183b7e8ecabdf1715a64',
|
||||
'7a7c55a56fa9ae51e655e01975d8a6ff4ae9e4b486fcbe4eac044588f245ebea',
|
||||
'2afdf3c82abc4867f5de111286c2b3be7d6e48657ba923cfbf101a6dfcf9db9a',
|
||||
'41037d2edcdce0c49b7fb4a6aa0999ca66976c7483afe631d4eda283144f6dfc',
|
||||
'c4466f8497ca2eeb4583a0b08e9d9ac74395709fda109d24f2e4462196779c5d',
|
||||
'75f609338aa67d969a2ae2a2362b2da9d77c695dfd1df7224a6901db932c3364',
|
||||
'68606ceb989d5488fc7cf649f3d7c272ef055da1a93faecd55fe06f6967098ca',
|
||||
'44346bdeb7e052f6255048f0d9b42c425bab9c3dd24168212c3ecf1ebf34e6ae',
|
||||
'8e9cf6e1f366471f2ac7d2ee9b5e6266fda71f8f2e4109f2237ed5f8813fc718',
|
||||
'84bbeb8406d250951f8c1b3e86a7c010082921833dfd9555a2f909b1086eb4b8',
|
||||
'ee666f3eef0f7e2a9c222958c97eaf35f51ced393d714485ab09a069340fdf88',
|
||||
'c153d34a65c47b4a62c5cacf24010975d0356b2f32c8f5da530d338816ad5de6',
|
||||
'9fc5450109e1b779f6c7ae79d56c27635c8dd426c5a9d54e2578db989b8c3b4e',
|
||||
'd12bf3732ef4af5c22fa90356af8fc50fcb40f8f2ea5c8594737a3b3d5abdbd7',
|
||||
'11030b9289bba5af65260672ab6fee88b87420acef4a1789a2073b7ec2f2a09e',
|
||||
'69cb192b8444005c8c0ceb12c846860768188cda0aec27a9c8a55cdee2123632',
|
||||
'db444c15597b5f1a03d1f9edd16e4a9f43a667cc275175dfa2b704e3bb1a9b83',
|
||||
'3fb735061abc519dfe979e54c1ee5bfad0a9d858b3315bad34bde999efd724dd'
|
||||
]
|
||||
end
|
||||
|
||||
def test_unkeyed
|
||||
(0..255).each do |i|
|
||||
buf = []
|
||||
|
||||
j = 0
|
||||
while j < i
|
||||
buf << (j & 0xff)
|
||||
j += 1
|
||||
end
|
||||
|
||||
res = Blake2b.new(32, Blake2b::Key.none).digest(bytes_to_string(buf), :to_hex)
|
||||
assert_kind_of String, res
|
||||
assert_equal @golden[i], res
|
||||
end
|
||||
end
|
||||
|
||||
def test_keyed_with_string
|
||||
key = (0..31).map { |i| i }
|
||||
|
||||
(0..255).each do |i|
|
||||
buf = []
|
||||
|
||||
j = 0
|
||||
while j < i
|
||||
buf << (j & 0xff)
|
||||
j += 1
|
||||
end
|
||||
|
||||
res = Blake2b.new(32, Blake2b::Key.from_string(bytes_to_string(key))).digest(bytes_to_string(buf), :to_hex)
|
||||
assert_kind_of String, res
|
||||
assert_equal @golden_keyed[i], res
|
||||
end
|
||||
end
|
||||
|
||||
def test_keyed_with_hex
|
||||
key = (0..31).map { |i| i }
|
||||
key_hex = bytes_to_hex(key)
|
||||
|
||||
(0..255).each do |i|
|
||||
buf = []
|
||||
|
||||
j = 0
|
||||
while j < i
|
||||
buf << (j & 0xff)
|
||||
j += 1
|
||||
end
|
||||
|
||||
res = Blake2b.new(32, Blake2b::Key.from_hex(key_hex)).digest(bytes_to_string(buf), :to_hex)
|
||||
assert_kind_of String, res
|
||||
assert_equal @golden_keyed[i], res
|
||||
end
|
||||
end
|
||||
|
||||
# utility methods
|
||||
#################
|
||||
|
||||
def bytes_to_string(bytes)
|
||||
bytes.pack('C*')
|
||||
end
|
||||
|
||||
def bytes_to_hex(bytes)
|
||||
hex = ''
|
||||
bytes.each { |b| hex += sprintf('%02x', b) }
|
||||
hex.downcase
|
||||
end
|
||||
end
|
9
test/performance/blake2b_gc_test.rb
Executable file
9
test/performance/blake2b_gc_test.rb
Executable file
|
@ -0,0 +1,9 @@
|
|||
require 'test_helper'
|
||||
|
||||
class Blake2bGCTest < MiniTest::Test
|
||||
def test_a_million_iteration
|
||||
1_000_000.times do |i|
|
||||
Blake2b.new(32, Blake2b::Key.none).digest('abc', :to_hex)
|
||||
end
|
||||
end
|
||||
end
|
3
test/test_helper.rb
Executable file
3
test/test_helper.rb
Executable file
|
@ -0,0 +1,3 @@
|
|||
require 'minitest/autorun'
|
||||
require 'minitest/assertions'
|
||||
require 'blake2b'
|
Loading…
Add table
Reference in a new issue