win32 platform
This commit is contained in:
commit
c1666978b2
1122 changed files with 348397 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
*.swp
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
__pycache__
|
||||||
|
pip_cache
|
||||||
|
.DS_Store
|
339
COPYING
Normal file
339
COPYING
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) 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
|
||||||
|
this service 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 make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. 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.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
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
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the 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 a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE 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.
|
||||||
|
|
||||||
|
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
|
||||||
|
convey 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 2 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, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision 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, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This 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.
|
674
COPYING3
Normal file
674
COPYING3
Normal file
|
@ -0,0 +1,674 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
115
Lib/site-packages/Crypto/Cipher/AES.py
Normal file
115
Lib/site-packages/Crypto/Cipher/AES.py
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/AES.py : AES
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
"""AES symmetric cipher
|
||||||
|
|
||||||
|
AES `(Advanced Encryption Standard)`__ is a symmetric block cipher standardized
|
||||||
|
by NIST_ . It has a fixed data block size of 16 bytes.
|
||||||
|
Its keys can be 128, 192, or 256 bits long.
|
||||||
|
|
||||||
|
AES is very fast and secure, and it is the de facto standard for symmetric
|
||||||
|
encryption.
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import AES
|
||||||
|
>>> from Crypto import Random
|
||||||
|
>>>
|
||||||
|
>>> key = b'Sixteen byte key'
|
||||||
|
>>> iv = Random.new().read(AES.block_size)
|
||||||
|
>>> cipher = AES.new(key, AES.MODE_CFB, iv)
|
||||||
|
>>> msg = iv + cipher.encrypt(b'Attack at dawn')
|
||||||
|
|
||||||
|
.. __: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||||||
|
.. _NIST: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Cipher import blockalgo
|
||||||
|
from Crypto.Cipher import _AES
|
||||||
|
|
||||||
|
class AESCipher (blockalgo.BlockAlgo):
|
||||||
|
"""AES cipher object"""
|
||||||
|
|
||||||
|
def __init__(self, key, *args, **kwargs):
|
||||||
|
"""Initialize an AES cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs)
|
||||||
|
|
||||||
|
def new(key, *args, **kwargs):
|
||||||
|
"""Create a new AES cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
It must be 16 (*AES-128*), 24 (*AES-192*), or 32 (*AES-256*) bytes long.
|
||||||
|
:Keywords:
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
Default is `MODE_ECB`.
|
||||||
|
IV : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
|
||||||
|
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
It is mandatory.
|
||||||
|
|
||||||
|
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||||
|
when not present it will be given a default value of all zeroes.
|
||||||
|
counter : callable
|
||||||
|
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||||
|
*counter block*, which is a byte string of `block_size` bytes.
|
||||||
|
For better performance, use `Crypto.Util.Counter`.
|
||||||
|
segment_size : integer
|
||||||
|
(*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
|
||||||
|
are segmented in.
|
||||||
|
It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
:Return: an `AESCipher` object
|
||||||
|
"""
|
||||||
|
return AESCipher(key, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: This mode should not be used.
|
||||||
|
MODE_PGP = 4
|
||||||
|
#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 16
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = ( 16, 24, 32 )
|
||||||
|
|
130
Lib/site-packages/Crypto/Cipher/ARC2.py
Normal file
130
Lib/site-packages/Crypto/Cipher/ARC2.py
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/ARC2.py : ARC2.py
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
"""RC2 symmetric cipher
|
||||||
|
|
||||||
|
RC2_ (Rivest's Cipher version 2) is a symmetric block cipher designed
|
||||||
|
by Ron Rivest in 1987. The cipher started as a proprietary design,
|
||||||
|
that was reverse engineered and anonymously posted on Usenet in 1996.
|
||||||
|
For this reason, the algorithm was first called *Alleged* RC2 (ARC2),
|
||||||
|
since the company that owned RC2 (RSA Data Inc.) did not confirm whether
|
||||||
|
the details leaked into public domain were really correct.
|
||||||
|
|
||||||
|
The company eventually published its full specification in RFC2268_.
|
||||||
|
|
||||||
|
RC2 has a fixed data block size of 8 bytes. Length of its keys can vary from
|
||||||
|
8 to 128 bits. One particular property of RC2 is that the actual
|
||||||
|
cryptographic strength of the key (*effective key length*) can be reduced
|
||||||
|
via a parameter.
|
||||||
|
|
||||||
|
Even though RC2 is not cryptographically broken, it has not been analyzed as
|
||||||
|
thoroughly as AES, which is also faster than RC2.
|
||||||
|
|
||||||
|
New designs should not use RC2.
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import ARC2
|
||||||
|
>>> from Crypto import Random
|
||||||
|
>>>
|
||||||
|
>>> key = b'Sixteen byte key'
|
||||||
|
>>> iv = Random.new().read(ARC2.block_size)
|
||||||
|
>>> cipher = ARC2.new(key, ARC2.MODE_CFB, iv)
|
||||||
|
>>> msg = iv + cipher.encrypt(b'Attack at dawn')
|
||||||
|
|
||||||
|
.. _RC2: http://en.wikipedia.org/wiki/RC2
|
||||||
|
.. _RFC2268: http://tools.ietf.org/html/rfc2268
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Cipher import blockalgo
|
||||||
|
from Crypto.Cipher import _ARC2
|
||||||
|
|
||||||
|
class RC2Cipher (blockalgo.BlockAlgo):
|
||||||
|
"""RC2 cipher object"""
|
||||||
|
|
||||||
|
def __init__(self, key, *args, **kwargs):
|
||||||
|
"""Initialize an ARC2 cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
blockalgo.BlockAlgo.__init__(self, _ARC2, key, *args, **kwargs)
|
||||||
|
|
||||||
|
def new(key, *args, **kwargs):
|
||||||
|
"""Create a new RC2 cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
Its length can vary from 1 to 128 bytes.
|
||||||
|
:Keywords:
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
Default is `MODE_ECB`.
|
||||||
|
IV : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
|
||||||
|
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
It is mandatory.
|
||||||
|
|
||||||
|
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||||
|
when not present it will be given a default value of all zeroes.
|
||||||
|
counter : callable
|
||||||
|
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||||
|
*counter block*, which is a byte string of `block_size` bytes.
|
||||||
|
For better performance, use `Crypto.Util.Counter`.
|
||||||
|
segment_size : integer
|
||||||
|
(*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
|
||||||
|
are segmented in.
|
||||||
|
It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
|
||||||
|
effective_keylen : integer
|
||||||
|
Maximum cryptographic strength of the key, in bits.
|
||||||
|
It can vary from 0 to 1024. The default value is 1024.
|
||||||
|
|
||||||
|
:Return: an `RC2Cipher` object
|
||||||
|
"""
|
||||||
|
return RC2Cipher(key, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: This mode should not be used.
|
||||||
|
MODE_PGP = 4
|
||||||
|
#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = range(1,16+1)
|
||||||
|
|
120
Lib/site-packages/Crypto/Cipher/ARC4.py
Normal file
120
Lib/site-packages/Crypto/Cipher/ARC4.py
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/ARC4.py : ARC4
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
"""ARC4 symmetric cipher
|
||||||
|
|
||||||
|
ARC4_ (Alleged RC4) is an implementation of RC4 (Rivest's Cipher version 4),
|
||||||
|
a symmetric stream cipher designed by Ron Rivest in 1987.
|
||||||
|
|
||||||
|
The cipher started as a proprietary design, that was reverse engineered and
|
||||||
|
anonymously posted on Usenet in 1994. The company that owns RC4 (RSA Data
|
||||||
|
Inc.) never confirmed the correctness of the leaked algorithm.
|
||||||
|
|
||||||
|
Unlike RC2, the company has never published the full specification of RC4,
|
||||||
|
of whom it still holds the trademark.
|
||||||
|
|
||||||
|
ARC4 keys can vary in length from 40 to 2048 bits.
|
||||||
|
|
||||||
|
One problem of ARC4 is that it does not take a nonce or an IV. If it is required
|
||||||
|
to encrypt multiple messages with the same long-term key, a distinct
|
||||||
|
independent nonce must be created for each message, and a short-term key must
|
||||||
|
be derived from the combination of the long-term key and the nonce.
|
||||||
|
Due to the weak key scheduling algorithm of RC2, the combination must be carried
|
||||||
|
out with a complex function (e.g. a cryptographic hash) and not by simply
|
||||||
|
concatenating key and nonce.
|
||||||
|
|
||||||
|
New designs should not use ARC4. A good alternative is AES
|
||||||
|
(`Crypto.Cipher.AES`) in any of the modes that turn it into a stream cipher (OFB, CFB, or CTR).
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import ARC4
|
||||||
|
>>> from Crypto.Hash import SHA
|
||||||
|
>>> from Crypto import Random
|
||||||
|
>>>
|
||||||
|
>>> key = b'Very long and confidential key'
|
||||||
|
>>> nonce = Random.new().read(16)
|
||||||
|
>>> tempkey = SHA.new(key+nonce).digest()
|
||||||
|
>>> cipher = ARC4.new(tempkey)
|
||||||
|
>>> msg = nonce + cipher.encrypt(b'Open the pod bay doors, HAL')
|
||||||
|
|
||||||
|
.. _ARC4: http://en.wikipedia.org/wiki/RC4
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Cipher import _ARC4
|
||||||
|
|
||||||
|
class ARC4Cipher:
|
||||||
|
"""ARC4 cipher object"""
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, key, *args, **kwargs):
|
||||||
|
"""Initialize an ARC4 cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
|
||||||
|
self._cipher = _ARC4.new(key, *args, **kwargs)
|
||||||
|
self.block_size = self._cipher.block_size
|
||||||
|
self.key_size = self._cipher.key_size
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt a piece of data.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt. It can be of any size.
|
||||||
|
:Return: the encrypted data (byte string, as long as the
|
||||||
|
plaintext).
|
||||||
|
"""
|
||||||
|
return self._cipher.encrypt(plaintext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt a piece of data.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt. It can be of any size.
|
||||||
|
:Return: the decrypted data (byte string, as long as the
|
||||||
|
ciphertext).
|
||||||
|
"""
|
||||||
|
return self._cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
def new(key, *args, **kwargs):
|
||||||
|
"""Create a new ARC4 cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
It can have any length, with a minimum of 40 bytes.
|
||||||
|
Its cryptograpic strength is always capped to 2048 bits (256 bytes).
|
||||||
|
|
||||||
|
:Return: an `ARC4Cipher` object
|
||||||
|
"""
|
||||||
|
return ARC4Cipher(key, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 1
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = range(1,256+1)
|
||||||
|
|
121
Lib/site-packages/Crypto/Cipher/Blowfish.py
Normal file
121
Lib/site-packages/Crypto/Cipher/Blowfish.py
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/Blowfish.py : Blowfish
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
"""Blowfish symmetric cipher
|
||||||
|
|
||||||
|
Blowfish_ is a symmetric block cipher designed by Bruce Schneier.
|
||||||
|
|
||||||
|
It has a fixed data block size of 8 bytes and its keys can vary in length
|
||||||
|
from 32 to 448 bits (4 to 56 bytes).
|
||||||
|
|
||||||
|
Blowfish is deemed secure and it is fast. However, its keys should be chosen
|
||||||
|
to be big enough to withstand a brute force attack (e.g. at least 16 bytes).
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import Blowfish
|
||||||
|
>>> from Crypto import Random
|
||||||
|
>>> from struct import pack
|
||||||
|
>>>
|
||||||
|
>>> bs = Blowfish.block_size
|
||||||
|
>>> key = b'An arbitrarily long key'
|
||||||
|
>>> iv = Random.new().read(bs)
|
||||||
|
>>> cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)
|
||||||
|
>>> plaintext = b'docendo discimus '
|
||||||
|
>>> plen = bs - divmod(len(plaintext),bs)[1]
|
||||||
|
>>> padding = [plen]*plen
|
||||||
|
>>> padding = pack('b'*plen, *padding)
|
||||||
|
>>> msg = iv + cipher.encrypt(plaintext + padding)
|
||||||
|
|
||||||
|
.. _Blowfish: http://www.schneier.com/blowfish.html
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Cipher import blockalgo
|
||||||
|
from Crypto.Cipher import _Blowfish
|
||||||
|
|
||||||
|
class BlowfishCipher (blockalgo.BlockAlgo):
|
||||||
|
"""Blowfish cipher object"""
|
||||||
|
|
||||||
|
def __init__(self, key, *args, **kwargs):
|
||||||
|
"""Initialize a Blowfish cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
blockalgo.BlockAlgo.__init__(self, _Blowfish, key, *args, **kwargs)
|
||||||
|
|
||||||
|
def new(key, *args, **kwargs):
|
||||||
|
"""Create a new Blowfish cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
Its length can vary from 4 to 56 bytes.
|
||||||
|
:Keywords:
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
Default is `MODE_ECB`.
|
||||||
|
IV : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
|
||||||
|
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
It is mandatory.
|
||||||
|
|
||||||
|
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||||
|
when not present it will be given a default value of all zeroes.
|
||||||
|
counter : callable
|
||||||
|
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||||
|
*counter block*, which is a byte string of `block_size` bytes.
|
||||||
|
For better performance, use `Crypto.Util.Counter`.
|
||||||
|
segment_size : integer
|
||||||
|
(*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
|
||||||
|
are segmented in.
|
||||||
|
It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
:Return: a `BlowfishCipher` object
|
||||||
|
"""
|
||||||
|
return BlowfishCipher(key, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: This mode should not be used.
|
||||||
|
MODE_PGP = 4
|
||||||
|
#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = range(4,56+1)
|
||||||
|
|
123
Lib/site-packages/Crypto/Cipher/CAST.py
Normal file
123
Lib/site-packages/Crypto/Cipher/CAST.py
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/CAST.py : CAST
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
"""CAST-128 symmetric cipher
|
||||||
|
|
||||||
|
CAST-128_ (or CAST5) is a symmetric block cipher specified in RFC2144_.
|
||||||
|
|
||||||
|
It has a fixed data block size of 8 bytes. Its key can vary in length
|
||||||
|
from 40 to 128 bits.
|
||||||
|
|
||||||
|
CAST is deemed to be cryptographically secure, but its usage is not widespread.
|
||||||
|
Keys of sufficient length should be used to prevent brute force attacks
|
||||||
|
(128 bits are recommended).
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import CAST
|
||||||
|
>>> from Crypto import Random
|
||||||
|
>>>
|
||||||
|
>>> key = b'Sixteen byte key'
|
||||||
|
>>> iv = Random.new().read(CAST.block_size)
|
||||||
|
>>> cipher = CAST.new(key, CAST.MODE_OPENPGP, iv)
|
||||||
|
>>> plaintext = b'sona si latine loqueris '
|
||||||
|
>>> msg = cipher.encrypt(plaintext)
|
||||||
|
>>>
|
||||||
|
...
|
||||||
|
>>> eiv = msg[:CAST.block_size+2]
|
||||||
|
>>> ciphertext = msg[CAST.block_size+2:]
|
||||||
|
>>> cipher = CAST.new(key, CAST.MODE_OPENPGP, eiv)
|
||||||
|
>>> print cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
.. _CAST-128: http://en.wikipedia.org/wiki/CAST-128
|
||||||
|
.. _RFC2144: http://tools.ietf.org/html/rfc2144
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Cipher import blockalgo
|
||||||
|
from Crypto.Cipher import _CAST
|
||||||
|
|
||||||
|
class CAST128Cipher(blockalgo.BlockAlgo):
|
||||||
|
"""CAST-128 cipher object"""
|
||||||
|
|
||||||
|
def __init__(self, key, *args, **kwargs):
|
||||||
|
"""Initialize a CAST-128 cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
blockalgo.BlockAlgo.__init__(self, _CAST, key, *args, **kwargs)
|
||||||
|
|
||||||
|
def new(key, *args, **kwargs):
|
||||||
|
"""Create a new CAST-128 cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
Its length may vary from 5 to 16 bytes.
|
||||||
|
:Keywords:
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
Default is `MODE_ECB`.
|
||||||
|
IV : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
|
||||||
|
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
It is mandatory.
|
||||||
|
|
||||||
|
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||||
|
when not present it will be given a default value of all zeroes.
|
||||||
|
counter : callable
|
||||||
|
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||||
|
*counter block*, which is a byte string of `block_size` bytes.
|
||||||
|
For better performance, use `Crypto.Util.Counter`.
|
||||||
|
segment_size : integer
|
||||||
|
(*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
|
||||||
|
are segmented in.
|
||||||
|
It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
:Return: an `CAST128Cipher` object
|
||||||
|
"""
|
||||||
|
return CAST128Cipher(key, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: This mode should not be used.
|
||||||
|
MODE_PGP = 4
|
||||||
|
#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = range(5,16+1)
|
118
Lib/site-packages/Crypto/Cipher/DES.py
Normal file
118
Lib/site-packages/Crypto/Cipher/DES.py
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/DES.py : DES
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
"""DES symmetric cipher
|
||||||
|
|
||||||
|
DES `(Data Encryption Standard)`__ is a symmetric block cipher standardized
|
||||||
|
by NIST_ . It has a fixed data block size of 8 bytes.
|
||||||
|
Its keys are 64 bits long, even though 8 bits were used for integrity (now they
|
||||||
|
are ignored) and do not contribute to securty.
|
||||||
|
|
||||||
|
DES is cryptographically secure, but its key length is too short by nowadays
|
||||||
|
standards and it could be brute forced with some effort.
|
||||||
|
|
||||||
|
DES should not be used for new designs. Use `AES`.
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import DES3
|
||||||
|
>>> from Crypto import Random
|
||||||
|
>>>
|
||||||
|
>>> key = b'Sixteen byte key'
|
||||||
|
>>> iv = Random.new().read(DES3.block_size)
|
||||||
|
>>> cipher = DES3.new(key, DES3.MODE_OFB, iv)
|
||||||
|
>>> plaintext = b'sona si latine loqueris '
|
||||||
|
>>> msg = iv + cipher.encrypt(plaintext)
|
||||||
|
|
||||||
|
.. __: http://en.wikipedia.org/wiki/Data_Encryption_Standard
|
||||||
|
.. _NIST: http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Cipher import blockalgo
|
||||||
|
from Crypto.Cipher import _DES
|
||||||
|
|
||||||
|
class DESCipher(blockalgo.BlockAlgo):
|
||||||
|
"""DES cipher object"""
|
||||||
|
|
||||||
|
def __init__(self, key, *args, **kwargs):
|
||||||
|
"""Initialize a DES cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
blockalgo.BlockAlgo.__init__(self, _DES, key, *args, **kwargs)
|
||||||
|
|
||||||
|
def new(key, *args, **kwargs):
|
||||||
|
"""Create a new DES cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
It must be 8 byte long. The parity bits will be ignored.
|
||||||
|
:Keywords:
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
Default is `MODE_ECB`.
|
||||||
|
IV : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
|
||||||
|
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
It is mandatory.
|
||||||
|
|
||||||
|
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||||
|
when not present it will be given a default value of all zeroes.
|
||||||
|
counter : callable
|
||||||
|
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||||
|
*counter block*, which is a byte string of `block_size` bytes.
|
||||||
|
For better performance, use `Crypto.Util.Counter`.
|
||||||
|
segment_size : integer
|
||||||
|
(*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
|
||||||
|
are segmented in.
|
||||||
|
It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
:Return: an `DESCipher` object
|
||||||
|
"""
|
||||||
|
return DESCipher(key, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: This mode should not be used.
|
||||||
|
MODE_PGP = 4
|
||||||
|
#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = 8
|
133
Lib/site-packages/Crypto/Cipher/DES3.py
Normal file
133
Lib/site-packages/Crypto/Cipher/DES3.py
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/DES3.py : DES3
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
"""Triple DES symmetric cipher
|
||||||
|
|
||||||
|
`Triple DES`__ (or TDES or TDEA or 3DES) is a symmetric block cipher standardized by NIST_.
|
||||||
|
It has a fixed data block size of 8 bytes. Its keys are 128 (*Option 1*) or 192
|
||||||
|
bits (*Option 2*) long.
|
||||||
|
However, 1 out of 8 bits is used for redundancy and do not contribute to
|
||||||
|
security. The effective key length is respectively 112 or 168 bits.
|
||||||
|
|
||||||
|
TDES consists of the concatenation of 3 simple `DES` ciphers.
|
||||||
|
|
||||||
|
The plaintext is first DES encrypted with *K1*, then decrypted with *K2*,
|
||||||
|
and finally encrypted again with *K3*. The ciphertext is decrypted in the reverse manner.
|
||||||
|
|
||||||
|
The 192 bit key is a bundle of three 64 bit independent subkeys: *K1*, *K2*, and *K3*.
|
||||||
|
|
||||||
|
The 128 bit key is split into *K1* and *K2*, whereas *K1=K3*.
|
||||||
|
|
||||||
|
It is important that all subkeys are different, otherwise TDES would degrade to
|
||||||
|
single `DES`.
|
||||||
|
|
||||||
|
TDES is cryptographically secure, even though it is neither as secure nor as fast
|
||||||
|
as `AES`.
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import DES
|
||||||
|
>>> from Crypto import Random
|
||||||
|
>>> from Crypto.Util import Counter
|
||||||
|
>>>
|
||||||
|
>>> key = b'-8B key-'
|
||||||
|
>>> nonce = Random.new().read(DES.block_size/2)
|
||||||
|
>>> ctr = Counter.new(DES.block_size*8/2, prefix=nonce)
|
||||||
|
>>> cipher = DES.new(key, DES.MODE_CTR, counter=ctr)
|
||||||
|
>>> plaintext = b'We are no longer the knights who say ni!'
|
||||||
|
>>> msg = nonce + cipher.encrypt(plaintext)
|
||||||
|
|
||||||
|
.. __: http://en.wikipedia.org/wiki/Triple_DES
|
||||||
|
.. _NIST: http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Cipher import blockalgo
|
||||||
|
from Crypto.Cipher import _DES3
|
||||||
|
|
||||||
|
class DES3Cipher(blockalgo.BlockAlgo):
|
||||||
|
"""TDES cipher object"""
|
||||||
|
|
||||||
|
def __init__(self, key, *args, **kwargs):
|
||||||
|
"""Initialize a TDES cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
blockalgo.BlockAlgo.__init__(self, _DES3, key, *args, **kwargs)
|
||||||
|
|
||||||
|
def new(key, *args, **kwargs):
|
||||||
|
"""Create a new TDES cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
It must be 16 or 24 bytes long. The parity bits will be ignored.
|
||||||
|
:Keywords:
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
Default is `MODE_ECB`.
|
||||||
|
IV : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
|
||||||
|
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
It is mandatory.
|
||||||
|
|
||||||
|
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||||
|
when not present it will be given a default value of all zeroes.
|
||||||
|
counter : callable
|
||||||
|
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||||
|
*counter block*, which is a byte string of `block_size` bytes.
|
||||||
|
For better performance, use `Crypto.Util.Counter`.
|
||||||
|
segment_size : integer
|
||||||
|
(*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
|
||||||
|
are segmented in.
|
||||||
|
It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
:Attention: it is important that all 8 byte subkeys are different,
|
||||||
|
otherwise TDES would degrade to single `DES`.
|
||||||
|
:Return: an `DES3Cipher` object
|
||||||
|
"""
|
||||||
|
return DES3Cipher(key, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: This mode should not be used.
|
||||||
|
MODE_PGP = 4
|
||||||
|
#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = ( 16, 24 )
|
255
Lib/site-packages/Crypto/Cipher/PKCS1_OAEP.py
Normal file
255
Lib/site-packages/Crypto/Cipher/PKCS1_OAEP.py
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/PKCS1_OAEP.py : PKCS#1 OAEP
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""RSA encryption protocol according to PKCS#1 OAEP
|
||||||
|
|
||||||
|
See RFC3447__ or the `original RSA Labs specification`__ .
|
||||||
|
|
||||||
|
This scheme is more properly called ``RSAES-OAEP``.
|
||||||
|
|
||||||
|
As an example, a sender may encrypt a message in this way:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import PKCS1_OAEP
|
||||||
|
>>> from Crypto.PublicKey import RSA
|
||||||
|
>>>
|
||||||
|
>>> message = 'To be encrypted'
|
||||||
|
>>> key = RSA.importKey(open('pubkey.der').read())
|
||||||
|
>>> cipher = PKCS1_OAEP.new(key)
|
||||||
|
>>> ciphertext = cipher.encrypt(message)
|
||||||
|
|
||||||
|
At the receiver side, decryption can be done using the private part of
|
||||||
|
the RSA key:
|
||||||
|
|
||||||
|
>>> key = RSA.importKey(open('privkey.der').read())
|
||||||
|
>>> cipher = PKCS1_OAP.new(key)
|
||||||
|
>>> message = cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
|
||||||
|
.. __: http://www.ietf.org/rfc/rfc3447.txt
|
||||||
|
.. __: http://www.rsa.com/rsalabs/node.asp?id=2125.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
__all__ = [ 'new', 'PKCS1OAEP_Cipher' ]
|
||||||
|
|
||||||
|
import Crypto.Signature.PKCS1_PSS
|
||||||
|
import Crypto.Hash.SHA
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
import Crypto.Util.number
|
||||||
|
from Crypto.Util.number import ceil_div
|
||||||
|
from Crypto.Util.strxor import strxor
|
||||||
|
|
||||||
|
class PKCS1OAEP_Cipher:
|
||||||
|
"""This cipher can perform PKCS#1 v1.5 OAEP encryption or decryption."""
|
||||||
|
|
||||||
|
def __init__(self, key, hashAlgo, mgfunc, label):
|
||||||
|
"""Initialize this PKCS#1 OAEP cipher object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : an RSA key object
|
||||||
|
If a private half is given, both encryption and decryption are possible.
|
||||||
|
If a public half is given, only encryption is possible.
|
||||||
|
hashAlgo : hash object
|
||||||
|
The hash function to use. This can be a module under `Crypto.Hash`
|
||||||
|
or an existing hash object created from any of such modules. If not specified,
|
||||||
|
`Crypto.Hash.SHA` (that is, SHA-1) is used.
|
||||||
|
mgfunc : callable
|
||||||
|
A mask generation function that accepts two parameters: a string to
|
||||||
|
use as seed, and the lenth of the mask to generate, in bytes.
|
||||||
|
If not specified, the standard MGF1 is used (a safe choice).
|
||||||
|
label : string
|
||||||
|
A label to apply to this particular encryption. If not specified,
|
||||||
|
an empty string is used. Specifying a label does not improve
|
||||||
|
security.
|
||||||
|
|
||||||
|
:attention: Modify the mask generation function only if you know what you are doing.
|
||||||
|
Sender and receiver must use the same one.
|
||||||
|
"""
|
||||||
|
self._key = key
|
||||||
|
|
||||||
|
if hashAlgo:
|
||||||
|
self._hashObj = hashAlgo
|
||||||
|
else:
|
||||||
|
self._hashObj = Crypto.Hash.SHA
|
||||||
|
|
||||||
|
if mgfunc:
|
||||||
|
self._mgf = mgfunc
|
||||||
|
else:
|
||||||
|
self._mgf = lambda x,y: Crypto.Signature.PKCS1_PSS.MGF1(x,y,self._hashObj)
|
||||||
|
|
||||||
|
self._label = label
|
||||||
|
|
||||||
|
def can_encrypt(self):
|
||||||
|
"""Return True/1 if this cipher object can be used for encryption."""
|
||||||
|
return self._key.can_encrypt()
|
||||||
|
|
||||||
|
def can_decrypt(self):
|
||||||
|
"""Return True/1 if this cipher object can be used for decryption."""
|
||||||
|
return self._key.can_decrypt()
|
||||||
|
|
||||||
|
def encrypt(self, message):
|
||||||
|
"""Produce the PKCS#1 OAEP encryption of a message.
|
||||||
|
|
||||||
|
This function is named ``RSAES-OAEP-ENCRYPT``, and is specified in
|
||||||
|
section 7.1.1 of RFC3447.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
message : string
|
||||||
|
The message to encrypt, also known as plaintext. It can be of
|
||||||
|
variable length, but not longer than the RSA modulus (in bytes)
|
||||||
|
minus 2, minus twice the hash output size.
|
||||||
|
|
||||||
|
:Return: A string, the ciphertext in which the message is encrypted.
|
||||||
|
It is as long as the RSA modulus (in bytes).
|
||||||
|
:Raise ValueError:
|
||||||
|
If the RSA key length is not sufficiently long to deal with the given
|
||||||
|
message.
|
||||||
|
"""
|
||||||
|
# TODO: Verify the key is RSA
|
||||||
|
|
||||||
|
randFunc = self._key._randfunc
|
||||||
|
|
||||||
|
# See 7.1.1 in RFC3447
|
||||||
|
modBits = Crypto.Util.number.size(self._key.n)
|
||||||
|
k = ceil_div(modBits,8) # Convert from bits to bytes
|
||||||
|
hLen = self._hashObj.digest_size
|
||||||
|
mLen = len(message)
|
||||||
|
|
||||||
|
# Step 1b
|
||||||
|
ps_len = k-mLen-2*hLen-2
|
||||||
|
if ps_len<0:
|
||||||
|
raise ValueError("Plaintext is too long.")
|
||||||
|
# Step 2a
|
||||||
|
lHash = self._hashObj.new(self._label).digest()
|
||||||
|
# Step 2b
|
||||||
|
ps = bchr(0x00)*ps_len
|
||||||
|
# Step 2c
|
||||||
|
db = lHash + ps + bchr(0x01) + message
|
||||||
|
# Step 2d
|
||||||
|
ros = randFunc(hLen)
|
||||||
|
# Step 2e
|
||||||
|
dbMask = self._mgf(ros, k-hLen-1)
|
||||||
|
# Step 2f
|
||||||
|
maskedDB = strxor(db, dbMask)
|
||||||
|
# Step 2g
|
||||||
|
seedMask = self._mgf(maskedDB, hLen)
|
||||||
|
# Step 2h
|
||||||
|
maskedSeed = strxor(ros, seedMask)
|
||||||
|
# Step 2i
|
||||||
|
em = bchr(0x00) + maskedSeed + maskedDB
|
||||||
|
# Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP)
|
||||||
|
m = self._key.encrypt(em, 0)[0]
|
||||||
|
# Complete step 3c (I2OSP)
|
||||||
|
c = bchr(0x00)*(k-len(m)) + m
|
||||||
|
return c
|
||||||
|
|
||||||
|
def decrypt(self, ct):
|
||||||
|
"""Decrypt a PKCS#1 OAEP ciphertext.
|
||||||
|
|
||||||
|
This function is named ``RSAES-OAEP-DECRYPT``, and is specified in
|
||||||
|
section 7.1.2 of RFC3447.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ct : string
|
||||||
|
The ciphertext that contains the message to recover.
|
||||||
|
|
||||||
|
:Return: A string, the original message.
|
||||||
|
:Raise ValueError:
|
||||||
|
If the ciphertext length is incorrect, or if the decryption does not
|
||||||
|
succeed.
|
||||||
|
:Raise TypeError:
|
||||||
|
If the RSA key has no private half.
|
||||||
|
"""
|
||||||
|
# TODO: Verify the key is RSA
|
||||||
|
|
||||||
|
# See 7.1.2 in RFC3447
|
||||||
|
modBits = Crypto.Util.number.size(self._key.n)
|
||||||
|
k = ceil_div(modBits,8) # Convert from bits to bytes
|
||||||
|
hLen = self._hashObj.digest_size
|
||||||
|
|
||||||
|
# Step 1b and 1c
|
||||||
|
if len(ct) != k or k<hLen+2:
|
||||||
|
raise ValueError("Ciphertext with incorrect length.")
|
||||||
|
# Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP)
|
||||||
|
m = self._key.decrypt(ct)
|
||||||
|
# Complete step 2c (I2OSP)
|
||||||
|
em = bchr(0x00)*(k-len(m)) + m
|
||||||
|
# Step 3a
|
||||||
|
lHash = self._hashObj.new(self._label).digest()
|
||||||
|
# Step 3b
|
||||||
|
y = em[0]
|
||||||
|
# y must be 0, but we MUST NOT check it here in order not to
|
||||||
|
# allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
|
||||||
|
maskedSeed = em[1:hLen+1]
|
||||||
|
maskedDB = em[hLen+1:]
|
||||||
|
# Step 3c
|
||||||
|
seedMask = self._mgf(maskedDB, hLen)
|
||||||
|
# Step 3d
|
||||||
|
seed = strxor(maskedSeed, seedMask)
|
||||||
|
# Step 3e
|
||||||
|
dbMask = self._mgf(seed, k-hLen-1)
|
||||||
|
# Step 3f
|
||||||
|
db = strxor(maskedDB, dbMask)
|
||||||
|
# Step 3g
|
||||||
|
valid = 1
|
||||||
|
one = db[hLen:].find(bchr(0x01))
|
||||||
|
lHash1 = db[:hLen]
|
||||||
|
if lHash1!=lHash:
|
||||||
|
valid = 0
|
||||||
|
if one<0:
|
||||||
|
valid = 0
|
||||||
|
if bord(y)!=0:
|
||||||
|
valid = 0
|
||||||
|
if not valid:
|
||||||
|
raise ValueError("Incorrect decryption.")
|
||||||
|
# Step 4
|
||||||
|
return db[hLen+one+1:]
|
||||||
|
|
||||||
|
def new(key, hashAlgo=None, mgfunc=None, label=b('')):
|
||||||
|
"""Return a cipher object `PKCS1OAEP_Cipher` that can be used to perform PKCS#1 OAEP encryption or decryption.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : RSA key object
|
||||||
|
The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object.
|
||||||
|
Decryption is only possible if *key* is a private RSA key.
|
||||||
|
hashAlgo : hash object
|
||||||
|
The hash function to use. This can be a module under `Crypto.Hash`
|
||||||
|
or an existing hash object created from any of such modules. If not specified,
|
||||||
|
`Crypto.Hash.SHA` (that is, SHA-1) is used.
|
||||||
|
mgfunc : callable
|
||||||
|
A mask generation function that accepts two parameters: a string to
|
||||||
|
use as seed, and the lenth of the mask to generate, in bytes.
|
||||||
|
If not specified, the standard MGF1 is used (a safe choice).
|
||||||
|
label : string
|
||||||
|
A label to apply to this particular encryption. If not specified,
|
||||||
|
an empty string is used. Specifying a label does not improve
|
||||||
|
security.
|
||||||
|
|
||||||
|
:attention: Modify the mask generation function only if you know what you are doing.
|
||||||
|
Sender and receiver must use the same one.
|
||||||
|
"""
|
||||||
|
return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label)
|
||||||
|
|
226
Lib/site-packages/Crypto/Cipher/PKCS1_v1_5.py
Normal file
226
Lib/site-packages/Crypto/Cipher/PKCS1_v1_5.py
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/PKCS1-v1_5.py : PKCS#1 v1.5
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""RSA encryption protocol according to PKCS#1 v1.5
|
||||||
|
|
||||||
|
See RFC3447__ or the `original RSA Labs specification`__ .
|
||||||
|
|
||||||
|
This scheme is more properly called ``RSAES-PKCS1-v1_5``.
|
||||||
|
|
||||||
|
**If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.**
|
||||||
|
|
||||||
|
As an example, a sender may encrypt a message in this way:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import PKCS1_v1_5
|
||||||
|
>>> from Crypto.PublicKey import RSA
|
||||||
|
>>> from Crypto.Hash import SHA
|
||||||
|
>>>
|
||||||
|
>>> message = 'To be encrypted'
|
||||||
|
>>> h = SHA.new(message)
|
||||||
|
>>>
|
||||||
|
>>> key = RSA.importKey(open('pubkey.der').read())
|
||||||
|
>>> cipher = PKCS1_v1_5.new(key)
|
||||||
|
>>> ciphertext = cipher.encrypt(message+h.digest())
|
||||||
|
|
||||||
|
At the receiver side, decryption can be done using the private part of
|
||||||
|
the RSA key:
|
||||||
|
|
||||||
|
>>> From Crypto.Hash import SHA
|
||||||
|
>>> from Crypto import Random
|
||||||
|
>>>
|
||||||
|
>>> key = RSA.importKey(open('privkey.der').read())
|
||||||
|
>>>
|
||||||
|
>>> dsize = SHA.digest_size
|
||||||
|
>>> sentinel = Random.new().read(15+dsize) # Let's assume that average data length is 15
|
||||||
|
>>>
|
||||||
|
>>> cipher = PKCS1_v1_5.new(key)
|
||||||
|
>>> message = cipher.decrypt(ciphertext, sentinel)
|
||||||
|
>>>
|
||||||
|
>>> digest = SHA.new(message[:-dsize]).digest()
|
||||||
|
>>> if digest==message[-dsize:]: # Note how we DO NOT look for the sentinel
|
||||||
|
>>> print "Encryption was correct."
|
||||||
|
>>> else:
|
||||||
|
>>> print "Encryption was not correct."
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
|
||||||
|
.. __: http://www.ietf.org/rfc/rfc3447.txt
|
||||||
|
.. __: http://www.rsa.com/rsalabs/node.asp?id=2125.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
__all__ = [ 'new', 'PKCS115_Cipher' ]
|
||||||
|
|
||||||
|
from Crypto.Util.number import ceil_div
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
import Crypto.Util.number
|
||||||
|
|
||||||
|
class PKCS115_Cipher:
|
||||||
|
"""This cipher can perform PKCS#1 v1.5 RSA encryption or decryption."""
|
||||||
|
|
||||||
|
def __init__(self, key):
|
||||||
|
"""Initialize this PKCS#1 v1.5 cipher object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : an RSA key object
|
||||||
|
If a private half is given, both encryption and decryption are possible.
|
||||||
|
If a public half is given, only encryption is possible.
|
||||||
|
"""
|
||||||
|
self._key = key
|
||||||
|
|
||||||
|
def can_encrypt(self):
|
||||||
|
"""Return True if this cipher object can be used for encryption."""
|
||||||
|
return self._key.can_encrypt()
|
||||||
|
|
||||||
|
def can_decrypt(self):
|
||||||
|
"""Return True if this cipher object can be used for decryption."""
|
||||||
|
return self._key.can_decrypt()
|
||||||
|
|
||||||
|
def encrypt(self, message):
|
||||||
|
"""Produce the PKCS#1 v1.5 encryption of a message.
|
||||||
|
|
||||||
|
This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and is specified in
|
||||||
|
section 7.2.1 of RFC3447.
|
||||||
|
For a complete example see `Crypto.Cipher.PKCS1_v1_5`.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
message : byte string
|
||||||
|
The message to encrypt, also known as plaintext. It can be of
|
||||||
|
variable length, but not longer than the RSA modulus (in bytes) minus 11.
|
||||||
|
|
||||||
|
:Return: A byte string, the ciphertext in which the message is encrypted.
|
||||||
|
It is as long as the RSA modulus (in bytes).
|
||||||
|
:Raise ValueError:
|
||||||
|
If the RSA key length is not sufficiently long to deal with the given
|
||||||
|
message.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# TODO: Verify the key is RSA
|
||||||
|
|
||||||
|
randFunc = self._key._randfunc
|
||||||
|
|
||||||
|
# See 7.2.1 in RFC3447
|
||||||
|
modBits = Crypto.Util.number.size(self._key.n)
|
||||||
|
k = ceil_div(modBits,8) # Convert from bits to bytes
|
||||||
|
mLen = len(message)
|
||||||
|
|
||||||
|
# Step 1
|
||||||
|
if mLen > k-11:
|
||||||
|
raise ValueError("Plaintext is too long.")
|
||||||
|
# Step 2a
|
||||||
|
class nonZeroRandByte:
|
||||||
|
def __init__(self, rf): self.rf=rf
|
||||||
|
def __call__(self, c):
|
||||||
|
while bord(c)==0x00: c=self.rf(1)[0]
|
||||||
|
return c
|
||||||
|
ps = tobytes(list(map(nonZeroRandByte(randFunc), randFunc(k-mLen-3))))
|
||||||
|
# Step 2b
|
||||||
|
em = b('\x00\x02') + ps + bchr(0x00) + message
|
||||||
|
# Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP)
|
||||||
|
m = self._key.encrypt(em, 0)[0]
|
||||||
|
# Complete step 3c (I2OSP)
|
||||||
|
c = bchr(0x00)*(k-len(m)) + m
|
||||||
|
return c
|
||||||
|
|
||||||
|
def decrypt(self, ct, sentinel):
|
||||||
|
"""Decrypt a PKCS#1 v1.5 ciphertext.
|
||||||
|
|
||||||
|
This function is named ``RSAES-PKCS1-V1_5-DECRYPT``, and is specified in
|
||||||
|
section 7.2.2 of RFC3447.
|
||||||
|
For a complete example see `Crypto.Cipher.PKCS1_v1_5`.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ct : byte string
|
||||||
|
The ciphertext that contains the message to recover.
|
||||||
|
sentinel : any type
|
||||||
|
The object to return to indicate that an error was detected during decryption.
|
||||||
|
|
||||||
|
:Return: A byte string. It is either the original message or the ``sentinel`` (in case of an error).
|
||||||
|
:Raise ValueError:
|
||||||
|
If the ciphertext length is incorrect
|
||||||
|
:Raise TypeError:
|
||||||
|
If the RSA key has no private half.
|
||||||
|
|
||||||
|
:attention:
|
||||||
|
You should **never** let the party who submitted the ciphertext know that
|
||||||
|
this function returned the ``sentinel`` value.
|
||||||
|
Armed with such knowledge (for a fair amount of carefully crafted but invalid ciphertexts),
|
||||||
|
an attacker is able to recontruct the plaintext of any other encryption that were carried out
|
||||||
|
with the same RSA public key (see `Bleichenbacher's`__ attack).
|
||||||
|
|
||||||
|
In general, it should not be possible for the other party to distinguish
|
||||||
|
whether processing at the server side failed because the value returned
|
||||||
|
was a ``sentinel`` as opposed to a random, invalid message.
|
||||||
|
|
||||||
|
In fact, the second option is not that unlikely: encryption done according to PKCS#1 v1.5
|
||||||
|
embeds no good integrity check. There is roughly one chance
|
||||||
|
in 2^16 for a random ciphertext to be returned as a valid message
|
||||||
|
(although random looking).
|
||||||
|
|
||||||
|
It is therefore advisabled to:
|
||||||
|
|
||||||
|
1. Select as ``sentinel`` a value that resembles a plausable random, invalid message.
|
||||||
|
2. Not report back an error as soon as you detect a ``sentinel`` value.
|
||||||
|
Put differently, you should not explicitly check if the returned value is the ``sentinel`` or not.
|
||||||
|
3. Cover all possible errors with a single, generic error indicator.
|
||||||
|
4. Embed into the definition of ``message`` (at the protocol level) a digest (e.g. ``SHA-1``).
|
||||||
|
It is recommended for it to be the rightmost part ``message``.
|
||||||
|
5. Where possible, monitor the number of errors due to ciphertexts originating from the same party,
|
||||||
|
and slow down the rate of the requests from such party (or even blacklist it altogether).
|
||||||
|
|
||||||
|
**If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.**
|
||||||
|
|
||||||
|
.. __: http://www.bell-labs.com/user/bleichen/papers/pkcs.ps
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# TODO: Verify the key is RSA
|
||||||
|
|
||||||
|
# See 7.2.1 in RFC3447
|
||||||
|
modBits = Crypto.Util.number.size(self._key.n)
|
||||||
|
k = ceil_div(modBits,8) # Convert from bits to bytes
|
||||||
|
|
||||||
|
# Step 1
|
||||||
|
if len(ct) != k:
|
||||||
|
raise ValueError("Ciphertext with incorrect length.")
|
||||||
|
# Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP)
|
||||||
|
m = self._key.decrypt(ct)
|
||||||
|
# Complete step 2c (I2OSP)
|
||||||
|
em = bchr(0x00)*(k-len(m)) + m
|
||||||
|
# Step 3
|
||||||
|
sep = em.find(bchr(0x00),2)
|
||||||
|
if not em.startswith(b('\x00\x02')) or sep<10:
|
||||||
|
return sentinel
|
||||||
|
# Step 4
|
||||||
|
return em[sep+1:]
|
||||||
|
|
||||||
|
def new(key):
|
||||||
|
"""Return a cipher object `PKCS115_Cipher` that can be used to perform PKCS#1 v1.5 encryption or decryption.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : RSA key object
|
||||||
|
The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object.
|
||||||
|
Decryption is only possible if *key* is a private RSA key.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return PKCS115_Cipher(key)
|
||||||
|
|
86
Lib/site-packages/Crypto/Cipher/XOR.py
Normal file
86
Lib/site-packages/Crypto/Cipher/XOR.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/XOR.py : XOR
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
"""XOR toy cipher
|
||||||
|
|
||||||
|
XOR is one the simplest stream ciphers. Encryption and decryption are
|
||||||
|
performed by XOR-ing data with a keystream made by contatenating
|
||||||
|
the key.
|
||||||
|
|
||||||
|
Do not use it for real applications!
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Cipher import _XOR
|
||||||
|
|
||||||
|
class XORCipher:
|
||||||
|
"""XOR cipher object"""
|
||||||
|
|
||||||
|
def __init__(self, key, *args, **kwargs):
|
||||||
|
"""Initialize a XOR cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
self._cipher = _XOR.new(key, *args, **kwargs)
|
||||||
|
self.block_size = self._cipher.block_size
|
||||||
|
self.key_size = self._cipher.key_size
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt a piece of data.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt. It can be of any size.
|
||||||
|
:Return: the encrypted data (byte string, as long as the
|
||||||
|
plaintext).
|
||||||
|
"""
|
||||||
|
return self._cipher.encrypt(plaintext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt a piece of data.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt. It can be of any size.
|
||||||
|
:Return: the decrypted data (byte string, as long as the
|
||||||
|
ciphertext).
|
||||||
|
"""
|
||||||
|
return self._cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
def new(key, *args, **kwargs):
|
||||||
|
"""Create a new XOR cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
Its length may vary from 1 to 32 bytes.
|
||||||
|
|
||||||
|
:Return: an `XORCipher` object
|
||||||
|
"""
|
||||||
|
return XORCipher(key, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 1
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = range(1,32+1)
|
||||||
|
|
83
Lib/site-packages/Crypto/Cipher/__init__.py
Normal file
83
Lib/site-packages/Crypto/Cipher/__init__.py
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Symmetric- and asymmetric-key encryption algorithms.
|
||||||
|
|
||||||
|
Encryption algorithms transform plaintext in some way that
|
||||||
|
is dependent on a key or key pair, producing ciphertext.
|
||||||
|
|
||||||
|
Symmetric algorithms
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Encryption can easily be reversed, if (and, hopefully, only if)
|
||||||
|
one knows the same key.
|
||||||
|
In other words, sender and receiver share the same key.
|
||||||
|
|
||||||
|
The symmetric encryption modules here all support the interface described in PEP
|
||||||
|
272, "API for Block Encryption Algorithms".
|
||||||
|
|
||||||
|
If you don't know which algorithm to choose, use AES because it's
|
||||||
|
standard and has undergone a fair bit of examination.
|
||||||
|
|
||||||
|
======================== ======= ========================
|
||||||
|
Module name Type Description
|
||||||
|
======================== ======= ========================
|
||||||
|
`Crypto.Cipher.AES` Block Advanced Encryption Standard
|
||||||
|
`Crypto.Cipher.ARC2` Block Alleged RC2
|
||||||
|
`Crypto.Cipher.ARC4` Stream Alleged RC4
|
||||||
|
`Crypto.Cipher.Blowfish` Block Blowfish
|
||||||
|
`Crypto.Cipher.CAST` Block CAST
|
||||||
|
`Crypto.Cipher.DES` Block The Data Encryption Standard.
|
||||||
|
Very commonly used in the past,
|
||||||
|
but today its 56-bit keys are too small.
|
||||||
|
`Crypto.Cipher.DES3` Block Triple DES.
|
||||||
|
`Crypto.Cipher.XOR` Stream The simple XOR cipher.
|
||||||
|
======================== ======= ========================
|
||||||
|
|
||||||
|
|
||||||
|
Asymmetric algorithms
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
For asymmetric algorithms, the key to be used for decryption is totally
|
||||||
|
different and cannot be derived in a feasible way from the key used
|
||||||
|
for encryption. Put differently, sender and receiver each own one half
|
||||||
|
of a key pair. The encryption key is often called ``public`` whereas
|
||||||
|
the decryption key is called ``private``.
|
||||||
|
|
||||||
|
========================== =======================
|
||||||
|
Module name Description
|
||||||
|
========================== =======================
|
||||||
|
`Crypto.Cipher.PKCS1_v1_5` PKCS#1 v1.5 encryption, based on RSA key pairs
|
||||||
|
`Crypto.Cipher.PKCS1_OAEP` PKCS#1 OAEP encryption, based on RSA key pairs
|
||||||
|
========================== =======================
|
||||||
|
|
||||||
|
:undocumented: __revision__, __package__, _AES, _ARC2, _ARC4, _Blowfish
|
||||||
|
_CAST, _DES, _DES3, _XOR
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['AES', 'ARC2', 'ARC4',
|
||||||
|
'Blowfish', 'CAST', 'DES', 'DES3',
|
||||||
|
'XOR',
|
||||||
|
'PKCS1_v1_5', 'PKCS1_OAEP'
|
||||||
|
]
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
|
296
Lib/site-packages/Crypto/Cipher/blockalgo.py
Normal file
296
Lib/site-packages/Crypto/Cipher/blockalgo.py
Normal file
|
@ -0,0 +1,296 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/blockalgo.py
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
"""Module with definitions common to all block ciphers."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
#: *Electronic Code Book (ECB)*.
|
||||||
|
#: This is the simplest encryption mode. Each of the plaintext blocks
|
||||||
|
#: is directly encrypted into a ciphertext block, independently of
|
||||||
|
#: any other block. This mode exposes frequency of symbols
|
||||||
|
#: in your plaintext. Other modes (e.g. *CBC*) should be used instead.
|
||||||
|
#:
|
||||||
|
#: See `NIST SP800-38A`_ , Section 6.1 .
|
||||||
|
#:
|
||||||
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
MODE_ECB = 1
|
||||||
|
|
||||||
|
#: *Cipher-Block Chaining (CBC)*. Each of the ciphertext blocks depends
|
||||||
|
#: on the current and all previous plaintext blocks. An Initialization Vector
|
||||||
|
#: (*IV*) is required.
|
||||||
|
#:
|
||||||
|
#: The *IV* is a data block to be transmitted to the receiver.
|
||||||
|
#: The *IV* can be made public, but it must be authenticated by the receiver and
|
||||||
|
#: it should be picked randomly.
|
||||||
|
#:
|
||||||
|
#: See `NIST SP800-38A`_ , Section 6.2 .
|
||||||
|
#:
|
||||||
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
MODE_CBC = 2
|
||||||
|
|
||||||
|
#: *Cipher FeedBack (CFB)*. This mode is similar to CBC, but it transforms
|
||||||
|
#: the underlying block cipher into a stream cipher. Plaintext and ciphertext
|
||||||
|
#: are processed in *segments* of **s** bits. The mode is therefore sometimes
|
||||||
|
#: labelled **s**-bit CFB. An Initialization Vector (*IV*) is required.
|
||||||
|
#:
|
||||||
|
#: When encrypting, each ciphertext segment contributes to the encryption of
|
||||||
|
#: the next plaintext segment.
|
||||||
|
#:
|
||||||
|
#: This *IV* is a data block to be transmitted to the receiver.
|
||||||
|
#: The *IV* can be made public, but it should be picked randomly.
|
||||||
|
#: Reusing the same *IV* for encryptions done with the same key lead to
|
||||||
|
#: catastrophic cryptographic failures.
|
||||||
|
#:
|
||||||
|
#: See `NIST SP800-38A`_ , Section 6.3 .
|
||||||
|
#:
|
||||||
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
MODE_CFB = 3
|
||||||
|
|
||||||
|
#: This mode should not be used.
|
||||||
|
MODE_PGP = 4
|
||||||
|
|
||||||
|
#: *Output FeedBack (OFB)*. This mode is very similar to CBC, but it
|
||||||
|
#: transforms the underlying block cipher into a stream cipher.
|
||||||
|
#: The keystream is the iterated block encryption of an Initialization Vector (*IV*).
|
||||||
|
#:
|
||||||
|
#: The *IV* is a data block to be transmitted to the receiver.
|
||||||
|
#: The *IV* can be made public, but it should be picked randomly.
|
||||||
|
#:
|
||||||
|
#: Reusing the same *IV* for encryptions done with the same key lead to
|
||||||
|
#: catastrophic cryptograhic failures.
|
||||||
|
#:
|
||||||
|
#: See `NIST SP800-38A`_ , Section 6.4 .
|
||||||
|
#:
|
||||||
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
MODE_OFB = 5
|
||||||
|
|
||||||
|
#: *CounTeR (CTR)*. This mode is very similar to ECB, in that
|
||||||
|
#: encryption of one block is done independently of all other blocks.
|
||||||
|
#: Unlike ECB, the block *position* contributes to the encryption and no
|
||||||
|
#: information leaks about symbol frequency.
|
||||||
|
#:
|
||||||
|
#: Each message block is associated to a *counter* which must be unique
|
||||||
|
#: across all messages that get encrypted with the same key (not just within
|
||||||
|
#: the same message). The counter is as big as the block size.
|
||||||
|
#:
|
||||||
|
#: Counters can be generated in several ways. The most straightword one is
|
||||||
|
#: to choose an *initial counter block* (which can be made public, similarly
|
||||||
|
#: to the *IV* for the other modes) and increment its lowest **m** bits by
|
||||||
|
#: one (modulo *2^m*) for each block. In most cases, **m** is chosen to be half
|
||||||
|
#: the block size.
|
||||||
|
#:
|
||||||
|
#: Reusing the same *initial counter block* for encryptions done with the same
|
||||||
|
#: key lead to catastrophic cryptograhic failures.
|
||||||
|
#:
|
||||||
|
#: See `NIST SP800-38A`_ , Section 6.5 (for the mode) and Appendix B (for how
|
||||||
|
#: to manage the *initial counter block*).
|
||||||
|
#:
|
||||||
|
#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
MODE_CTR = 6
|
||||||
|
|
||||||
|
#: OpenPGP. This mode is a variant of CFB, and it is only used in PGP and OpenPGP_ applications.
|
||||||
|
#: An Initialization Vector (*IV*) is required.
|
||||||
|
#:
|
||||||
|
#: Unlike CFB, the IV is not transmitted to the receiver. Instead, the *encrypted* IV is.
|
||||||
|
#: The IV is a random data block. Two of its bytes are duplicated to act as a checksum
|
||||||
|
#: for the correctness of the key. The encrypted IV is therefore 2 bytes longer than
|
||||||
|
#: the clean IV.
|
||||||
|
#:
|
||||||
|
#: .. _OpenPGP: http://tools.ietf.org/html/rfc4880
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
|
||||||
|
def _getParameter(name, index, args, kwargs, default=None):
|
||||||
|
"""Find a parameter in tuple and dictionary arguments a function receives"""
|
||||||
|
param = kwargs.get(name)
|
||||||
|
if len(args)>index:
|
||||||
|
if param:
|
||||||
|
raise ValueError("Parameter '%s' is specified twice" % name)
|
||||||
|
param = args[index]
|
||||||
|
return param or default
|
||||||
|
|
||||||
|
class BlockAlgo:
|
||||||
|
"""Class modelling an abstract block cipher."""
|
||||||
|
|
||||||
|
def __init__(self, factory, key, *args, **kwargs):
|
||||||
|
self.mode = _getParameter('mode', 0, args, kwargs, default=MODE_ECB)
|
||||||
|
self.block_size = factory.block_size
|
||||||
|
|
||||||
|
if self.mode != MODE_OPENPGP:
|
||||||
|
self._cipher = factory.new(key, *args, **kwargs)
|
||||||
|
self.IV = self._cipher.IV
|
||||||
|
else:
|
||||||
|
# OPENPGP mode. For details, see 13.9 in RCC4880.
|
||||||
|
#
|
||||||
|
# A few members are specifically created for this mode:
|
||||||
|
# - _encrypted_iv, set in this constructor
|
||||||
|
# - _done_first_block, set to True after the first encryption
|
||||||
|
# - _done_last_block, set to True after a partial block is processed
|
||||||
|
|
||||||
|
self._done_first_block = False
|
||||||
|
self._done_last_block = False
|
||||||
|
self.IV = _getParameter('iv', 1, args, kwargs)
|
||||||
|
if not self.IV:
|
||||||
|
raise ValueError("MODE_OPENPGP requires an IV")
|
||||||
|
|
||||||
|
# Instantiate a temporary cipher to process the IV
|
||||||
|
IV_cipher = factory.new(key, MODE_CFB,
|
||||||
|
b('\x00')*self.block_size, # IV for CFB
|
||||||
|
segment_size=self.block_size*8)
|
||||||
|
|
||||||
|
# The cipher will be used for...
|
||||||
|
if len(self.IV) == self.block_size:
|
||||||
|
# ... encryption
|
||||||
|
self._encrypted_IV = IV_cipher.encrypt(
|
||||||
|
self.IV + self.IV[-2:] + # Plaintext
|
||||||
|
b('\x00')*(self.block_size-2) # Padding
|
||||||
|
)[:self.block_size+2]
|
||||||
|
elif len(self.IV) == self.block_size+2:
|
||||||
|
# ... decryption
|
||||||
|
self._encrypted_IV = self.IV
|
||||||
|
self.IV = IV_cipher.decrypt(self.IV + # Ciphertext
|
||||||
|
b('\x00')*(self.block_size-2) # Padding
|
||||||
|
)[:self.block_size+2]
|
||||||
|
if self.IV[-2:] != self.IV[-4:-2]:
|
||||||
|
raise ValueError("Failed integrity check for OPENPGP IV")
|
||||||
|
self.IV = self.IV[:-2]
|
||||||
|
else:
|
||||||
|
raise ValueError("Length of IV must be %d or %d bytes for MODE_OPENPGP"
|
||||||
|
% (self.block_size, self.block_size+2))
|
||||||
|
|
||||||
|
# Instantiate the cipher for the real PGP data
|
||||||
|
self._cipher = factory.new(key, MODE_CFB,
|
||||||
|
self._encrypted_IV[-self.block_size:],
|
||||||
|
segment_size=self.block_size*8)
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
The cipher object is stateful; encryption of a long block
|
||||||
|
of data can be broken up in two or more calls to `encrypt()`.
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is always equivalent to:
|
||||||
|
|
||||||
|
>>> c.encrypt(a+b)
|
||||||
|
|
||||||
|
That also means that you cannot reuse an object for encrypting
|
||||||
|
or decrypting other data with the same key.
|
||||||
|
|
||||||
|
This function does not perform any padding.
|
||||||
|
|
||||||
|
- For `MODE_ECB`, `MODE_CBC`, and `MODE_OFB`, *plaintext* length
|
||||||
|
(in bytes) must be a multiple of *block_size*.
|
||||||
|
|
||||||
|
- For `MODE_CFB`, *plaintext* length (in bytes) must be a multiple
|
||||||
|
of *segment_size*/8.
|
||||||
|
|
||||||
|
- For `MODE_CTR`, *plaintext* can be of any length.
|
||||||
|
|
||||||
|
- For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*,
|
||||||
|
unless it is the last chunk of the message.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string. It is as long as
|
||||||
|
*plaintext* with one exception: when encrypting the first message
|
||||||
|
chunk with `MODE_OPENPGP`, the encypted IV is prepended to the
|
||||||
|
returned ciphertext.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.mode == MODE_OPENPGP:
|
||||||
|
padding_length = (self.block_size - len(plaintext) % self.block_size) % self.block_size
|
||||||
|
if padding_length>0:
|
||||||
|
# CFB mode requires ciphertext to have length multiple of block size,
|
||||||
|
# but PGP mode allows the last block to be shorter
|
||||||
|
if self._done_last_block:
|
||||||
|
raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes",
|
||||||
|
self.block_size)
|
||||||
|
self._done_last_block = True
|
||||||
|
padded = plaintext + b('\x00')*padding_length
|
||||||
|
res = self._cipher.encrypt(padded)[:len(plaintext)]
|
||||||
|
else:
|
||||||
|
res = self._cipher.encrypt(plaintext)
|
||||||
|
if not self._done_first_block:
|
||||||
|
res = self._encrypted_IV + res
|
||||||
|
self._done_first_block = True
|
||||||
|
return res
|
||||||
|
|
||||||
|
return self._cipher.encrypt(plaintext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
The cipher object is stateful; decryption of a long block
|
||||||
|
of data can be broken up in two or more calls to `decrypt()`.
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is always equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
That also means that you cannot reuse an object for encrypting
|
||||||
|
or decrypting other data with the same key.
|
||||||
|
|
||||||
|
This function does not perform any padding.
|
||||||
|
|
||||||
|
- For `MODE_ECB`, `MODE_CBC`, and `MODE_OFB`, *ciphertext* length
|
||||||
|
(in bytes) must be a multiple of *block_size*.
|
||||||
|
|
||||||
|
- For `MODE_CFB`, *ciphertext* length (in bytes) must be a multiple
|
||||||
|
of *segment_size*/8.
|
||||||
|
|
||||||
|
- For `MODE_CTR`, *ciphertext* can be of any length.
|
||||||
|
|
||||||
|
- For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*,
|
||||||
|
unless it is the last chunk of the message.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
:Return: the decrypted data (byte string, as long as *ciphertext*).
|
||||||
|
"""
|
||||||
|
if self.mode == MODE_OPENPGP:
|
||||||
|
padding_length = (self.block_size - len(ciphertext) % self.block_size) % self.block_size
|
||||||
|
if padding_length>0:
|
||||||
|
# CFB mode requires ciphertext to have length multiple of block size,
|
||||||
|
# but PGP mode allows the last block to be shorter
|
||||||
|
if self._done_last_block:
|
||||||
|
raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes",
|
||||||
|
self.block_size)
|
||||||
|
self._done_last_block = True
|
||||||
|
padded = ciphertext + b('\x00')*padding_length
|
||||||
|
res = self._cipher.decrypt(padded)[:len(ciphertext)]
|
||||||
|
else:
|
||||||
|
res = self._cipher.decrypt(ciphertext)
|
||||||
|
return res
|
||||||
|
|
||||||
|
return self._cipher.decrypt(ciphertext)
|
||||||
|
|
212
Lib/site-packages/Crypto/Hash/HMAC.py
Normal file
212
Lib/site-packages/Crypto/Hash/HMAC.py
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
# HMAC.py - Implements the HMAC algorithm as described by RFC 2104.
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# Portions Copyright (c) 2001, 2002, 2003 Python Software Foundation;
|
||||||
|
# All Rights Reserved
|
||||||
|
#
|
||||||
|
# This file contains code from the Python 2.2 hmac.py module (the
|
||||||
|
# "Original Code"), with modifications made after it was incorporated
|
||||||
|
# into PyCrypto (the "Modifications").
|
||||||
|
#
|
||||||
|
# To the best of our knowledge, the Python Software Foundation is the
|
||||||
|
# copyright holder of the Original Code, and has licensed it under the
|
||||||
|
# Python 2.2 license. See the file LEGAL/copy/LICENSE.python-2.2 for
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# The Modifications to this file are dedicated to the public domain.
|
||||||
|
# To the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever. No rights are
|
||||||
|
# reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
|
||||||
|
"""HMAC (Hash-based Message Authentication Code) algorithm
|
||||||
|
|
||||||
|
HMAC is a MAC defined in RFC2104_ and FIPS-198_ and constructed using
|
||||||
|
a cryptograpic hash algorithm.
|
||||||
|
It is usually named *HMAC-X*, where *X* is the hash algorithm; for
|
||||||
|
instance *HMAC-SHA1* or *HMAC-MD5*.
|
||||||
|
|
||||||
|
The strength of an HMAC depends on:
|
||||||
|
|
||||||
|
- the strength of the hash algorithm
|
||||||
|
- the length and entropy of the secret key
|
||||||
|
|
||||||
|
An example of possible usage is the following:
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import HMAC
|
||||||
|
>>>
|
||||||
|
>>> secret = b'Swordfish'
|
||||||
|
>>> h = HMAC.new(secret)
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
.. _RFC2104: http://www.ietf.org/rfc/rfc2104.txt
|
||||||
|
.. _FIPS-198: http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
# This is just a copy of the Python 2.2 HMAC module, modified to work when
|
||||||
|
# used on versions of Python before 2.2.
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'HMAC' ]
|
||||||
|
|
||||||
|
from Crypto.Util.strxor import strxor_c
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
#: The size of the authentication tag produced by the MAC.
|
||||||
|
#: It matches the digest size on the underlying
|
||||||
|
#: hashing module used.
|
||||||
|
digest_size = None
|
||||||
|
|
||||||
|
class HMAC:
|
||||||
|
"""Class that implements HMAC"""
|
||||||
|
|
||||||
|
#: The size of the authentication tag produced by the MAC.
|
||||||
|
#: It matches the digest size on the underlying
|
||||||
|
#: hashing module used.
|
||||||
|
digest_size = None
|
||||||
|
|
||||||
|
def __init__(self, key, msg = None, digestmod = None):
|
||||||
|
"""Create a new HMAC object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
secret key for the MAC object.
|
||||||
|
It must be long enough to match the expected security level of the
|
||||||
|
MAC. However, there is no benefit in using keys longer than the
|
||||||
|
`digest_size` of the underlying hash algorithm.
|
||||||
|
msg : byte string
|
||||||
|
The very first chunk of the message to authenticate.
|
||||||
|
It is equivalent to an early call to `update()`. Optional.
|
||||||
|
:Parameter digestmod:
|
||||||
|
The hash algorithm the HMAC is based on.
|
||||||
|
Default is `Crypto.Hash.MD5`.
|
||||||
|
:Type digestmod:
|
||||||
|
A hash module or object instantiated from `Crypto.Hash`
|
||||||
|
"""
|
||||||
|
if digestmod is None:
|
||||||
|
from . import MD5
|
||||||
|
digestmod = MD5
|
||||||
|
|
||||||
|
self.digestmod = digestmod
|
||||||
|
self.outer = digestmod.new()
|
||||||
|
self.inner = digestmod.new()
|
||||||
|
try:
|
||||||
|
self.digest_size = digestmod.digest_size
|
||||||
|
except AttributeError:
|
||||||
|
self.digest_size = len(self.outer.digest())
|
||||||
|
|
||||||
|
try:
|
||||||
|
# The block size is 128 bytes for SHA384 and SHA512 and 64 bytes
|
||||||
|
# for the others hash function
|
||||||
|
blocksize = digestmod.block_size
|
||||||
|
except AttributeError:
|
||||||
|
blocksize = 64
|
||||||
|
|
||||||
|
ipad = 0x36
|
||||||
|
opad = 0x5C
|
||||||
|
|
||||||
|
if len(key) > blocksize:
|
||||||
|
key = digestmod.new(key).digest()
|
||||||
|
|
||||||
|
key = key + bchr(0) * (blocksize - len(key))
|
||||||
|
self.outer.update(strxor_c(key, opad))
|
||||||
|
self.inner.update(strxor_c(key, ipad))
|
||||||
|
if (msg):
|
||||||
|
self.update(msg)
|
||||||
|
|
||||||
|
def update(self, msg):
|
||||||
|
"""Continue authentication of a message by consuming the next chunk of data.
|
||||||
|
|
||||||
|
Repeated calls are equivalent to a single call with the concatenation
|
||||||
|
of all the arguments. In other words:
|
||||||
|
|
||||||
|
>>> m.update(a); m.update(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> m.update(a+b)
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
msg : byte string
|
||||||
|
The next chunk of the message being authenticated
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.inner.update(msg)
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
"""Return a copy ("clone") of the MAC object.
|
||||||
|
|
||||||
|
The copy will have the same internal state as the original MAC
|
||||||
|
object.
|
||||||
|
This can be used to efficiently compute the MAC of strings that
|
||||||
|
share a common initial substring.
|
||||||
|
|
||||||
|
:Returns: An `HMAC` object
|
||||||
|
"""
|
||||||
|
other = HMAC(b(""))
|
||||||
|
other.digestmod = self.digestmod
|
||||||
|
other.inner = self.inner.copy()
|
||||||
|
other.outer = self.outer.copy()
|
||||||
|
return other
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Return the **binary** (non-printable) MAC of the message that has
|
||||||
|
been authenticated so far.
|
||||||
|
|
||||||
|
This method does not change the state of the MAC object.
|
||||||
|
You can continue updating the object after calling this function.
|
||||||
|
|
||||||
|
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
|
||||||
|
characters, including null bytes.
|
||||||
|
"""
|
||||||
|
h = self.outer.copy()
|
||||||
|
h.update(self.inner.digest())
|
||||||
|
return h.digest()
|
||||||
|
|
||||||
|
def hexdigest(self):
|
||||||
|
"""Return the **printable** MAC of the message that has been
|
||||||
|
authenticated so far.
|
||||||
|
|
||||||
|
This method does not change the state of the MAC object.
|
||||||
|
|
||||||
|
:Return: A string of 2* `digest_size` bytes. It contains only
|
||||||
|
hexadecimal ASCII digits.
|
||||||
|
"""
|
||||||
|
return "".join(["%02x" % bord(x)
|
||||||
|
for x in tuple(self.digest())])
|
||||||
|
|
||||||
|
def new(key, msg = None, digestmod = None):
|
||||||
|
"""Create a new HMAC object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
key for the MAC object.
|
||||||
|
It must be long enough to match the expected security level of the
|
||||||
|
MAC. However, there is no benefit in using keys longer than the
|
||||||
|
`digest_size` of the underlying hash algorithm.
|
||||||
|
msg : byte string
|
||||||
|
The very first chunk of the message to authenticate.
|
||||||
|
It is equivalent to an early call to `HMAC.update()`.
|
||||||
|
Optional.
|
||||||
|
:Parameter digestmod:
|
||||||
|
The hash to use to implement the HMAC. Default is `Crypto.Hash.MD5`.
|
||||||
|
:Type digestmod:
|
||||||
|
A hash module or instantiated object from `Crypto.Hash`
|
||||||
|
:Returns: An `HMAC` object
|
||||||
|
"""
|
||||||
|
return HMAC(key, msg, digestmod)
|
||||||
|
|
91
Lib/site-packages/Crypto/Hash/MD2.py
Normal file
91
Lib/site-packages/Crypto/Hash/MD2.py
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""MD2 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
MD2 is specified in RFC1319_ and it produces the 128 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import MD2
|
||||||
|
>>>
|
||||||
|
>>> h = MD2.new()
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
MD2 stand for Message Digest version 2, and it was invented by Rivest in 1989.
|
||||||
|
|
||||||
|
This algorithm is both slow and insecure. Do not use it for new designs.
|
||||||
|
|
||||||
|
.. _RFC1319: http://tools.ietf.org/html/rfc1319
|
||||||
|
"""
|
||||||
|
|
||||||
|
_revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'MD2Hash' ]
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash.hashalgo import HashAlgo
|
||||||
|
|
||||||
|
import Crypto.Hash._MD2 as _MD2
|
||||||
|
hashFactory = _MD2
|
||||||
|
|
||||||
|
class MD2Hash(HashAlgo):
|
||||||
|
"""Class that implements an MD2 hash
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object identifier (OID)::
|
||||||
|
#:
|
||||||
|
#: id-md2 OBJECT IDENTIFIER ::= {
|
||||||
|
#: iso(1) member-body(2) us(840) rsadsi(113549)
|
||||||
|
#: digestAlgorithm(2) 2
|
||||||
|
#: }
|
||||||
|
#:
|
||||||
|
#: This value uniquely identifies the MD2 algorithm.
|
||||||
|
oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02')
|
||||||
|
|
||||||
|
digest_size = 16
|
||||||
|
block_size = 16
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
HashAlgo.__init__(self, hashFactory, data)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return MD2Hash(data)
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `MD2Hash.update()`.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: An `MD2Hash` object
|
||||||
|
"""
|
||||||
|
return MD2Hash().new(data)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = MD2Hash.digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = MD2Hash.block_size
|
||||||
|
|
91
Lib/site-packages/Crypto/Hash/MD4.py
Normal file
91
Lib/site-packages/Crypto/Hash/MD4.py
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""MD4 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
MD4 is specified in RFC1320_ and produces the 128 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import MD4
|
||||||
|
>>>
|
||||||
|
>>> h = MD4.new()
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
MD4 stand for Message Digest version 4, and it was invented by Rivest in 1990.
|
||||||
|
|
||||||
|
This algorithm is insecure. Do not use it for new designs.
|
||||||
|
|
||||||
|
.. _RFC1320: http://tools.ietf.org/html/rfc1320
|
||||||
|
"""
|
||||||
|
|
||||||
|
_revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'MD4Hash' ]
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash.hashalgo import HashAlgo
|
||||||
|
|
||||||
|
import Crypto.Hash._MD4 as _MD4
|
||||||
|
hashFactory = _MD4
|
||||||
|
|
||||||
|
class MD4Hash(HashAlgo):
|
||||||
|
"""Class that implements an MD4 hash
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object identifier (OID)::
|
||||||
|
#:
|
||||||
|
#: id-md2 OBJECT IDENTIFIER ::= {
|
||||||
|
#: iso(1) member-body(2) us(840) rsadsi(113549)
|
||||||
|
#: digestAlgorithm(2) 4
|
||||||
|
#: }
|
||||||
|
#:
|
||||||
|
#: This value uniquely identifies the MD4 algorithm.
|
||||||
|
oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04')
|
||||||
|
|
||||||
|
digest_size = 16
|
||||||
|
block_size = 64
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
HashAlgo.__init__(self, hashFactory, data)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return MD4Hash(data)
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `MD4Hash.update()`.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `MD4Hash` object
|
||||||
|
"""
|
||||||
|
return MD4Hash().new(data)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = MD4Hash.digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = MD4Hash.block_size
|
||||||
|
|
97
Lib/site-packages/Crypto/Hash/MD5.py
Normal file
97
Lib/site-packages/Crypto/Hash/MD5.py
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""MD5 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
MD5 is specified in RFC1321_ and produces the 128 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import MD5
|
||||||
|
>>>
|
||||||
|
>>> h = MD5.new()
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
MD5 stand for Message Digest version 5, and it was invented by Rivest in 1991.
|
||||||
|
|
||||||
|
This algorithm is insecure. Do not use it for new designs.
|
||||||
|
|
||||||
|
.. _RFC1321: http://tools.ietf.org/html/rfc1321
|
||||||
|
"""
|
||||||
|
|
||||||
|
_revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'MD5Hash' ]
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash.hashalgo import HashAlgo
|
||||||
|
|
||||||
|
try:
|
||||||
|
# The md5 module is deprecated in Python 2.6, so use hashlib when possible.
|
||||||
|
import hashlib
|
||||||
|
hashFactory = hashlib.md5
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
from . import md5
|
||||||
|
hashFactory = md5
|
||||||
|
|
||||||
|
class MD5Hash(HashAlgo):
|
||||||
|
"""Class that implements an MD5 hash
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object identifier (OID)::
|
||||||
|
#:
|
||||||
|
#: id-md5 OBJECT IDENTIFIER ::= {
|
||||||
|
#: iso(1) member-body(2) us(840) rsadsi(113549)
|
||||||
|
#: digestAlgorithm(2) 5
|
||||||
|
#: }
|
||||||
|
#:
|
||||||
|
#: This value uniquely identifies the MD5 algorithm.
|
||||||
|
oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05')
|
||||||
|
|
||||||
|
digest_size = 16
|
||||||
|
block_size = 64
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
HashAlgo.__init__(self, hashFactory, data)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return MD5Hash(data)
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `MD5Hash.update()`.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `MD5Hash` object
|
||||||
|
"""
|
||||||
|
return MD5Hash().new(data)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = MD5Hash.digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = MD5Hash.block_size
|
||||||
|
|
94
Lib/site-packages/Crypto/Hash/RIPEMD.py
Normal file
94
Lib/site-packages/Crypto/Hash/RIPEMD.py
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""RIPEMD-160 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
RIPEMD-160_ produces the 160 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import RIPEMD
|
||||||
|
>>>
|
||||||
|
>>> h = RIPEMD.new()
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
RIPEMD-160 stands for RACE Integrity Primitives Evaluation Message Digest
|
||||||
|
with a 160 bit digest. It was invented by Dobbertin, Bosselaers, and Preneel.
|
||||||
|
|
||||||
|
This algorithm is considered secure, although it has not been scrutinized as
|
||||||
|
extensively as SHA-1. Moreover, it provides an informal security level of just
|
||||||
|
80bits.
|
||||||
|
|
||||||
|
.. _RIPEMD-160: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
_revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'RIPEMD160Hash' ]
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash.hashalgo import HashAlgo
|
||||||
|
|
||||||
|
import Crypto.Hash._RIPEMD160 as _RIPEMD160
|
||||||
|
hashFactory = _RIPEMD160
|
||||||
|
|
||||||
|
class RIPEMD160Hash(HashAlgo):
|
||||||
|
"""Class that implements a RIPMD-160 hash
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object identifier (OID)::
|
||||||
|
#:
|
||||||
|
#: id-ripemd160 OBJECT IDENTIFIER ::= {
|
||||||
|
#: iso(1) identified-organization(3) teletrust(36)
|
||||||
|
#: algorithm(3) hashAlgorithm(2) ripemd160(1)
|
||||||
|
#: }
|
||||||
|
#:
|
||||||
|
#: This value uniquely identifies the RIPMD-160 algorithm.
|
||||||
|
oid = b("\x06\x05\x2b\x24\x03\x02\x01")
|
||||||
|
|
||||||
|
digest_size = 20
|
||||||
|
block_size = 64
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
HashAlgo.__init__(self, hashFactory, data)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return RIPEMD160Hash(data)
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `RIPEMD160Hash.update()`.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `RIPEMD160Hash` object
|
||||||
|
"""
|
||||||
|
return RIPEMD160Hash().new(data)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = RIPEMD160Hash.digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = RIPEMD160Hash.block_size
|
||||||
|
|
98
Lib/site-packages/Crypto/Hash/SHA.py
Normal file
98
Lib/site-packages/Crypto/Hash/SHA.py
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""SHA-1 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
SHA-1_ produces the 160 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHA
|
||||||
|
>>>
|
||||||
|
>>> h = SHA.new()
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
*SHA* stands for Secure Hash Algorithm.
|
||||||
|
|
||||||
|
This algorithm is not considered secure. Do not use it for new designs.
|
||||||
|
|
||||||
|
.. _SHA-1: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
_revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'SHA1Hash' ]
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash.hashalgo import HashAlgo
|
||||||
|
|
||||||
|
try:
|
||||||
|
# The sha module is deprecated in Python 2.6, so use hashlib when possible.
|
||||||
|
import hashlib
|
||||||
|
hashFactory = hashlib.sha1
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
from . import sha
|
||||||
|
hashFactory = sha
|
||||||
|
|
||||||
|
class SHA1Hash(HashAlgo):
|
||||||
|
"""Class that implements a SHA-1 hash
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object identifier (OID)::
|
||||||
|
#:
|
||||||
|
#: id-sha1 OBJECT IDENTIFIER ::= {
|
||||||
|
#: iso(1) identified-organization(3) oiw(14) secsig(3)
|
||||||
|
#: algorithms(2) 26
|
||||||
|
#: }
|
||||||
|
#:
|
||||||
|
#: This value uniquely identifies the SHA-1 algorithm.
|
||||||
|
oid = b('\x06\x05\x2b\x0e\x03\x02\x1a')
|
||||||
|
|
||||||
|
digest_size = 20
|
||||||
|
block_size = 64
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
HashAlgo.__init__(self, hashFactory, data)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return SHA1Hash(data)
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `SHA1Hash.update()`.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `SHA1Hash` object
|
||||||
|
"""
|
||||||
|
return SHA1Hash().new(data)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = SHA1Hash.digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = SHA1Hash.block_size
|
||||||
|
|
||||||
|
|
95
Lib/site-packages/Crypto/Hash/SHA224.py
Normal file
95
Lib/site-packages/Crypto/Hash/SHA224.py
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""SHA-224 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
SHA-224 belongs to the SHA-2_ family of cryptographic hashes.
|
||||||
|
It produces the 224 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHA224
|
||||||
|
>>>
|
||||||
|
>>> h = SHA224.new()
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
*SHA* stands for Secure Hash Algorithm.
|
||||||
|
|
||||||
|
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
_revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'SHA224Hash' ]
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash.hashalgo import HashAlgo
|
||||||
|
|
||||||
|
try:
|
||||||
|
import hashlib
|
||||||
|
hashFactory = hashlib.sha224
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
from Crypto.Hash import _SHA224
|
||||||
|
hashFactory = _SHA224
|
||||||
|
|
||||||
|
class SHA224Hash(HashAlgo):
|
||||||
|
"""Class that implements a SHA-224 hash
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object identifier (OID)::
|
||||||
|
#:
|
||||||
|
#: id-sha224 OBJECT IDENTIFIER ::= {
|
||||||
|
#: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
|
||||||
|
#: nistalgorithm(4) hashalgs(2) 4
|
||||||
|
#: }
|
||||||
|
#:
|
||||||
|
#: This value uniquely identifies the SHA-224 algorithm.
|
||||||
|
oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04')
|
||||||
|
|
||||||
|
digest_size = 28
|
||||||
|
block_size = 64
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
HashAlgo.__init__(self, hashFactory, data)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return SHA224Hash(data)
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `SHA224Hash.update()`.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `SHA224Hash` object
|
||||||
|
"""
|
||||||
|
return SHA224Hash().new(data)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = SHA224Hash.digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = SHA224Hash.block_size
|
||||||
|
|
95
Lib/site-packages/Crypto/Hash/SHA256.py
Normal file
95
Lib/site-packages/Crypto/Hash/SHA256.py
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""SHA-256 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
SHA-256 belongs to the SHA-2_ family of cryptographic hashes.
|
||||||
|
It produces the 256 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHA256
|
||||||
|
>>>
|
||||||
|
>>> h = SHA256.new()
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
*SHA* stands for Secure Hash Algorithm.
|
||||||
|
|
||||||
|
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
_revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'SHA256Hash' ]
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash.hashalgo import HashAlgo
|
||||||
|
|
||||||
|
try:
|
||||||
|
import hashlib
|
||||||
|
hashFactory = hashlib.sha256
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
from Crypto.Hash import _SHA256
|
||||||
|
hashFactory = _SHA256
|
||||||
|
|
||||||
|
class SHA256Hash(HashAlgo):
|
||||||
|
"""Class that implements a SHA-256 hash
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object identifier (OID)::
|
||||||
|
#:
|
||||||
|
#: id-sha256 OBJECT IDENTIFIER ::= {
|
||||||
|
#: joint-iso-itu-t(2) country(16) us(840) organization(1)
|
||||||
|
#: gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1
|
||||||
|
#: }
|
||||||
|
#:
|
||||||
|
#: This value uniquely identifies the SHA-256 algorithm.
|
||||||
|
oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01')
|
||||||
|
|
||||||
|
digest_size = 32
|
||||||
|
block_size = 64
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
HashAlgo.__init__(self, hashFactory, data)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return SHA256Hash(data)
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `SHA256Hash.update()`.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `SHA256Hash` object
|
||||||
|
"""
|
||||||
|
return SHA256Hash().new(data)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = SHA256Hash.digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = SHA256Hash.block_size
|
||||||
|
|
96
Lib/site-packages/Crypto/Hash/SHA384.py
Normal file
96
Lib/site-packages/Crypto/Hash/SHA384.py
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""SHA-384 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
SHA-384 belongs to the SHA-2_ family of cryptographic hashes.
|
||||||
|
It produces the 384 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHA384
|
||||||
|
>>>
|
||||||
|
>>> h = SHA384.new()
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
*SHA* stands for Secure Hash Algorithm.
|
||||||
|
|
||||||
|
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
_revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'SHA384Hash' ]
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash.hashalgo import HashAlgo
|
||||||
|
|
||||||
|
try:
|
||||||
|
import hashlib
|
||||||
|
hashFactory = hashlib.sha384
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
from Crypto.Hash import _SHA384
|
||||||
|
hashFactory = _SHA384
|
||||||
|
|
||||||
|
class SHA384Hash(HashAlgo):
|
||||||
|
"""Class that implements a SHA-384 hash
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object identifier (OID)::
|
||||||
|
#:
|
||||||
|
#: id-sha384 OBJECT IDENTIFIER ::= {
|
||||||
|
#: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
|
||||||
|
#: nistalgorithm(4) hashalgs(2) 2
|
||||||
|
#: }
|
||||||
|
#:
|
||||||
|
#: This value uniquely identifies the SHA-384 algorithm.
|
||||||
|
oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02')
|
||||||
|
|
||||||
|
digest_size = 48
|
||||||
|
block_size = 128
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
HashAlgo.__init__(self, hashFactory, data)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return SHA384Hash(data)
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `SHA384Hash.update()`.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `SHA384Hash` object
|
||||||
|
"""
|
||||||
|
return SHA384Hash().new(data)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = SHA384Hash.digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = SHA384Hash.block_size
|
||||||
|
|
||||||
|
|
95
Lib/site-packages/Crypto/Hash/SHA512.py
Normal file
95
Lib/site-packages/Crypto/Hash/SHA512.py
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""SHA-512 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
SHA-512 belongs to the SHA-2_ family of cryptographic hashes.
|
||||||
|
It produces the 512 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHA512
|
||||||
|
>>>
|
||||||
|
>>> h = SHA512.new()
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
*SHA* stands for Secure Hash Algorithm.
|
||||||
|
|
||||||
|
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
_revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['new', 'digest_size', 'SHA512Hash' ]
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash.hashalgo import HashAlgo
|
||||||
|
|
||||||
|
try:
|
||||||
|
import hashlib
|
||||||
|
hashFactory = hashlib.sha512
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
from Crypto.Hash import _SHA512
|
||||||
|
hashFactory = _SHA512
|
||||||
|
|
||||||
|
class SHA512Hash(HashAlgo):
|
||||||
|
"""Class that implements a SHA-512 hash
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object identifier (OID)::
|
||||||
|
#:
|
||||||
|
#: id-sha512 OBJECT IDENTIFIER ::= {
|
||||||
|
#: joint-iso-itu-t(2)
|
||||||
|
#: country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3
|
||||||
|
#: }
|
||||||
|
#:
|
||||||
|
#: This value uniquely identifies the SHA-512 algorithm.
|
||||||
|
oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03')
|
||||||
|
|
||||||
|
digest_size = 64
|
||||||
|
block_size = 128
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
HashAlgo.__init__(self, hashFactory, data)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return SHA512Hash(data)
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `SHA512Hash.update()`.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `SHA512Hash` object
|
||||||
|
"""
|
||||||
|
return SHA512Hash().new(data)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = SHA512Hash.digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = SHA512Hash.block_size
|
||||||
|
|
56
Lib/site-packages/Crypto/Hash/__init__.py
Normal file
56
Lib/site-packages/Crypto/Hash/__init__.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Hashing algorithms
|
||||||
|
|
||||||
|
Hash functions take arbitrary binary strings as input, and produce a random-like output
|
||||||
|
of fixed size that is dependent on the input; it should be practically infeasible
|
||||||
|
to derive the original input data given only the hash function's
|
||||||
|
output. In other words, the hash function is *one-way*.
|
||||||
|
|
||||||
|
It should also not be practically feasible to find a second piece of data
|
||||||
|
(a *second pre-image*) whose hash is the same as the original message
|
||||||
|
(*weak collision resistance*).
|
||||||
|
|
||||||
|
Finally, it should not be feasible to find two arbitrary messages with the
|
||||||
|
same hash (*strong collision resistance*).
|
||||||
|
|
||||||
|
The output of the hash function is called the *digest* of the input message.
|
||||||
|
In general, the security of a hash function is related to the length of the
|
||||||
|
digest. If the digest is *n* bits long, its security level is roughly comparable
|
||||||
|
to the the one offered by an *n/2* bit encryption algorithm.
|
||||||
|
|
||||||
|
Hash functions can be used simply as a integrity check, or, in
|
||||||
|
association with a public-key algorithm, can be used to implement
|
||||||
|
digital signatures.
|
||||||
|
|
||||||
|
The hashing modules here all support the interface described in `PEP
|
||||||
|
247`_ , "API for Cryptographic Hash Functions".
|
||||||
|
|
||||||
|
.. _`PEP 247` : http://www.python.org/dev/peps/pep-0247/
|
||||||
|
|
||||||
|
:undocumented: _MD2, _MD4, _RIPEMD160, _SHA224, _SHA256, _SHA384, _SHA512
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD', 'SHA',
|
||||||
|
'SHA224', 'SHA256', 'SHA384', 'SHA512']
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
|
116
Lib/site-packages/Crypto/Hash/hashalgo.py
Normal file
116
Lib/site-packages/Crypto/Hash/hashalgo.py
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
from binascii import hexlify
|
||||||
|
|
||||||
|
class HashAlgo:
|
||||||
|
"""A generic class for an abstract cryptographic hash algorithm.
|
||||||
|
|
||||||
|
:undocumented: block_size
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = None
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = None
|
||||||
|
|
||||||
|
def __init__(self, hashFactory, data=None):
|
||||||
|
"""Initialize the hash object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hashFactory : callable
|
||||||
|
An object that will generate the actual hash implementation.
|
||||||
|
*hashFactory* must have a *new()* method, or must be directly
|
||||||
|
callable.
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `update()`.
|
||||||
|
"""
|
||||||
|
if hasattr(hashFactory, 'new'):
|
||||||
|
self._hash = hashFactory.new()
|
||||||
|
else:
|
||||||
|
self._hash = hashFactory()
|
||||||
|
if data:
|
||||||
|
self.update(data)
|
||||||
|
|
||||||
|
def update(self, data):
|
||||||
|
"""Continue hashing of a message by consuming the next chunk of data.
|
||||||
|
|
||||||
|
Repeated calls are equivalent to a single call with the concatenation
|
||||||
|
of all the arguments. In other words:
|
||||||
|
|
||||||
|
>>> m.update(a); m.update(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> m.update(a+b)
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The next chunk of the message being hashed.
|
||||||
|
"""
|
||||||
|
return self._hash.update(data)
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
|
||||||
|
|
||||||
|
This method does not change the state of the hash object.
|
||||||
|
You can continue updating the object after calling this function.
|
||||||
|
|
||||||
|
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
|
||||||
|
characters, including null bytes.
|
||||||
|
"""
|
||||||
|
return self._hash.digest()
|
||||||
|
|
||||||
|
def hexdigest(self):
|
||||||
|
"""Return the **printable** digest of the message that has been hashed so far.
|
||||||
|
|
||||||
|
This method does not change the state of the hash object.
|
||||||
|
|
||||||
|
:Return: A string of 2* `digest_size` characters. It contains only
|
||||||
|
hexadecimal ASCII digits.
|
||||||
|
"""
|
||||||
|
return self._hash.hexdigest()
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
"""Return a copy ("clone") of the hash object.
|
||||||
|
|
||||||
|
The copy will have the same internal state as the original hash
|
||||||
|
object.
|
||||||
|
This can be used to efficiently compute the digests of strings that
|
||||||
|
share a common initial substring.
|
||||||
|
|
||||||
|
:Return: A hash object of the same type
|
||||||
|
"""
|
||||||
|
return self._hash.copy()
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
Unlike the `copy` method, the internal state of the object is empty.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The next chunk of the message being hashed.
|
||||||
|
|
||||||
|
:Return: A hash object of the same type
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
320
Lib/site-packages/Crypto/Protocol/AllOrNothing.py
Normal file
320
Lib/site-packages/Crypto/Protocol/AllOrNothing.py
Normal file
|
@ -0,0 +1,320 @@
|
||||||
|
#
|
||||||
|
# AllOrNothing.py : all-or-nothing package transformations
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# Written by Andrew M. Kuchling and others
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""This file implements all-or-nothing package transformations.
|
||||||
|
|
||||||
|
An all-or-nothing package transformation is one in which some text is
|
||||||
|
transformed into message blocks, such that all blocks must be obtained before
|
||||||
|
the reverse transformation can be applied. Thus, if any blocks are corrupted
|
||||||
|
or lost, the original message cannot be reproduced.
|
||||||
|
|
||||||
|
An all-or-nothing package transformation is not encryption, although a block
|
||||||
|
cipher algorithm is used. The encryption key is randomly generated and is
|
||||||
|
extractable from the message blocks.
|
||||||
|
|
||||||
|
This class implements the All-Or-Nothing package transformation algorithm
|
||||||
|
described in:
|
||||||
|
|
||||||
|
Ronald L. Rivest. "All-Or-Nothing Encryption and The Package Transform"
|
||||||
|
http://theory.lcs.mit.edu/~rivest/fusion.pdf
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import operator
|
||||||
|
import sys
|
||||||
|
from Crypto.Util.number import bytes_to_long, long_to_bytes
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
def isInt(x):
|
||||||
|
test = 0
|
||||||
|
try:
|
||||||
|
test += x
|
||||||
|
except TypeError:
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
class AllOrNothing:
|
||||||
|
"""Class implementing the All-or-Nothing package transform.
|
||||||
|
|
||||||
|
Methods for subclassing:
|
||||||
|
|
||||||
|
_inventkey(key_size):
|
||||||
|
Returns a randomly generated key. Subclasses can use this to
|
||||||
|
implement better random key generating algorithms. The default
|
||||||
|
algorithm is probably not very cryptographically secure.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, ciphermodule, mode=None, IV=None):
|
||||||
|
"""AllOrNothing(ciphermodule, mode=None, IV=None)
|
||||||
|
|
||||||
|
ciphermodule is a module implementing the cipher algorithm to
|
||||||
|
use. It must provide the PEP272 interface.
|
||||||
|
|
||||||
|
Note that the encryption key is randomly generated
|
||||||
|
automatically when needed. Optional arguments mode and IV are
|
||||||
|
passed directly through to the ciphermodule.new() method; they
|
||||||
|
are the feedback mode and initialization vector to use. All
|
||||||
|
three arguments must be the same for the object used to create
|
||||||
|
the digest, and to undigest'ify the message blocks.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.__ciphermodule = ciphermodule
|
||||||
|
self.__mode = mode
|
||||||
|
self.__IV = IV
|
||||||
|
self.__key_size = ciphermodule.key_size
|
||||||
|
if not isInt(self.__key_size) or self.__key_size==0:
|
||||||
|
self.__key_size = 16
|
||||||
|
|
||||||
|
__K0digit = bchr(0x69)
|
||||||
|
|
||||||
|
def digest(self, text):
|
||||||
|
"""digest(text:string) : [string]
|
||||||
|
|
||||||
|
Perform the All-or-Nothing package transform on the given
|
||||||
|
string. Output is a list of message blocks describing the
|
||||||
|
transformed text, where each block is a string of bit length equal
|
||||||
|
to the ciphermodule's block_size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# generate a random session key and K0, the key used to encrypt the
|
||||||
|
# hash blocks. Rivest calls this a fixed, publically-known encryption
|
||||||
|
# key, but says nothing about the security implications of this key or
|
||||||
|
# how to choose it.
|
||||||
|
key = self._inventkey(self.__key_size)
|
||||||
|
K0 = self.__K0digit * self.__key_size
|
||||||
|
|
||||||
|
# we need two cipher objects here, one that is used to encrypt the
|
||||||
|
# message blocks and one that is used to encrypt the hashes. The
|
||||||
|
# former uses the randomly generated key, while the latter uses the
|
||||||
|
# well-known key.
|
||||||
|
mcipher = self.__newcipher(key)
|
||||||
|
hcipher = self.__newcipher(K0)
|
||||||
|
|
||||||
|
# Pad the text so that its length is a multiple of the cipher's
|
||||||
|
# block_size. Pad with trailing spaces, which will be eliminated in
|
||||||
|
# the undigest() step.
|
||||||
|
block_size = self.__ciphermodule.block_size
|
||||||
|
padbytes = block_size - (len(text) % block_size)
|
||||||
|
text = text + b(' ') * padbytes
|
||||||
|
|
||||||
|
# Run through the algorithm:
|
||||||
|
# s: number of message blocks (size of text / block_size)
|
||||||
|
# input sequence: m1, m2, ... ms
|
||||||
|
# random key K' (`key' in the code)
|
||||||
|
# Compute output sequence: m'1, m'2, ... m's' for s' = s + 1
|
||||||
|
# Let m'i = mi ^ E(K', i) for i = 1, 2, 3, ..., s
|
||||||
|
# Let m's' = K' ^ h1 ^ h2 ^ ... hs
|
||||||
|
# where hi = E(K0, m'i ^ i) for i = 1, 2, ... s
|
||||||
|
#
|
||||||
|
# The one complication I add is that the last message block is hard
|
||||||
|
# coded to the number of padbytes added, so that these can be stripped
|
||||||
|
# during the undigest() step
|
||||||
|
s = divmod(len(text), block_size)[0]
|
||||||
|
blocks = []
|
||||||
|
hashes = []
|
||||||
|
for i in range(1, s+1):
|
||||||
|
start = (i-1) * block_size
|
||||||
|
end = start + block_size
|
||||||
|
mi = text[start:end]
|
||||||
|
assert len(mi) == block_size
|
||||||
|
cipherblock = mcipher.encrypt(long_to_bytes(i, block_size))
|
||||||
|
mticki = bytes_to_long(mi) ^ bytes_to_long(cipherblock)
|
||||||
|
blocks.append(mticki)
|
||||||
|
# calculate the hash block for this block
|
||||||
|
hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size))
|
||||||
|
hashes.append(bytes_to_long(hi))
|
||||||
|
|
||||||
|
# Add the padbytes length as a message block
|
||||||
|
i = i + 1
|
||||||
|
cipherblock = mcipher.encrypt(long_to_bytes(i, block_size))
|
||||||
|
mticki = padbytes ^ bytes_to_long(cipherblock)
|
||||||
|
blocks.append(mticki)
|
||||||
|
|
||||||
|
# calculate this block's hash
|
||||||
|
hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size))
|
||||||
|
hashes.append(bytes_to_long(hi))
|
||||||
|
|
||||||
|
# Now calculate the last message block of the sequence 1..s'. This
|
||||||
|
# will contain the random session key XOR'd with all the hash blocks,
|
||||||
|
# so that for undigest(), once all the hash blocks are calculated, the
|
||||||
|
# session key can be trivially extracted. Calculating all the hash
|
||||||
|
# blocks requires that all the message blocks be received, thus the
|
||||||
|
# All-or-Nothing algorithm succeeds.
|
||||||
|
mtick_stick = bytes_to_long(key) ^ reduce(operator.xor, hashes)
|
||||||
|
blocks.append(mtick_stick)
|
||||||
|
|
||||||
|
# we convert the blocks to strings since in Python, byte sequences are
|
||||||
|
# always represented as strings. This is more consistent with the
|
||||||
|
# model that encryption and hash algorithms always operate on strings.
|
||||||
|
return [long_to_bytes(i,self.__ciphermodule.block_size) for i in blocks]
|
||||||
|
|
||||||
|
|
||||||
|
def undigest(self, blocks):
|
||||||
|
"""undigest(blocks : [string]) : string
|
||||||
|
|
||||||
|
Perform the reverse package transformation on a list of message
|
||||||
|
blocks. Note that the ciphermodule used for both transformations
|
||||||
|
must be the same. blocks is a list of strings of bit length
|
||||||
|
equal to the ciphermodule's block_size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# better have at least 2 blocks, for the padbytes package and the hash
|
||||||
|
# block accumulator
|
||||||
|
if len(blocks) < 2:
|
||||||
|
raise ValueError("List must be at least length 2.")
|
||||||
|
|
||||||
|
# blocks is a list of strings. We need to deal with them as long
|
||||||
|
# integers
|
||||||
|
blocks = list(map(bytes_to_long, blocks))
|
||||||
|
|
||||||
|
# Calculate the well-known key, to which the hash blocks are
|
||||||
|
# encrypted, and create the hash cipher.
|
||||||
|
K0 = self.__K0digit * self.__key_size
|
||||||
|
hcipher = self.__newcipher(K0)
|
||||||
|
block_size = self.__ciphermodule.block_size
|
||||||
|
|
||||||
|
# Since we have all the blocks (or this method would have been called
|
||||||
|
# prematurely), we can calculate all the hash blocks.
|
||||||
|
hashes = []
|
||||||
|
for i in range(1, len(blocks)):
|
||||||
|
mticki = blocks[i-1] ^ i
|
||||||
|
hi = hcipher.encrypt(long_to_bytes(mticki, block_size))
|
||||||
|
hashes.append(bytes_to_long(hi))
|
||||||
|
|
||||||
|
# now we can calculate K' (key). remember the last block contains
|
||||||
|
# m's' which we don't include here
|
||||||
|
key = blocks[-1] ^ reduce(operator.xor, hashes)
|
||||||
|
|
||||||
|
# and now we can create the cipher object
|
||||||
|
mcipher = self.__newcipher(long_to_bytes(key, self.__key_size))
|
||||||
|
|
||||||
|
# And we can now decode the original message blocks
|
||||||
|
parts = []
|
||||||
|
for i in range(1, len(blocks)):
|
||||||
|
cipherblock = mcipher.encrypt(long_to_bytes(i, block_size))
|
||||||
|
mi = blocks[i-1] ^ bytes_to_long(cipherblock)
|
||||||
|
parts.append(mi)
|
||||||
|
|
||||||
|
# The last message block contains the number of pad bytes appended to
|
||||||
|
# the original text string, such that its length was an even multiple
|
||||||
|
# of the cipher's block_size. This number should be small enough that
|
||||||
|
# the conversion from long integer to integer should never overflow
|
||||||
|
padbytes = int(parts[-1])
|
||||||
|
text = b('').join(map(long_to_bytes, parts[:-1]))
|
||||||
|
return text[:-padbytes]
|
||||||
|
|
||||||
|
def _inventkey(self, key_size):
|
||||||
|
# Return key_size random bytes
|
||||||
|
from Crypto import Random
|
||||||
|
return Random.new().read(key_size)
|
||||||
|
|
||||||
|
def __newcipher(self, key):
|
||||||
|
if self.__mode is None and self.__IV is None:
|
||||||
|
return self.__ciphermodule.new(key)
|
||||||
|
elif self.__IV is None:
|
||||||
|
return self.__ciphermodule.new(key, self.__mode)
|
||||||
|
else:
|
||||||
|
return self.__ciphermodule.new(key, self.__mode, self.__IV)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
import getopt
|
||||||
|
import base64
|
||||||
|
|
||||||
|
usagemsg = '''\
|
||||||
|
Test module usage: %(program)s [-c cipher] [-l] [-h]
|
||||||
|
|
||||||
|
Where:
|
||||||
|
--cipher module
|
||||||
|
-c module
|
||||||
|
Cipher module to use. Default: %(ciphermodule)s
|
||||||
|
|
||||||
|
--aslong
|
||||||
|
-l
|
||||||
|
Print the encoded message blocks as long integers instead of base64
|
||||||
|
encoded strings
|
||||||
|
|
||||||
|
--help
|
||||||
|
-h
|
||||||
|
Print this help message
|
||||||
|
'''
|
||||||
|
|
||||||
|
ciphermodule = 'AES'
|
||||||
|
aslong = 0
|
||||||
|
|
||||||
|
def usage(code, msg=None):
|
||||||
|
if msg:
|
||||||
|
print(msg)
|
||||||
|
print(usagemsg % {'program': sys.argv[0],
|
||||||
|
'ciphermodule': ciphermodule})
|
||||||
|
sys.exit(code)
|
||||||
|
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:],
|
||||||
|
'c:l', ['cipher=', 'aslong'])
|
||||||
|
except getopt.error as msg:
|
||||||
|
usage(1, msg)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
usage(1, 'Too many arguments')
|
||||||
|
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt in ('-h', '--help'):
|
||||||
|
usage(0)
|
||||||
|
elif opt in ('-c', '--cipher'):
|
||||||
|
ciphermodule = arg
|
||||||
|
elif opt in ('-l', '--aslong'):
|
||||||
|
aslong = 1
|
||||||
|
|
||||||
|
# ugly hack to force __import__ to give us the end-path module
|
||||||
|
module = __import__('Crypto.Cipher.'+ciphermodule, None, None, ['new'])
|
||||||
|
|
||||||
|
x = AllOrNothing(module)
|
||||||
|
print('Original text:\n==========')
|
||||||
|
print(__doc__)
|
||||||
|
print('==========')
|
||||||
|
msgblocks = x.digest(b(__doc__))
|
||||||
|
print('message blocks:')
|
||||||
|
for i, blk in zip(list(range(len(msgblocks))), msgblocks):
|
||||||
|
# base64 adds a trailing newline
|
||||||
|
print(' %3d' % i, end=' ')
|
||||||
|
if aslong:
|
||||||
|
print(bytes_to_long(blk))
|
||||||
|
else:
|
||||||
|
print(base64.encodestring(blk)[:-1])
|
||||||
|
#
|
||||||
|
# get a new undigest-only object so there's no leakage
|
||||||
|
y = AllOrNothing(module)
|
||||||
|
text = y.undigest(msgblocks)
|
||||||
|
if text == b(__doc__):
|
||||||
|
print('They match!')
|
||||||
|
else:
|
||||||
|
print('They differ!')
|
245
Lib/site-packages/Crypto/Protocol/Chaffing.py
Normal file
245
Lib/site-packages/Crypto/Protocol/Chaffing.py
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
#
|
||||||
|
# Chaffing.py : chaffing & winnowing support
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# Written by Andrew M. Kuchling, Barry A. Warsaw, and others
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
"""This file implements the chaffing algorithm.
|
||||||
|
|
||||||
|
Winnowing and chaffing is a technique for enhancing privacy without requiring
|
||||||
|
strong encryption. In short, the technique takes a set of authenticated
|
||||||
|
message blocks (the wheat) and adds a number of chaff blocks which have
|
||||||
|
randomly chosen data and MAC fields. This means that to an adversary, the
|
||||||
|
chaff blocks look as valid as the wheat blocks, and so the authentication
|
||||||
|
would have to be performed on every block. By tailoring the number of chaff
|
||||||
|
blocks added to the message, the sender can make breaking the message
|
||||||
|
computationally infeasible. There are many other interesting properties of
|
||||||
|
the winnow/chaff technique.
|
||||||
|
|
||||||
|
For example, say Alice is sending a message to Bob. She packetizes the
|
||||||
|
message and performs an all-or-nothing transformation on the packets. Then
|
||||||
|
she authenticates each packet with a message authentication code (MAC). The
|
||||||
|
MAC is a hash of the data packet, and there is a secret key which she must
|
||||||
|
share with Bob (key distribution is an exercise left to the reader). She then
|
||||||
|
adds a serial number to each packet, and sends the packets to Bob.
|
||||||
|
|
||||||
|
Bob receives the packets, and using the shared secret authentication key,
|
||||||
|
authenticates the MACs for each packet. Those packets that have bad MACs are
|
||||||
|
simply discarded. The remainder are sorted by serial number, and passed
|
||||||
|
through the reverse all-or-nothing transform. The transform means that an
|
||||||
|
eavesdropper (say Eve) must acquire all the packets before any of the data can
|
||||||
|
be read. If even one packet is missing, the data is useless.
|
||||||
|
|
||||||
|
There's one twist: by adding chaff packets, Alice and Bob can make Eve's job
|
||||||
|
much harder, since Eve now has to break the shared secret key, or try every
|
||||||
|
combination of wheat and chaff packet to read any of the message. The cool
|
||||||
|
thing is that Bob doesn't need to add any additional code; the chaff packets
|
||||||
|
are already filtered out because their MACs don't match (in all likelihood --
|
||||||
|
since the data and MACs for the chaff packets are randomly chosen it is
|
||||||
|
possible, but very unlikely that a chaff MAC will match the chaff data). And
|
||||||
|
Alice need not even be the party adding the chaff! She could be completely
|
||||||
|
unaware that a third party, say Charles, is adding chaff packets to her
|
||||||
|
messages as they are transmitted.
|
||||||
|
|
||||||
|
For more information on winnowing and chaffing see this paper:
|
||||||
|
|
||||||
|
Ronald L. Rivest, "Chaffing and Winnowing: Confidentiality without Encryption"
|
||||||
|
http://theory.lcs.mit.edu/~rivest/chaffing.txt
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.number import bytes_to_long
|
||||||
|
|
||||||
|
class Chaff:
|
||||||
|
"""Class implementing the chaff adding algorithm.
|
||||||
|
|
||||||
|
Methods for subclasses:
|
||||||
|
|
||||||
|
_randnum(size):
|
||||||
|
Returns a randomly generated number with a byte-length equal
|
||||||
|
to size. Subclasses can use this to implement better random
|
||||||
|
data and MAC generating algorithms. The default algorithm is
|
||||||
|
probably not very cryptographically secure. It is most
|
||||||
|
important that the chaff data does not contain any patterns
|
||||||
|
that can be used to discern it from wheat data without running
|
||||||
|
the MAC.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, factor=1.0, blocksper=1):
|
||||||
|
"""Chaff(factor:float, blocksper:int)
|
||||||
|
|
||||||
|
factor is the number of message blocks to add chaff to,
|
||||||
|
expressed as a percentage between 0.0 and 1.0. blocksper is
|
||||||
|
the number of chaff blocks to include for each block being
|
||||||
|
chaffed. Thus the defaults add one chaff block to every
|
||||||
|
message block. By changing the defaults, you can adjust how
|
||||||
|
computationally difficult it could be for an adversary to
|
||||||
|
brute-force crack the message. The difficulty is expressed
|
||||||
|
as:
|
||||||
|
|
||||||
|
pow(blocksper, int(factor * number-of-blocks))
|
||||||
|
|
||||||
|
For ease of implementation, when factor < 1.0, only the first
|
||||||
|
int(factor*number-of-blocks) message blocks are chaffed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not (0.0<=factor<=1.0):
|
||||||
|
raise ValueError("'factor' must be between 0.0 and 1.0")
|
||||||
|
if blocksper < 0:
|
||||||
|
raise ValueError("'blocksper' must be zero or more")
|
||||||
|
|
||||||
|
self.__factor = factor
|
||||||
|
self.__blocksper = blocksper
|
||||||
|
|
||||||
|
|
||||||
|
def chaff(self, blocks):
|
||||||
|
"""chaff( [(serial-number:int, data:string, MAC:string)] )
|
||||||
|
: [(int, string, string)]
|
||||||
|
|
||||||
|
Add chaff to message blocks. blocks is a list of 3-tuples of the
|
||||||
|
form (serial-number, data, MAC).
|
||||||
|
|
||||||
|
Chaff is created by choosing a random number of the same
|
||||||
|
byte-length as data, and another random number of the same
|
||||||
|
byte-length as MAC. The message block's serial number is
|
||||||
|
placed on the chaff block and all the packet's chaff blocks
|
||||||
|
are randomly interspersed with the single wheat block. This
|
||||||
|
method then returns a list of 3-tuples of the same form.
|
||||||
|
Chaffed blocks will contain multiple instances of 3-tuples
|
||||||
|
with the same serial number, but the only way to figure out
|
||||||
|
which blocks are wheat and which are chaff is to perform the
|
||||||
|
MAC hash and compare values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
chaffedblocks = []
|
||||||
|
|
||||||
|
# count is the number of blocks to add chaff to. blocksper is the
|
||||||
|
# number of chaff blocks to add per message block that is being
|
||||||
|
# chaffed.
|
||||||
|
count = len(blocks) * self.__factor
|
||||||
|
blocksper = list(range(self.__blocksper))
|
||||||
|
for i, wheat in zip(list(range(len(blocks))), blocks):
|
||||||
|
# it shouldn't matter which of the n blocks we add chaff to, so for
|
||||||
|
# ease of implementation, we'll just add them to the first count
|
||||||
|
# blocks
|
||||||
|
if i < count:
|
||||||
|
serial, data, mac = wheat
|
||||||
|
datasize = len(data)
|
||||||
|
macsize = len(mac)
|
||||||
|
addwheat = 1
|
||||||
|
# add chaff to this block
|
||||||
|
for j in blocksper:
|
||||||
|
import sys
|
||||||
|
chaffdata = self._randnum(datasize)
|
||||||
|
chaffmac = self._randnum(macsize)
|
||||||
|
chaff = (serial, chaffdata, chaffmac)
|
||||||
|
# mix up the order, if the 5th bit is on then put the
|
||||||
|
# wheat on the list
|
||||||
|
if addwheat and bytes_to_long(self._randnum(16)) & 0x40:
|
||||||
|
chaffedblocks.append(wheat)
|
||||||
|
addwheat = 0
|
||||||
|
chaffedblocks.append(chaff)
|
||||||
|
if addwheat:
|
||||||
|
chaffedblocks.append(wheat)
|
||||||
|
else:
|
||||||
|
# just add the wheat
|
||||||
|
chaffedblocks.append(wheat)
|
||||||
|
return chaffedblocks
|
||||||
|
|
||||||
|
def _randnum(self, size):
|
||||||
|
from Crypto import Random
|
||||||
|
return Random.new().read(size)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
text = """\
|
||||||
|
We hold these truths to be self-evident, that all men are created equal, that
|
||||||
|
they are endowed by their Creator with certain unalienable Rights, that among
|
||||||
|
these are Life, Liberty, and the pursuit of Happiness. That to secure these
|
||||||
|
rights, Governments are instituted among Men, deriving their just powers from
|
||||||
|
the consent of the governed. That whenever any Form of Government becomes
|
||||||
|
destructive of these ends, it is the Right of the People to alter or to
|
||||||
|
abolish it, and to institute new Government, laying its foundation on such
|
||||||
|
principles and organizing its powers in such form, as to them shall seem most
|
||||||
|
likely to effect their Safety and Happiness.
|
||||||
|
"""
|
||||||
|
print('Original text:\n==========')
|
||||||
|
print(text)
|
||||||
|
print('==========')
|
||||||
|
|
||||||
|
# first transform the text into packets
|
||||||
|
blocks = [] ; size = 40
|
||||||
|
for i in range(0, len(text), size):
|
||||||
|
blocks.append( text[i:i+size] )
|
||||||
|
|
||||||
|
# now get MACs for all the text blocks. The key is obvious...
|
||||||
|
print('Calculating MACs...')
|
||||||
|
from Crypto.Hash import HMAC, SHA
|
||||||
|
key = 'Jefferson'
|
||||||
|
macs = [HMAC.new(key, block, digestmod=SHA).digest()
|
||||||
|
for block in blocks]
|
||||||
|
|
||||||
|
assert len(blocks) == len(macs)
|
||||||
|
|
||||||
|
# put these into a form acceptable as input to the chaffing procedure
|
||||||
|
source = []
|
||||||
|
m = list(zip(list(range(len(blocks))), blocks, macs))
|
||||||
|
print(m)
|
||||||
|
for i, data, mac in m:
|
||||||
|
source.append((i, data, mac))
|
||||||
|
|
||||||
|
# now chaff these
|
||||||
|
print('Adding chaff...')
|
||||||
|
c = Chaff(factor=0.5, blocksper=2)
|
||||||
|
chaffed = c.chaff(source)
|
||||||
|
|
||||||
|
from base64 import encodestring
|
||||||
|
|
||||||
|
# print the chaffed message blocks. meanwhile, separate the wheat from
|
||||||
|
# the chaff
|
||||||
|
|
||||||
|
wheat = []
|
||||||
|
print('chaffed message blocks:')
|
||||||
|
for i, data, mac in chaffed:
|
||||||
|
# do the authentication
|
||||||
|
h = HMAC.new(key, data, digestmod=SHA)
|
||||||
|
pmac = h.digest()
|
||||||
|
if pmac == mac:
|
||||||
|
tag = '-->'
|
||||||
|
wheat.append(data)
|
||||||
|
else:
|
||||||
|
tag = ' '
|
||||||
|
# base64 adds a trailing newline
|
||||||
|
print(tag, '%3d' % i, \
|
||||||
|
repr(data), encodestring(mac)[:-1])
|
||||||
|
|
||||||
|
# now decode the message packets and check it against the original text
|
||||||
|
print('Undigesting wheat...')
|
||||||
|
# PY3K: This is meant to be text, do not change to bytes (data)
|
||||||
|
newtext = "".join(wheat)
|
||||||
|
if newtext == text:
|
||||||
|
print('They match!')
|
||||||
|
else:
|
||||||
|
print('They differ!')
|
123
Lib/site-packages/Crypto/Protocol/KDF.py
Normal file
123
Lib/site-packages/Crypto/Protocol/KDF.py
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
#
|
||||||
|
# KDF.py : a collection of Key Derivation Functions
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""This file contains a collection of standard key derivation functions.
|
||||||
|
|
||||||
|
A key derivation function derives one or more secondary secret keys from
|
||||||
|
one primary secret (a master key or a pass phrase).
|
||||||
|
|
||||||
|
This is typically done to insulate the secondary keys from each other,
|
||||||
|
to avoid that leakage of a secondary key compromises the security of the
|
||||||
|
master key, or to thwart attacks on pass phrases (e.g. via rainbow tables).
|
||||||
|
|
||||||
|
:undocumented: __revision__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import math
|
||||||
|
import struct
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Hash import SHA as SHA1, HMAC
|
||||||
|
from Crypto.Util.strxor import strxor
|
||||||
|
|
||||||
|
def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None):
|
||||||
|
"""Derive one key from a password (or passphrase).
|
||||||
|
|
||||||
|
This function performs key derivation according an old version of
|
||||||
|
the PKCS#5 standard (v1.5).
|
||||||
|
|
||||||
|
This algorithm is called ``PBKDF1``. Even though it is still described
|
||||||
|
in the latest version of the PKCS#5 standard (version 2, or RFC2898),
|
||||||
|
newer applications should use the more secure and versatile `PBKDF2` instead.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
password : string
|
||||||
|
The secret password or pass phrase to generate the key from.
|
||||||
|
salt : byte string
|
||||||
|
An 8 byte string to use for better protection from dictionary attacks.
|
||||||
|
This value does not need to be kept secret, but it should be randomly
|
||||||
|
chosen for each derivation.
|
||||||
|
dkLen : integer
|
||||||
|
The length of the desired key. Default is 16 bytes, suitable for instance for `Crypto.Cipher.AES`.
|
||||||
|
count : integer
|
||||||
|
The number of iterations to carry out. It's recommended to use at least 1000.
|
||||||
|
hashAlgo : module
|
||||||
|
The hash algorithm to use, as a module or an object from the `Crypto.Hash` package.
|
||||||
|
The digest length must be no shorter than ``dkLen``.
|
||||||
|
The default algorithm is `SHA1`.
|
||||||
|
|
||||||
|
:Return: A byte string of length `dkLen` that can be used as key.
|
||||||
|
"""
|
||||||
|
if not hashAlgo:
|
||||||
|
hashAlgo = SHA1
|
||||||
|
password = tobytes(password)
|
||||||
|
pHash = hashAlgo.new(password+salt)
|
||||||
|
digest = pHash.digest_size
|
||||||
|
if dkLen>digest:
|
||||||
|
raise ValueError("Selected hash algorithm has a too short digest (%d bytes)." % digest)
|
||||||
|
if len(salt)!=8:
|
||||||
|
raise ValueError("Salt is not 8 bytes long.")
|
||||||
|
for i in range(count-1):
|
||||||
|
pHash = pHash.new(pHash.digest())
|
||||||
|
return pHash.digest()[:dkLen]
|
||||||
|
|
||||||
|
def PBKDF2(password, salt, dkLen=16, count=1000, prf=None):
|
||||||
|
"""Derive one or more keys from a password (or passphrase).
|
||||||
|
|
||||||
|
This performs key derivation according to the PKCS#5 standard (v2.0),
|
||||||
|
by means of the ``PBKDF2`` algorithm.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
password : string
|
||||||
|
The secret password or pass phrase to generate the key from.
|
||||||
|
salt : string
|
||||||
|
A string to use for better protection from dictionary attacks.
|
||||||
|
This value does not need to be kept secret, but it should be randomly
|
||||||
|
chosen for each derivation. It is recommended to be at least 8 bytes long.
|
||||||
|
dkLen : integer
|
||||||
|
The cumulative length of the desired keys. Default is 16 bytes, suitable for instance for `Crypto.Cipher.AES`.
|
||||||
|
count : integer
|
||||||
|
The number of iterations to carry out. It's recommended to use at least 1000.
|
||||||
|
prf : callable
|
||||||
|
A pseudorandom function. It must be a function that returns a pseudorandom string
|
||||||
|
from two parameters: a secret and a salt. If not specified, HMAC-SHA1 is used.
|
||||||
|
|
||||||
|
:Return: A byte string of length `dkLen` that can be used as key material.
|
||||||
|
If you wanted multiple keys, just break up this string into segments of the desired length.
|
||||||
|
"""
|
||||||
|
password = tobytes(password)
|
||||||
|
if prf is None:
|
||||||
|
prf = lambda p,s: HMAC.new(p,s,SHA1).digest()
|
||||||
|
key = b('')
|
||||||
|
i = 1
|
||||||
|
while len(key)<dkLen:
|
||||||
|
U = previousU = prf(password,salt+struct.pack(">I", i))
|
||||||
|
for j in range(count-1):
|
||||||
|
previousU = t = prf(password,previousU)
|
||||||
|
U = strxor(U,t)
|
||||||
|
key += U
|
||||||
|
i = i + 1
|
||||||
|
return key[:dkLen]
|
||||||
|
|
41
Lib/site-packages/Crypto/Protocol/__init__.py
Normal file
41
Lib/site-packages/Crypto/Protocol/__init__.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Cryptographic protocols
|
||||||
|
|
||||||
|
Implements various cryptographic protocols. (Don't expect to find
|
||||||
|
network protocols here.)
|
||||||
|
|
||||||
|
Crypto.Protocol.AllOrNothing
|
||||||
|
Transforms a message into a set of message blocks, such that the blocks
|
||||||
|
can be recombined to get the message back.
|
||||||
|
|
||||||
|
Crypto.Protocol.Chaffing
|
||||||
|
Takes a set of authenticated message blocks (the wheat) and adds a number
|
||||||
|
of randomly generated blocks (the chaff).
|
||||||
|
|
||||||
|
Crypto.Protocol.KDF
|
||||||
|
A collection of standard key derivation functions.
|
||||||
|
|
||||||
|
:undocumented: __revision__
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['AllOrNothing', 'Chaffing', 'KDF']
|
||||||
|
__revision__ = "$Id$"
|
379
Lib/site-packages/Crypto/PublicKey/DSA.py
Normal file
379
Lib/site-packages/Crypto/PublicKey/DSA.py
Normal file
|
@ -0,0 +1,379 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# PublicKey/DSA.py : DSA signature primitive
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""DSA public-key signature algorithm.
|
||||||
|
|
||||||
|
DSA_ is a widespread public-key signature algorithm. Its security is
|
||||||
|
based on the discrete logarithm problem (DLP_). Given a cyclic
|
||||||
|
group, a generator *g*, and an element *h*, it is hard
|
||||||
|
to find an integer *x* such that *g^x = h*. The problem is believed
|
||||||
|
to be difficult, and it has been proved such (and therefore secure) for
|
||||||
|
more than 30 years.
|
||||||
|
|
||||||
|
The group is actually a sub-group over the integers modulo *p*, with *p* prime.
|
||||||
|
The sub-group order is *q*, which is prime too; it always holds that *(p-1)* is a multiple of *q*.
|
||||||
|
The cryptographic strength is linked to the magnitude of *p* and *q*.
|
||||||
|
The signer holds a value *x* (*0<x<q-1*) as private key, and its public
|
||||||
|
key (*y* where *y=g^x mod p*) is distributed.
|
||||||
|
|
||||||
|
In 2012, a sufficient size is deemed to be 2048 bits for *p* and 256 bits for *q*.
|
||||||
|
For more information, see the most recent ECRYPT_ report.
|
||||||
|
|
||||||
|
DSA is reasonably secure for new designs.
|
||||||
|
|
||||||
|
The algorithm can only be used for authentication (digital signature).
|
||||||
|
DSA cannot be used for confidentiality (encryption).
|
||||||
|
|
||||||
|
The values *(p,q,g)* are called *domain parameters*;
|
||||||
|
they are not sensitive but must be shared by both parties (the signer and the verifier).
|
||||||
|
Different signers can share the same domain parameters with no security
|
||||||
|
concerns.
|
||||||
|
|
||||||
|
The DSA signature is twice as big as the size of *q* (64 bytes if *q* is 256 bit
|
||||||
|
long).
|
||||||
|
|
||||||
|
This module provides facilities for generating new DSA keys and for constructing
|
||||||
|
them from known components. DSA keys allows you to perform basic signing and
|
||||||
|
verification.
|
||||||
|
|
||||||
|
>>> from Crypto.Random import random
|
||||||
|
>>> from Crypto.PublicKey import DSA
|
||||||
|
>>> from Crypto.Hash import SHA
|
||||||
|
>>>
|
||||||
|
>>> message = "Hello"
|
||||||
|
>>> key = DSA.generate(1024)
|
||||||
|
>>> h = SHA.new(message).digest()
|
||||||
|
>>> k = random.StrongRandom().randint(1,key.q-1)
|
||||||
|
>>> sig = key.sign(h,k)
|
||||||
|
>>> ...
|
||||||
|
>>> if key.verify(h,sig):
|
||||||
|
>>> print "OK"
|
||||||
|
>>> else:
|
||||||
|
>>> print "Incorrect signature"
|
||||||
|
|
||||||
|
.. _DSA: http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
|
||||||
|
.. _DLP: http://www.cosic.esat.kuleuven.be/publications/talk-78.pdf
|
||||||
|
.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['generate', 'construct', 'error', 'DSAImplementation', '_DSAobj']
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
|
||||||
|
from Crypto.PublicKey import _DSA, _slowmath, pubkey
|
||||||
|
from Crypto import Random
|
||||||
|
|
||||||
|
try:
|
||||||
|
from Crypto.PublicKey import _fastmath
|
||||||
|
except ImportError:
|
||||||
|
_fastmath = None
|
||||||
|
|
||||||
|
class _DSAobj(pubkey.pubkey):
|
||||||
|
"""Class defining an actual DSA key.
|
||||||
|
|
||||||
|
:undocumented: __getstate__, __setstate__, __repr__, __getattr__
|
||||||
|
"""
|
||||||
|
#: Dictionary of DSA parameters.
|
||||||
|
#:
|
||||||
|
#: A public key will only have the following entries:
|
||||||
|
#:
|
||||||
|
#: - **y**, the public key.
|
||||||
|
#: - **g**, the generator.
|
||||||
|
#: - **p**, the modulus.
|
||||||
|
#: - **q**, the order of the sub-group.
|
||||||
|
#:
|
||||||
|
#: A private key will also have:
|
||||||
|
#:
|
||||||
|
#: - **x**, the private key.
|
||||||
|
keydata = ['y', 'g', 'p', 'q', 'x']
|
||||||
|
|
||||||
|
def __init__(self, implementation, key):
|
||||||
|
self.implementation = implementation
|
||||||
|
self.key = key
|
||||||
|
|
||||||
|
def __getattr__(self, attrname):
|
||||||
|
if attrname in self.keydata:
|
||||||
|
# For backward compatibility, allow the user to get (not set) the
|
||||||
|
# DSA key parameters directly from this object.
|
||||||
|
return getattr(self.key, attrname)
|
||||||
|
else:
|
||||||
|
raise AttributeError("%s object has no %r attribute" % (self.__class__.__name__, attrname,))
|
||||||
|
|
||||||
|
def sign(self, M, K):
|
||||||
|
"""Sign a piece of data with DSA.
|
||||||
|
|
||||||
|
:Parameter M: The piece of data to sign with DSA. It may
|
||||||
|
not be longer in bit size than the sub-group order (*q*).
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter K: A secret number, chosen randomly in the closed
|
||||||
|
range *[1,q-1]*.
|
||||||
|
:Type K: long (recommended) or byte string (not recommended)
|
||||||
|
|
||||||
|
:attention: selection of *K* is crucial for security. Generating a
|
||||||
|
random number larger than *q* and taking the modulus by *q* is
|
||||||
|
**not** secure, since smaller values will occur more frequently.
|
||||||
|
Generating a random number systematically smaller than *q-1*
|
||||||
|
(e.g. *floor((q-1)/8)* random bytes) is also **not** secure. In general,
|
||||||
|
it shall not be possible for an attacker to know the value of `any
|
||||||
|
bit of K`__.
|
||||||
|
|
||||||
|
:attention: The number *K* shall not be reused for any other
|
||||||
|
operation and shall be discarded immediately.
|
||||||
|
|
||||||
|
:attention: M must be a digest cryptographic hash, otherwise
|
||||||
|
an attacker may mount an existential forgery attack.
|
||||||
|
|
||||||
|
:Return: A tuple with 2 longs.
|
||||||
|
|
||||||
|
.. __: http://www.di.ens.fr/~pnguyen/pub_NgSh00.htm
|
||||||
|
"""
|
||||||
|
return pubkey.pubkey.sign(self, M, K)
|
||||||
|
|
||||||
|
def verify(self, M, signature):
|
||||||
|
"""Verify the validity of a DSA signature.
|
||||||
|
|
||||||
|
:Parameter M: The expected message.
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter signature: The DSA signature to verify.
|
||||||
|
:Type signature: A tuple with 2 longs as return by `sign`
|
||||||
|
|
||||||
|
:Return: True if the signature is correct, False otherwise.
|
||||||
|
"""
|
||||||
|
return pubkey.pubkey.verify(self, M, signature)
|
||||||
|
|
||||||
|
def _encrypt(self, c, K):
|
||||||
|
raise TypeError("DSA cannot encrypt")
|
||||||
|
|
||||||
|
def _decrypt(self, c):
|
||||||
|
raise TypeError("DSA cannot decrypt")
|
||||||
|
|
||||||
|
def _blind(self, m, r):
|
||||||
|
raise TypeError("DSA cannot blind")
|
||||||
|
|
||||||
|
def _unblind(self, m, r):
|
||||||
|
raise TypeError("DSA cannot unblind")
|
||||||
|
|
||||||
|
def _sign(self, m, k):
|
||||||
|
return self.key._sign(m, k)
|
||||||
|
|
||||||
|
def _verify(self, m, sig):
|
||||||
|
(r, s) = sig
|
||||||
|
return self.key._verify(m, r, s)
|
||||||
|
|
||||||
|
def has_private(self):
|
||||||
|
return self.key.has_private()
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return self.key.size()
|
||||||
|
|
||||||
|
def can_blind(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def can_encrypt(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def can_sign(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def publickey(self):
|
||||||
|
return self.implementation.construct((self.key.y, self.key.g, self.key.p, self.key.q))
|
||||||
|
|
||||||
|
def __getstate__(self):
|
||||||
|
d = {}
|
||||||
|
for k in self.keydata:
|
||||||
|
try:
|
||||||
|
d[k] = getattr(self.key, k)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
return d
|
||||||
|
|
||||||
|
def __setstate__(self, d):
|
||||||
|
if not hasattr(self, 'implementation'):
|
||||||
|
self.implementation = DSAImplementation()
|
||||||
|
t = []
|
||||||
|
for k in self.keydata:
|
||||||
|
if k not in d:
|
||||||
|
break
|
||||||
|
t.append(d[k])
|
||||||
|
self.key = self.implementation._math.dsa_construct(*tuple(t))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
attrs = []
|
||||||
|
for k in self.keydata:
|
||||||
|
if k == 'p':
|
||||||
|
attrs.append("p(%d)" % (self.size()+1,))
|
||||||
|
elif hasattr(self.key, k):
|
||||||
|
attrs.append(k)
|
||||||
|
if self.has_private():
|
||||||
|
attrs.append("private")
|
||||||
|
# PY3K: This is meant to be text, do not change to bytes (data)
|
||||||
|
return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
|
||||||
|
|
||||||
|
class DSAImplementation(object):
|
||||||
|
"""
|
||||||
|
A DSA key factory.
|
||||||
|
|
||||||
|
This class is only internally used to implement the methods of the
|
||||||
|
`Crypto.PublicKey.DSA` module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
"""Create a new DSA key factory.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
use_fast_math : bool
|
||||||
|
Specify which mathematic library to use:
|
||||||
|
|
||||||
|
- *None* (default). Use fastest math available.
|
||||||
|
- *True* . Use fast math.
|
||||||
|
- *False* . Use slow math.
|
||||||
|
default_randfunc : callable
|
||||||
|
Specify how to collect random data:
|
||||||
|
|
||||||
|
- *None* (default). Use Random.new().read().
|
||||||
|
- not *None* . Use the specified function directly.
|
||||||
|
:Raise RuntimeError:
|
||||||
|
When **use_fast_math** =True but fast math is not available.
|
||||||
|
"""
|
||||||
|
use_fast_math = kwargs.get('use_fast_math', None)
|
||||||
|
if use_fast_math is None: # Automatic
|
||||||
|
if _fastmath is not None:
|
||||||
|
self._math = _fastmath
|
||||||
|
else:
|
||||||
|
self._math = _slowmath
|
||||||
|
|
||||||
|
elif use_fast_math: # Explicitly select fast math
|
||||||
|
if _fastmath is not None:
|
||||||
|
self._math = _fastmath
|
||||||
|
else:
|
||||||
|
raise RuntimeError("fast math module not available")
|
||||||
|
|
||||||
|
else: # Explicitly select slow math
|
||||||
|
self._math = _slowmath
|
||||||
|
|
||||||
|
self.error = self._math.error
|
||||||
|
|
||||||
|
# 'default_randfunc' parameter:
|
||||||
|
# None (default) - use Random.new().read
|
||||||
|
# not None - use the specified function
|
||||||
|
self._default_randfunc = kwargs.get('default_randfunc', None)
|
||||||
|
self._current_randfunc = None
|
||||||
|
|
||||||
|
def _get_randfunc(self, randfunc):
|
||||||
|
if randfunc is not None:
|
||||||
|
return randfunc
|
||||||
|
elif self._current_randfunc is None:
|
||||||
|
self._current_randfunc = Random.new().read
|
||||||
|
return self._current_randfunc
|
||||||
|
|
||||||
|
def generate(self, bits, randfunc=None, progress_func=None):
|
||||||
|
"""Randomly generate a fresh, new DSA key.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
bits : int
|
||||||
|
Key length, or size (in bits) of the DSA modulus
|
||||||
|
*p*.
|
||||||
|
It must be a multiple of 64, in the closed
|
||||||
|
interval [512,1024].
|
||||||
|
randfunc : callable
|
||||||
|
Random number generation function; it should accept
|
||||||
|
a single integer N and return a string of random data
|
||||||
|
N bytes long.
|
||||||
|
If not specified, a new one will be instantiated
|
||||||
|
from ``Crypto.Random``.
|
||||||
|
progress_func : callable
|
||||||
|
Optional function that will be called with a short string
|
||||||
|
containing the key parameter currently being generated;
|
||||||
|
it's useful for interactive applications where a user is
|
||||||
|
waiting for a key to be generated.
|
||||||
|
|
||||||
|
:attention: You should always use a cryptographically secure random number generator,
|
||||||
|
such as the one defined in the ``Crypto.Random`` module; **don't** just use the
|
||||||
|
current time and the ``random`` module.
|
||||||
|
|
||||||
|
:Return: A DSA key object (`_DSAobj`).
|
||||||
|
|
||||||
|
:Raise ValueError:
|
||||||
|
When **bits** is too little, too big, or not a multiple of 64.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Check against FIPS 186-2, which says that the size of the prime p
|
||||||
|
# must be a multiple of 64 bits between 512 and 1024
|
||||||
|
for i in (0, 1, 2, 3, 4, 5, 6, 7, 8):
|
||||||
|
if bits == 512 + 64*i:
|
||||||
|
return self._generate(bits, randfunc, progress_func)
|
||||||
|
|
||||||
|
# The March 2006 draft of FIPS 186-3 also allows 2048 and 3072-bit
|
||||||
|
# primes, but only with longer q values. Since the current DSA
|
||||||
|
# implementation only supports a 160-bit q, we don't support larger
|
||||||
|
# values.
|
||||||
|
raise ValueError("Number of bits in p must be a multiple of 64 between 512 and 1024, not %d bits" % (bits,))
|
||||||
|
|
||||||
|
def _generate(self, bits, randfunc=None, progress_func=None):
|
||||||
|
rf = self._get_randfunc(randfunc)
|
||||||
|
obj = _DSA.generate_py(bits, rf, progress_func) # TODO: Don't use legacy _DSA module
|
||||||
|
key = self._math.dsa_construct(obj.y, obj.g, obj.p, obj.q, obj.x)
|
||||||
|
return _DSAobj(self, key)
|
||||||
|
|
||||||
|
def construct(self, tup):
|
||||||
|
"""Construct a DSA key from a tuple of valid DSA components.
|
||||||
|
|
||||||
|
The modulus *p* must be a prime.
|
||||||
|
|
||||||
|
The following equations must apply:
|
||||||
|
|
||||||
|
- p-1 = 0 mod q
|
||||||
|
- g^x = y mod p
|
||||||
|
- 0 < x < q
|
||||||
|
- 1 < g < p
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
tup : tuple
|
||||||
|
A tuple of long integers, with 4 or 5 items
|
||||||
|
in the following order:
|
||||||
|
|
||||||
|
1. Public key (*y*).
|
||||||
|
2. Sub-group generator (*g*).
|
||||||
|
3. Modulus, finite field order (*p*).
|
||||||
|
4. Sub-group order (*q*).
|
||||||
|
5. Private key (*x*). Optional.
|
||||||
|
|
||||||
|
:Return: A DSA key object (`_DSAobj`).
|
||||||
|
"""
|
||||||
|
key = self._math.dsa_construct(*tup)
|
||||||
|
return _DSAobj(self, key)
|
||||||
|
|
||||||
|
_impl = DSAImplementation()
|
||||||
|
generate = _impl.generate
|
||||||
|
construct = _impl.construct
|
||||||
|
error = _impl.error
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||||
|
|
373
Lib/site-packages/Crypto/PublicKey/ElGamal.py
Normal file
373
Lib/site-packages/Crypto/PublicKey/ElGamal.py
Normal file
|
@ -0,0 +1,373 @@
|
||||||
|
#
|
||||||
|
# ElGamal.py : ElGamal encryption/decryption and signatures
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# Originally written by: A.M. Kuchling
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""ElGamal public-key algorithm (randomized encryption and signature).
|
||||||
|
|
||||||
|
Signature algorithm
|
||||||
|
-------------------
|
||||||
|
The security of the ElGamal signature scheme is based (like DSA) on the discrete
|
||||||
|
logarithm problem (DLP_). Given a cyclic group, a generator *g*,
|
||||||
|
and an element *h*, it is hard to find an integer *x* such that *g^x = h*.
|
||||||
|
|
||||||
|
The group is the largest multiplicative sub-group of the integers modulo *p*,
|
||||||
|
with *p* prime.
|
||||||
|
The signer holds a value *x* (*0<x<p-1*) as private key, and its public
|
||||||
|
key (*y* where *y=g^x mod p*) is distributed.
|
||||||
|
|
||||||
|
The ElGamal signature is twice as big as *p*.
|
||||||
|
|
||||||
|
Encryption algorithm
|
||||||
|
--------------------
|
||||||
|
The security of the ElGamal encryption scheme is based on the computational
|
||||||
|
Diffie-Hellman problem (CDH_). Given a cyclic group, a generator *g*,
|
||||||
|
and two integers *a* and *b*, it is difficult to find
|
||||||
|
the element *g^{ab}* when only *g^a* and *g^b* are known, and not *a* and *b*.
|
||||||
|
|
||||||
|
As before, the group is the largest multiplicative sub-group of the integers
|
||||||
|
modulo *p*, with *p* prime.
|
||||||
|
The receiver holds a value *a* (*0<a<p-1*) as private key, and its public key
|
||||||
|
(*b* where *b*=g^a*) is given to the sender.
|
||||||
|
|
||||||
|
The ElGamal ciphertext is twice as big as *p*.
|
||||||
|
|
||||||
|
Domain parameters
|
||||||
|
-----------------
|
||||||
|
For both signature and encryption schemes, the values *(p,g)* are called
|
||||||
|
*domain parameters*.
|
||||||
|
They are not sensitive but must be distributed to all parties (senders and
|
||||||
|
receivers).
|
||||||
|
Different signers can share the same domain parameters, as can
|
||||||
|
different recipients of encrypted messages.
|
||||||
|
|
||||||
|
Security
|
||||||
|
--------
|
||||||
|
Both DLP and CDH problem are believed to be difficult, and they have been proved
|
||||||
|
such (and therefore secure) for more than 30 years.
|
||||||
|
|
||||||
|
The cryptographic strength is linked to the magnitude of *p*.
|
||||||
|
In 2012, a sufficient size for *p* is deemed to be 2048 bits.
|
||||||
|
For more information, see the most recent ECRYPT_ report.
|
||||||
|
|
||||||
|
Even though ElGamal algorithms are in theory reasonably secure for new designs,
|
||||||
|
in practice there are no real good reasons for using them.
|
||||||
|
The signature is four times larger than the equivalent DSA, and the ciphertext
|
||||||
|
is two times larger than the equivalent RSA.
|
||||||
|
|
||||||
|
Functionality
|
||||||
|
-------------
|
||||||
|
This module provides facilities for generating new ElGamal keys and for constructing
|
||||||
|
them from known components. ElGamal keys allows you to perform basic signing,
|
||||||
|
verification, encryption, and decryption.
|
||||||
|
|
||||||
|
>>> from Crypto import Random
|
||||||
|
>>> from Crypto.Random import random
|
||||||
|
>>> from Crypto.PublicKey import ElGamal
|
||||||
|
>>> from Crypto.Util.number import GCD
|
||||||
|
>>> from Crypto.Hash import SHA
|
||||||
|
>>>
|
||||||
|
>>> message = "Hello"
|
||||||
|
>>> key = ElGamal.generate(1024, Random.new().read)
|
||||||
|
>>> h = SHA.new(message).digest()
|
||||||
|
>>> while 1:
|
||||||
|
>>> k = random.StrongRandom().randint(1,key.p-1)
|
||||||
|
>>> if GCD(k,key.p-1)==1: break
|
||||||
|
>>> sig = key.sign(h,k)
|
||||||
|
>>> ...
|
||||||
|
>>> if key.verify(h,sig):
|
||||||
|
>>> print "OK"
|
||||||
|
>>> else:
|
||||||
|
>>> print "Incorrect signature"
|
||||||
|
|
||||||
|
.. _DLP: http://www.cosic.esat.kuleuven.be/publications/talk-78.pdf
|
||||||
|
.. _CDH: http://en.wikipedia.org/wiki/Computational_Diffie%E2%80%93Hellman_assumption
|
||||||
|
.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['generate', 'construct', 'error', 'ElGamalobj']
|
||||||
|
|
||||||
|
from Crypto.PublicKey.pubkey import *
|
||||||
|
from Crypto.Util import number
|
||||||
|
|
||||||
|
class error (Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Generate an ElGamal key with N bits
|
||||||
|
def generate(bits, randfunc, progress_func=None):
|
||||||
|
"""Randomly generate a fresh, new ElGamal key.
|
||||||
|
|
||||||
|
The key will be safe for use for both encryption and signature
|
||||||
|
(although it should be used for **only one** purpose).
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
bits : int
|
||||||
|
Key length, or size (in bits) of the modulus *p*.
|
||||||
|
Recommended value is 2048.
|
||||||
|
randfunc : callable
|
||||||
|
Random number generation function; it should accept
|
||||||
|
a single integer N and return a string of random data
|
||||||
|
N bytes long.
|
||||||
|
progress_func : callable
|
||||||
|
Optional function that will be called with a short string
|
||||||
|
containing the key parameter currently being generated;
|
||||||
|
it's useful for interactive applications where a user is
|
||||||
|
waiting for a key to be generated.
|
||||||
|
|
||||||
|
:attention: You should always use a cryptographically secure random number generator,
|
||||||
|
such as the one defined in the ``Crypto.Random`` module; **don't** just use the
|
||||||
|
current time and the ``random`` module.
|
||||||
|
|
||||||
|
:Return: An ElGamal key object (`ElGamalobj`).
|
||||||
|
"""
|
||||||
|
obj=ElGamalobj()
|
||||||
|
# Generate a safe prime p
|
||||||
|
# See Algorithm 4.86 in Handbook of Applied Cryptography
|
||||||
|
if progress_func:
|
||||||
|
progress_func('p\n')
|
||||||
|
while 1:
|
||||||
|
q = bignum(getPrime(bits-1, randfunc))
|
||||||
|
obj.p = 2*q+1
|
||||||
|
if number.isPrime(obj.p, randfunc=randfunc):
|
||||||
|
break
|
||||||
|
# Generate generator g
|
||||||
|
# See Algorithm 4.80 in Handbook of Applied Cryptography
|
||||||
|
# Note that the order of the group is n=p-1=2q, where q is prime
|
||||||
|
if progress_func:
|
||||||
|
progress_func('g\n')
|
||||||
|
while 1:
|
||||||
|
# We must avoid g=2 because of Bleichenbacher's attack described
|
||||||
|
# in "Generating ElGamal signatures without knowning the secret key",
|
||||||
|
# 1996
|
||||||
|
#
|
||||||
|
obj.g = number.getRandomRange(3, obj.p, randfunc)
|
||||||
|
safe = 1
|
||||||
|
if pow(obj.g, 2, obj.p)==1:
|
||||||
|
safe=0
|
||||||
|
if safe and pow(obj.g, q, obj.p)==1:
|
||||||
|
safe=0
|
||||||
|
# Discard g if it divides p-1 because of the attack described
|
||||||
|
# in Note 11.67 (iii) in HAC
|
||||||
|
if safe and divmod(obj.p-1, obj.g)[1]==0:
|
||||||
|
safe=0
|
||||||
|
# g^{-1} must not divide p-1 because of Khadir's attack
|
||||||
|
# described in "Conditions of the generator for forging ElGamal
|
||||||
|
# signature", 2011
|
||||||
|
ginv = number.inverse(obj.g, obj.p)
|
||||||
|
if safe and divmod(obj.p-1, ginv)[1]==0:
|
||||||
|
safe=0
|
||||||
|
if safe:
|
||||||
|
break
|
||||||
|
# Generate private key x
|
||||||
|
if progress_func:
|
||||||
|
progress_func('x\n')
|
||||||
|
obj.x=number.getRandomRange(2, obj.p-1, randfunc)
|
||||||
|
# Generate public key y
|
||||||
|
if progress_func:
|
||||||
|
progress_func('y\n')
|
||||||
|
obj.y = pow(obj.g, obj.x, obj.p)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def construct(tup):
|
||||||
|
"""Construct an ElGamal key from a tuple of valid ElGamal components.
|
||||||
|
|
||||||
|
The modulus *p* must be a prime.
|
||||||
|
|
||||||
|
The following conditions must apply:
|
||||||
|
|
||||||
|
- 1 < g < p-1
|
||||||
|
- g^{p-1} = 1 mod p
|
||||||
|
- 1 < x < p-1
|
||||||
|
- g^x = y mod p
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
tup : tuple
|
||||||
|
A tuple of long integers, with 3 or 4 items
|
||||||
|
in the following order:
|
||||||
|
|
||||||
|
1. Modulus (*p*).
|
||||||
|
2. Generator (*g*).
|
||||||
|
3. Public key (*y*).
|
||||||
|
4. Private key (*x*). Optional.
|
||||||
|
|
||||||
|
:Return: An ElGamal key object (`ElGamalobj`).
|
||||||
|
"""
|
||||||
|
|
||||||
|
obj=ElGamalobj()
|
||||||
|
if len(tup) not in [3,4]:
|
||||||
|
raise ValueError('argument for construct() wrong length')
|
||||||
|
for i in range(len(tup)):
|
||||||
|
field = obj.keydata[i]
|
||||||
|
setattr(obj, field, tup[i])
|
||||||
|
return obj
|
||||||
|
|
||||||
|
class ElGamalobj(pubkey):
|
||||||
|
"""Class defining an ElGamal key.
|
||||||
|
|
||||||
|
:undocumented: __getstate__, __setstate__, __repr__, __getattr__
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: Dictionary of ElGamal parameters.
|
||||||
|
#:
|
||||||
|
#: A public key will only have the following entries:
|
||||||
|
#:
|
||||||
|
#: - **y**, the public key.
|
||||||
|
#: - **g**, the generator.
|
||||||
|
#: - **p**, the modulus.
|
||||||
|
#:
|
||||||
|
#: A private key will also have:
|
||||||
|
#:
|
||||||
|
#: - **x**, the private key.
|
||||||
|
keydata=['p', 'g', 'y', 'x']
|
||||||
|
|
||||||
|
def encrypt(self, plaintext, K):
|
||||||
|
"""Encrypt a piece of data with ElGamal.
|
||||||
|
|
||||||
|
:Parameter plaintext: The piece of data to encrypt with ElGamal.
|
||||||
|
It must be numerically smaller than the module (*p*).
|
||||||
|
:Type plaintext: byte string or long
|
||||||
|
|
||||||
|
:Parameter K: A secret number, chosen randomly in the closed
|
||||||
|
range *[1,p-2]*.
|
||||||
|
:Type K: long (recommended) or byte string (not recommended)
|
||||||
|
|
||||||
|
:Return: A tuple with two items. Each item is of the same type as the
|
||||||
|
plaintext (string or long).
|
||||||
|
|
||||||
|
:attention: selection of *K* is crucial for security. Generating a
|
||||||
|
random number larger than *p-1* and taking the modulus by *p-1* is
|
||||||
|
**not** secure, since smaller values will occur more frequently.
|
||||||
|
Generating a random number systematically smaller than *p-1*
|
||||||
|
(e.g. *floor((p-1)/8)* random bytes) is also **not** secure.
|
||||||
|
In general, it shall not be possible for an attacker to know
|
||||||
|
the value of any bit of K.
|
||||||
|
|
||||||
|
:attention: The number *K* shall not be reused for any other
|
||||||
|
operation and shall be discarded immediately.
|
||||||
|
"""
|
||||||
|
return pubkey.encrypt(self, plaintext, K)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt a piece of data with ElGamal.
|
||||||
|
|
||||||
|
:Parameter ciphertext: The piece of data to decrypt with ElGamal.
|
||||||
|
:Type ciphertext: byte string, long or a 2-item tuple as returned
|
||||||
|
by `encrypt`
|
||||||
|
|
||||||
|
:Return: A byte string if ciphertext was a byte string or a tuple
|
||||||
|
of byte strings. A long otherwise.
|
||||||
|
"""
|
||||||
|
return pubkey.decrypt(self, ciphertext)
|
||||||
|
|
||||||
|
def sign(self, M, K):
|
||||||
|
"""Sign a piece of data with ElGamal.
|
||||||
|
|
||||||
|
:Parameter M: The piece of data to sign with ElGamal. It may
|
||||||
|
not be longer in bit size than *p-1*.
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter K: A secret number, chosen randomly in the closed
|
||||||
|
range *[1,p-2]* and such that *gcd(k,p-1)=1*.
|
||||||
|
:Type K: long (recommended) or byte string (not recommended)
|
||||||
|
|
||||||
|
:attention: selection of *K* is crucial for security. Generating a
|
||||||
|
random number larger than *p-1* and taking the modulus by *p-1* is
|
||||||
|
**not** secure, since smaller values will occur more frequently.
|
||||||
|
Generating a random number systematically smaller than *p-1*
|
||||||
|
(e.g. *floor((p-1)/8)* random bytes) is also **not** secure.
|
||||||
|
In general, it shall not be possible for an attacker to know
|
||||||
|
the value of any bit of K.
|
||||||
|
|
||||||
|
:attention: The number *K* shall not be reused for any other
|
||||||
|
operation and shall be discarded immediately.
|
||||||
|
|
||||||
|
:attention: M must be be a cryptographic hash, otherwise an
|
||||||
|
attacker may mount an existential forgery attack.
|
||||||
|
|
||||||
|
:Return: A tuple with 2 longs.
|
||||||
|
"""
|
||||||
|
return pubkey.sign(self, M, K)
|
||||||
|
|
||||||
|
def verify(self, M, signature):
|
||||||
|
"""Verify the validity of an ElGamal signature.
|
||||||
|
|
||||||
|
:Parameter M: The expected message.
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter signature: The ElGamal signature to verify.
|
||||||
|
:Type signature: A tuple with 2 longs as return by `sign`
|
||||||
|
|
||||||
|
:Return: True if the signature is correct, False otherwise.
|
||||||
|
"""
|
||||||
|
return pubkey.verify(self, M, signature)
|
||||||
|
|
||||||
|
def _encrypt(self, M, K):
|
||||||
|
a=pow(self.g, K, self.p)
|
||||||
|
b=( M*pow(self.y, K, self.p) ) % self.p
|
||||||
|
return ( a,b )
|
||||||
|
|
||||||
|
def _decrypt(self, M):
|
||||||
|
if (not hasattr(self, 'x')):
|
||||||
|
raise TypeError('Private key not available in this object')
|
||||||
|
ax=pow(M[0], self.x, self.p)
|
||||||
|
plaintext=(M[1] * inverse(ax, self.p ) ) % self.p
|
||||||
|
return plaintext
|
||||||
|
|
||||||
|
def _sign(self, M, K):
|
||||||
|
if (not hasattr(self, 'x')):
|
||||||
|
raise TypeError('Private key not available in this object')
|
||||||
|
p1=self.p-1
|
||||||
|
if (GCD(K, p1)!=1):
|
||||||
|
raise ValueError('Bad K value: GCD(K,p-1)!=1')
|
||||||
|
a=pow(self.g, K, self.p)
|
||||||
|
t=(M-self.x*a) % p1
|
||||||
|
while t<0: t=t+p1
|
||||||
|
b=(t*inverse(K, p1)) % p1
|
||||||
|
return (a, b)
|
||||||
|
|
||||||
|
def _verify(self, M, sig):
|
||||||
|
if sig[0]<1 or sig[0]>self.p-1:
|
||||||
|
return 0
|
||||||
|
v1=pow(self.y, sig[0], self.p)
|
||||||
|
v1=(v1*pow(sig[0], sig[1], self.p)) % self.p
|
||||||
|
v2=pow(self.g, M, self.p)
|
||||||
|
if v1==v2:
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return number.size(self.p) - 1
|
||||||
|
|
||||||
|
def has_private(self):
|
||||||
|
if hasattr(self, 'x'):
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def publickey(self):
|
||||||
|
return construct((self.p, self.g, self.y))
|
||||||
|
|
||||||
|
|
||||||
|
object=ElGamalobj
|
719
Lib/site-packages/Crypto/PublicKey/RSA.py
Normal file
719
Lib/site-packages/Crypto/PublicKey/RSA.py
Normal file
|
@ -0,0 +1,719 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# PublicKey/RSA.py : RSA public key primitive
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""RSA public-key cryptography algorithm (signature and encryption).
|
||||||
|
|
||||||
|
RSA_ is the most widespread and used public key algorithm. Its security is
|
||||||
|
based on the difficulty of factoring large integers. The algorithm has
|
||||||
|
withstood attacks for 30 years, and it is therefore considered reasonably
|
||||||
|
secure for new designs.
|
||||||
|
|
||||||
|
The algorithm can be used for both confidentiality (encryption) and
|
||||||
|
authentication (digital signature). It is worth noting that signing and
|
||||||
|
decryption are significantly slower than verification and encryption.
|
||||||
|
The cryptograhic strength is primarily linked to the length of the modulus *n*.
|
||||||
|
In 2012, a sufficient length is deemed to be 2048 bits. For more information,
|
||||||
|
see the most recent ECRYPT_ report.
|
||||||
|
|
||||||
|
Both RSA ciphertext and RSA signature are as big as the modulus *n* (256
|
||||||
|
bytes if *n* is 2048 bit long).
|
||||||
|
|
||||||
|
This module provides facilities for generating fresh, new RSA keys, constructing
|
||||||
|
them from known components, exporting them, and importing them.
|
||||||
|
|
||||||
|
>>> from Crypto.PublicKey import RSA
|
||||||
|
>>>
|
||||||
|
>>> key = RSA.generate(2048)
|
||||||
|
>>> f = open('mykey.pem','w')
|
||||||
|
>>> f.write(RSA.exportKey('PEM'))
|
||||||
|
>>> f.close()
|
||||||
|
...
|
||||||
|
>>> f = open('mykey.pem','r')
|
||||||
|
>>> key = RSA.importKey(f.read())
|
||||||
|
|
||||||
|
Even though you may choose to directly use the methods of an RSA key object
|
||||||
|
to perform the primitive cryptographic operations (e.g. `_RSAobj.encrypt`),
|
||||||
|
it is recommended to use one of the standardized schemes instead (like
|
||||||
|
`Crypto.Cipher.PKCS1_v1_5` or `Crypto.Signature.PKCS1_v1_5`).
|
||||||
|
|
||||||
|
.. _RSA: http://en.wikipedia.org/wiki/RSA_%28algorithm%29
|
||||||
|
.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
|
||||||
|
|
||||||
|
:sort: generate,construct,importKey,error
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['generate', 'construct', 'error', 'importKey', 'RSAImplementation', '_RSAobj']
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
#from Crypto.Util.python_compat import *
|
||||||
|
from Crypto.Util.number import getRandomRange, bytes_to_long, long_to_bytes
|
||||||
|
|
||||||
|
from Crypto.PublicKey import _RSA, _slowmath, pubkey
|
||||||
|
from Crypto import Random
|
||||||
|
|
||||||
|
from Crypto.Util.asn1 import DerObject, DerSequence, DerNull
|
||||||
|
import binascii
|
||||||
|
import struct
|
||||||
|
|
||||||
|
from Crypto.Util.number import inverse
|
||||||
|
|
||||||
|
from Crypto.Util.number import inverse
|
||||||
|
|
||||||
|
try:
|
||||||
|
from Crypto.PublicKey import _fastmath
|
||||||
|
except ImportError:
|
||||||
|
_fastmath = None
|
||||||
|
|
||||||
|
class _RSAobj(pubkey.pubkey):
|
||||||
|
"""Class defining an actual RSA key.
|
||||||
|
|
||||||
|
:undocumented: __getstate__, __setstate__, __repr__, __getattr__
|
||||||
|
"""
|
||||||
|
#: Dictionary of RSA parameters.
|
||||||
|
#:
|
||||||
|
#: A public key will only have the following entries:
|
||||||
|
#:
|
||||||
|
#: - **n**, the modulus.
|
||||||
|
#: - **e**, the public exponent.
|
||||||
|
#:
|
||||||
|
#: A private key will also have:
|
||||||
|
#:
|
||||||
|
#: - **d**, the private exponent.
|
||||||
|
#: - **p**, the first factor of n.
|
||||||
|
#: - **q**, the second factor of n.
|
||||||
|
#: - **u**, the CRT coefficient (1/p) mod q.
|
||||||
|
keydata = ['n', 'e', 'd', 'p', 'q', 'u']
|
||||||
|
|
||||||
|
def __init__(self, implementation, key, randfunc=None):
|
||||||
|
self.implementation = implementation
|
||||||
|
self.key = key
|
||||||
|
if randfunc is None:
|
||||||
|
randfunc = Random.new().read
|
||||||
|
self._randfunc = randfunc
|
||||||
|
|
||||||
|
def __getattr__(self, attrname):
|
||||||
|
if attrname in self.keydata:
|
||||||
|
# For backward compatibility, allow the user to get (not set) the
|
||||||
|
# RSA key parameters directly from this object.
|
||||||
|
return getattr(self.key, attrname)
|
||||||
|
else:
|
||||||
|
raise AttributeError("%s object has no %r attribute" % (self.__class__.__name__, attrname,))
|
||||||
|
|
||||||
|
def encrypt(self, plaintext, K):
|
||||||
|
"""Encrypt a piece of data with RSA.
|
||||||
|
|
||||||
|
:Parameter plaintext: The piece of data to encrypt with RSA. It may not
|
||||||
|
be numerically larger than the RSA module (**n**).
|
||||||
|
:Type plaintext: byte string or long
|
||||||
|
|
||||||
|
:Parameter K: A random parameter (*for compatibility only. This
|
||||||
|
value will be ignored*)
|
||||||
|
:Type K: byte string or long
|
||||||
|
|
||||||
|
:attention: this function performs the plain, primitive RSA encryption
|
||||||
|
(*textbook*). In real applications, you always need to use proper
|
||||||
|
cryptographic padding, and you should not directly encrypt data with
|
||||||
|
this method. Failure to do so may lead to security vulnerabilities.
|
||||||
|
It is recommended to use modules
|
||||||
|
`Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead.
|
||||||
|
|
||||||
|
:Return: A tuple with two items. The first item is the ciphertext
|
||||||
|
of the same type as the plaintext (string or long). The second item
|
||||||
|
is always None.
|
||||||
|
"""
|
||||||
|
return pubkey.pubkey.encrypt(self, plaintext, K)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt a piece of data with RSA.
|
||||||
|
|
||||||
|
Decryption always takes place with blinding.
|
||||||
|
|
||||||
|
:attention: this function performs the plain, primitive RSA decryption
|
||||||
|
(*textbook*). In real applications, you always need to use proper
|
||||||
|
cryptographic padding, and you should not directly decrypt data with
|
||||||
|
this method. Failure to do so may lead to security vulnerabilities.
|
||||||
|
It is recommended to use modules
|
||||||
|
`Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead.
|
||||||
|
|
||||||
|
:Parameter ciphertext: The piece of data to decrypt with RSA. It may
|
||||||
|
not be numerically larger than the RSA module (**n**). If a tuple,
|
||||||
|
the first item is the actual ciphertext; the second item is ignored.
|
||||||
|
|
||||||
|
:Type ciphertext: byte string, long or a 2-item tuple as returned by
|
||||||
|
`encrypt`
|
||||||
|
|
||||||
|
:Return: A byte string if ciphertext was a byte string or a tuple
|
||||||
|
of byte strings. A long otherwise.
|
||||||
|
"""
|
||||||
|
return pubkey.pubkey.decrypt(self, ciphertext)
|
||||||
|
|
||||||
|
def sign(self, M, K):
|
||||||
|
"""Sign a piece of data with RSA.
|
||||||
|
|
||||||
|
Signing always takes place with blinding.
|
||||||
|
|
||||||
|
:attention: this function performs the plain, primitive RSA decryption
|
||||||
|
(*textbook*). In real applications, you always need to use proper
|
||||||
|
cryptographic padding, and you should not directly sign data with
|
||||||
|
this method. Failure to do so may lead to security vulnerabilities.
|
||||||
|
It is recommended to use modules
|
||||||
|
`Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead.
|
||||||
|
|
||||||
|
:Parameter M: The piece of data to sign with RSA. It may
|
||||||
|
not be numerically larger than the RSA module (**n**).
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter K: A random parameter (*for compatibility only. This
|
||||||
|
value will be ignored*)
|
||||||
|
:Type K: byte string or long
|
||||||
|
|
||||||
|
:Return: A 2-item tuple. The first item is the actual signature (a
|
||||||
|
long). The second item is always None.
|
||||||
|
"""
|
||||||
|
return pubkey.pubkey.sign(self, M, K)
|
||||||
|
|
||||||
|
def verify(self, M, signature):
|
||||||
|
"""Verify the validity of an RSA signature.
|
||||||
|
|
||||||
|
:attention: this function performs the plain, primitive RSA encryption
|
||||||
|
(*textbook*). In real applications, you always need to use proper
|
||||||
|
cryptographic padding, and you should not directly verify data with
|
||||||
|
this method. Failure to do so may lead to security vulnerabilities.
|
||||||
|
It is recommended to use modules
|
||||||
|
`Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead.
|
||||||
|
|
||||||
|
:Parameter M: The expected message.
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter signature: The RSA signature to verify. The first item of
|
||||||
|
the tuple is the actual signature (a long not larger than the modulus
|
||||||
|
**n**), whereas the second item is always ignored.
|
||||||
|
:Type signature: A 2-item tuple as return by `sign`
|
||||||
|
|
||||||
|
:Return: True if the signature is correct, False otherwise.
|
||||||
|
"""
|
||||||
|
return pubkey.pubkey.verify(self, M, signature)
|
||||||
|
|
||||||
|
def _encrypt(self, c, K):
|
||||||
|
return (self.key._encrypt(c),)
|
||||||
|
|
||||||
|
def _decrypt(self, c):
|
||||||
|
#(ciphertext,) = c
|
||||||
|
(ciphertext,) = c[:1] # HACK - We should use the previous line
|
||||||
|
# instead, but this is more compatible and we're
|
||||||
|
# going to replace the Crypto.PublicKey API soon
|
||||||
|
# anyway.
|
||||||
|
|
||||||
|
# Blinded RSA decryption (to prevent timing attacks):
|
||||||
|
# Step 1: Generate random secret blinding factor r, such that 0 < r < n-1
|
||||||
|
r = getRandomRange(1, self.key.n-1, randfunc=self._randfunc)
|
||||||
|
# Step 2: Compute c' = c * r**e mod n
|
||||||
|
cp = self.key._blind(ciphertext, r)
|
||||||
|
# Step 3: Compute m' = c'**d mod n (ordinary RSA decryption)
|
||||||
|
mp = self.key._decrypt(cp)
|
||||||
|
# Step 4: Compute m = m**(r-1) mod n
|
||||||
|
return self.key._unblind(mp, r)
|
||||||
|
|
||||||
|
def _blind(self, m, r):
|
||||||
|
return self.key._blind(m, r)
|
||||||
|
|
||||||
|
def _unblind(self, m, r):
|
||||||
|
return self.key._unblind(m, r)
|
||||||
|
|
||||||
|
def _sign(self, m, K=None):
|
||||||
|
return (self.key._sign(m),)
|
||||||
|
|
||||||
|
def _verify(self, m, sig):
|
||||||
|
#(s,) = sig
|
||||||
|
(s,) = sig[:1] # HACK - We should use the previous line instead, but
|
||||||
|
# this is more compatible and we're going to replace
|
||||||
|
# the Crypto.PublicKey API soon anyway.
|
||||||
|
return self.key._verify(m, s)
|
||||||
|
|
||||||
|
def has_private(self):
|
||||||
|
return self.key.has_private()
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
return self.key.size()
|
||||||
|
|
||||||
|
def can_blind(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def can_encrypt(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def can_sign(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def publickey(self):
|
||||||
|
return self.implementation.construct((self.key.n, self.key.e))
|
||||||
|
|
||||||
|
def __getstate__(self):
|
||||||
|
d = {}
|
||||||
|
for k in self.keydata:
|
||||||
|
try:
|
||||||
|
d[k] = getattr(self.key, k)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
return d
|
||||||
|
|
||||||
|
def __setstate__(self, d):
|
||||||
|
if not hasattr(self, 'implementation'):
|
||||||
|
self.implementation = RSAImplementation()
|
||||||
|
t = []
|
||||||
|
for k in self.keydata:
|
||||||
|
if k not in d:
|
||||||
|
break
|
||||||
|
t.append(d[k])
|
||||||
|
self.key = self.implementation._math.rsa_construct(*tuple(t))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
attrs = []
|
||||||
|
for k in self.keydata:
|
||||||
|
if k == 'n':
|
||||||
|
attrs.append("n(%d)" % (self.size()+1,))
|
||||||
|
elif hasattr(self.key, k):
|
||||||
|
attrs.append(k)
|
||||||
|
if self.has_private():
|
||||||
|
attrs.append("private")
|
||||||
|
# PY3K: This is meant to be text, do not change to bytes (data)
|
||||||
|
return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
|
||||||
|
|
||||||
|
def exportKey(self, format='PEM', passphrase=None, pkcs=1):
|
||||||
|
"""Export this RSA key.
|
||||||
|
|
||||||
|
:Parameter format: The format to use for wrapping the key.
|
||||||
|
|
||||||
|
- *'DER'*. Binary encoding, always unencrypted.
|
||||||
|
- *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_.
|
||||||
|
Unencrypted (default) or encrypted.
|
||||||
|
- *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
|
||||||
|
Only suitable for public keys (not private keys).
|
||||||
|
:Type format: string
|
||||||
|
|
||||||
|
:Parameter passphrase: In case of PEM, the pass phrase to derive the encryption key from.
|
||||||
|
:Type passphrase: string
|
||||||
|
|
||||||
|
:Parameter pkcs: The PKCS standard to follow for assembling the key.
|
||||||
|
You have two choices:
|
||||||
|
|
||||||
|
- with **1**, the public key is embedded into an X.509 `SubjectPublicKeyInfo` DER SEQUENCE.
|
||||||
|
The private key is embedded into a `PKCS#1`_ `RSAPrivateKey` DER SEQUENCE.
|
||||||
|
This mode is the default.
|
||||||
|
- with **8**, the private key is embedded into a `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE.
|
||||||
|
This mode is not available for public keys.
|
||||||
|
|
||||||
|
PKCS standards are not relevant for the *OpenSSH* format.
|
||||||
|
:Type pkcs: integer
|
||||||
|
|
||||||
|
:Return: A byte string with the encoded public or private half.
|
||||||
|
:Raise ValueError:
|
||||||
|
When the format is unknown.
|
||||||
|
|
||||||
|
.. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
|
||||||
|
.. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
|
||||||
|
.. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
|
||||||
|
.. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
|
||||||
|
"""
|
||||||
|
if passphrase is not None:
|
||||||
|
passphrase = tobytes(passphrase)
|
||||||
|
if format=='OpenSSH':
|
||||||
|
eb = long_to_bytes(self.e)
|
||||||
|
nb = long_to_bytes(self.n)
|
||||||
|
if bord(eb[0]) & 0x80: eb=bchr(0x00)+eb
|
||||||
|
if bord(nb[0]) & 0x80: nb=bchr(0x00)+nb
|
||||||
|
keyparts = [ 'ssh-rsa', eb, nb ]
|
||||||
|
keystring = ''.join([ struct.pack(">I",len(kp))+kp for kp in keyparts])
|
||||||
|
return 'ssh-rsa '+binascii.b2a_base64(keystring)[:-1]
|
||||||
|
|
||||||
|
# DER format is always used, even in case of PEM, which simply
|
||||||
|
# encodes it into BASE64.
|
||||||
|
der = DerSequence()
|
||||||
|
if self.has_private():
|
||||||
|
keyType= { 1: 'RSA PRIVATE', 8: 'PRIVATE' }[pkcs]
|
||||||
|
der[:] = [ 0, self.n, self.e, self.d, self.p, self.q,
|
||||||
|
self.d % (self.p-1), self.d % (self.q-1),
|
||||||
|
inverse(self.q, self.p) ]
|
||||||
|
if pkcs==8:
|
||||||
|
derkey = der.encode()
|
||||||
|
der = DerSequence([0])
|
||||||
|
der.append(algorithmIdentifier)
|
||||||
|
der.append(DerObject('OCTET STRING', derkey).encode())
|
||||||
|
else:
|
||||||
|
keyType = "PUBLIC"
|
||||||
|
der.append(algorithmIdentifier)
|
||||||
|
bitmap = DerObject('BIT STRING')
|
||||||
|
derPK = DerSequence( [ self.n, self.e ] )
|
||||||
|
bitmap.payload = bchr(0x00) + derPK.encode()
|
||||||
|
der.append(bitmap.encode())
|
||||||
|
if format=='DER':
|
||||||
|
return der.encode()
|
||||||
|
if format=='PEM':
|
||||||
|
pem = b("-----BEGIN " + keyType + " KEY-----\n")
|
||||||
|
objenc = None
|
||||||
|
if passphrase and keyType.endswith('PRIVATE'):
|
||||||
|
# We only support 3DES for encryption
|
||||||
|
import Crypto.Hash.MD5
|
||||||
|
from Crypto.Cipher import DES3
|
||||||
|
from Crypto.Protocol.KDF import PBKDF1
|
||||||
|
salt = self._randfunc(8)
|
||||||
|
key = PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
|
||||||
|
key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD5)
|
||||||
|
objenc = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt)
|
||||||
|
pem += b('Proc-Type: 4,ENCRYPTED\n')
|
||||||
|
pem += b('DEK-Info: DES-EDE3-CBC,') + binascii.b2a_hex(salt).upper() + b('\n\n')
|
||||||
|
|
||||||
|
binaryKey = der.encode()
|
||||||
|
if objenc:
|
||||||
|
# Add PKCS#7-like padding
|
||||||
|
padding = objenc.block_size-len(binaryKey)%objenc.block_size
|
||||||
|
binaryKey = objenc.encrypt(binaryKey+bchr(padding)*padding)
|
||||||
|
|
||||||
|
# Each BASE64 line can take up to 64 characters (=48 bytes of data)
|
||||||
|
chunks = [ binascii.b2a_base64(binaryKey[i:i+48]) for i in range(0, len(binaryKey), 48) ]
|
||||||
|
pem += b('').join(chunks)
|
||||||
|
pem += b("-----END " + keyType + " KEY-----")
|
||||||
|
return pem
|
||||||
|
return ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
|
||||||
|
|
||||||
|
class RSAImplementation(object):
|
||||||
|
"""
|
||||||
|
An RSA key factory.
|
||||||
|
|
||||||
|
This class is only internally used to implement the methods of the `Crypto.PublicKey.RSA` module.
|
||||||
|
|
||||||
|
:sort: __init__,generate,construct,importKey
|
||||||
|
:undocumented: _g*, _i*
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
"""Create a new RSA key factory.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
use_fast_math : bool
|
||||||
|
Specify which mathematic library to use:
|
||||||
|
|
||||||
|
- *None* (default). Use fastest math available.
|
||||||
|
- *True* . Use fast math.
|
||||||
|
- *False* . Use slow math.
|
||||||
|
default_randfunc : callable
|
||||||
|
Specify how to collect random data:
|
||||||
|
|
||||||
|
- *None* (default). Use Random.new().read().
|
||||||
|
- not *None* . Use the specified function directly.
|
||||||
|
:Raise RuntimeError:
|
||||||
|
When **use_fast_math** =True but fast math is not available.
|
||||||
|
"""
|
||||||
|
use_fast_math = kwargs.get('use_fast_math', None)
|
||||||
|
if use_fast_math is None: # Automatic
|
||||||
|
if _fastmath is not None:
|
||||||
|
self._math = _fastmath
|
||||||
|
else:
|
||||||
|
self._math = _slowmath
|
||||||
|
|
||||||
|
elif use_fast_math: # Explicitly select fast math
|
||||||
|
if _fastmath is not None:
|
||||||
|
self._math = _fastmath
|
||||||
|
else:
|
||||||
|
raise RuntimeError("fast math module not available")
|
||||||
|
|
||||||
|
else: # Explicitly select slow math
|
||||||
|
self._math = _slowmath
|
||||||
|
|
||||||
|
self.error = self._math.error
|
||||||
|
|
||||||
|
self._default_randfunc = kwargs.get('default_randfunc', None)
|
||||||
|
self._current_randfunc = None
|
||||||
|
|
||||||
|
def _get_randfunc(self, randfunc):
|
||||||
|
if randfunc is not None:
|
||||||
|
return randfunc
|
||||||
|
elif self._current_randfunc is None:
|
||||||
|
self._current_randfunc = Random.new().read
|
||||||
|
return self._current_randfunc
|
||||||
|
|
||||||
|
def generate(self, bits, randfunc=None, progress_func=None, e=65537):
|
||||||
|
"""Randomly generate a fresh, new RSA key.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
bits : int
|
||||||
|
Key length, or size (in bits) of the RSA modulus.
|
||||||
|
It must be a multiple of 256, and no smaller than 1024.
|
||||||
|
|
||||||
|
randfunc : callable
|
||||||
|
Random number generation function; it should accept
|
||||||
|
a single integer N and return a string of random data
|
||||||
|
N bytes long.
|
||||||
|
If not specified, a new one will be instantiated
|
||||||
|
from ``Crypto.Random``.
|
||||||
|
|
||||||
|
progress_func : callable
|
||||||
|
Optional function that will be called with a short string
|
||||||
|
containing the key parameter currently being generated;
|
||||||
|
it's useful for interactive applications where a user is
|
||||||
|
waiting for a key to be generated.
|
||||||
|
|
||||||
|
e : int
|
||||||
|
Public RSA exponent. It must be an odd positive integer.
|
||||||
|
It is typically a small number with very few ones in its
|
||||||
|
binary representation.
|
||||||
|
The default value 65537 (= ``0b10000000000000001`` ) is a safe
|
||||||
|
choice: other common values are 5, 7, 17, and 257.
|
||||||
|
|
||||||
|
:attention: You should always use a cryptographically secure random number generator,
|
||||||
|
such as the one defined in the ``Crypto.Random`` module; **don't** just use the
|
||||||
|
current time and the ``random`` module.
|
||||||
|
|
||||||
|
:attention: Exponent 3 is also widely used, but it requires very special care when padding
|
||||||
|
the message.
|
||||||
|
|
||||||
|
:Return: An RSA key object (`_RSAobj`).
|
||||||
|
|
||||||
|
:Raise ValueError:
|
||||||
|
When **bits** is too little or not a multiple of 256, or when
|
||||||
|
**e** is not odd or smaller than 2.
|
||||||
|
"""
|
||||||
|
if bits < 1024 or (bits & 0xff) != 0:
|
||||||
|
# pubkey.getStrongPrime doesn't like anything that's not a multiple of 256 and >= 1024
|
||||||
|
raise ValueError("RSA modulus length must be a multiple of 256 and >= 1024")
|
||||||
|
if e%2==0 or e<3:
|
||||||
|
raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.")
|
||||||
|
rf = self._get_randfunc(randfunc)
|
||||||
|
obj = _RSA.generate_py(bits, rf, progress_func, e) # TODO: Don't use legacy _RSA module
|
||||||
|
key = self._math.rsa_construct(obj.n, obj.e, obj.d, obj.p, obj.q, obj.u)
|
||||||
|
return _RSAobj(self, key)
|
||||||
|
|
||||||
|
def construct(self, tup):
|
||||||
|
"""Construct an RSA key from a tuple of valid RSA components.
|
||||||
|
|
||||||
|
The modulus **n** must be the product of two primes.
|
||||||
|
The public exponent **e** must be odd and larger than 1.
|
||||||
|
|
||||||
|
In case of a private key, the following equations must apply:
|
||||||
|
|
||||||
|
- e != 1
|
||||||
|
- p*q = n
|
||||||
|
- e*d = 1 mod (p-1)(q-1)
|
||||||
|
- p*u = 1 mod q
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
tup : tuple
|
||||||
|
A tuple of long integers, with at least 2 and no
|
||||||
|
more than 6 items. The items come in the following order:
|
||||||
|
|
||||||
|
1. RSA modulus (n).
|
||||||
|
2. Public exponent (e).
|
||||||
|
3. Private exponent (d). Only required if the key is private.
|
||||||
|
4. First factor of n (p). Optional.
|
||||||
|
5. Second factor of n (q). Optional.
|
||||||
|
6. CRT coefficient, (1/p) mod q (u). Optional.
|
||||||
|
|
||||||
|
:Return: An RSA key object (`_RSAobj`).
|
||||||
|
"""
|
||||||
|
key = self._math.rsa_construct(*tup)
|
||||||
|
return _RSAobj(self, key)
|
||||||
|
|
||||||
|
def _importKeyDER(self, externKey):
|
||||||
|
"""Import an RSA key (public or private half), encoded in DER form."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
der = DerSequence()
|
||||||
|
der.decode(externKey, True)
|
||||||
|
|
||||||
|
# Try PKCS#1 first, for a private key
|
||||||
|
if len(der)==9 and der.hasOnlyInts() and der[0]==0:
|
||||||
|
# ASN.1 RSAPrivateKey element
|
||||||
|
del der[6:] # Remove d mod (p-1), d mod (q-1), and q^{-1} mod p
|
||||||
|
der.append(inverse(der[4],der[5])) # Add p^{-1} mod q
|
||||||
|
del der[0] # Remove version
|
||||||
|
return self.construct(der[:])
|
||||||
|
|
||||||
|
# Keep on trying PKCS#1, but now for a public key
|
||||||
|
if len(der)==2:
|
||||||
|
# The DER object is an RSAPublicKey SEQUENCE with two elements
|
||||||
|
if der.hasOnlyInts():
|
||||||
|
return self.construct(der[:])
|
||||||
|
# The DER object is a SubjectPublicKeyInfo SEQUENCE with two elements:
|
||||||
|
# an 'algorithm' (or 'algorithmIdentifier') SEQUENCE and a 'subjectPublicKey' BIT STRING.
|
||||||
|
# 'algorithm' takes the value given a few lines above.
|
||||||
|
# 'subjectPublicKey' encapsulates the actual ASN.1 RSAPublicKey element.
|
||||||
|
if der[0]==algorithmIdentifier:
|
||||||
|
bitmap = DerObject()
|
||||||
|
bitmap.decode(der[1], True)
|
||||||
|
if bitmap.isType('BIT STRING') and bord(bitmap.payload[0])==0x00:
|
||||||
|
der.decode(bitmap.payload[1:], True)
|
||||||
|
if len(der)==2 and der.hasOnlyInts():
|
||||||
|
return self.construct(der[:])
|
||||||
|
|
||||||
|
# Try unencrypted PKCS#8
|
||||||
|
if der[0]==0:
|
||||||
|
# The second element in the SEQUENCE is algorithmIdentifier.
|
||||||
|
# It must say RSA (see above for description).
|
||||||
|
if der[1]==algorithmIdentifier:
|
||||||
|
privateKey = DerObject()
|
||||||
|
privateKey.decode(der[2], True)
|
||||||
|
if privateKey.isType('OCTET STRING'):
|
||||||
|
return self._importKeyDER(privateKey.payload)
|
||||||
|
|
||||||
|
except ValueError as IndexError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
raise ValueError("RSA key format is not supported")
|
||||||
|
|
||||||
|
def importKey(self, externKey, passphrase=None):
|
||||||
|
"""Import an RSA key (public or private half), encoded in standard form.
|
||||||
|
|
||||||
|
:Parameter externKey:
|
||||||
|
The RSA key to import, encoded as a string.
|
||||||
|
|
||||||
|
An RSA public key can be in any of the following formats:
|
||||||
|
|
||||||
|
- X.509 `subjectPublicKeyInfo` DER SEQUENCE (binary or PEM encoding)
|
||||||
|
- `PKCS#1`_ `RSAPublicKey` DER SEQUENCE (binary or PEM encoding)
|
||||||
|
- OpenSSH (textual public key only)
|
||||||
|
|
||||||
|
An RSA private key can be in any of the following formats:
|
||||||
|
|
||||||
|
- PKCS#1 `RSAPrivateKey` DER SEQUENCE (binary or PEM encoding)
|
||||||
|
- `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE (binary or PEM encoding)
|
||||||
|
- OpenSSH (textual public key only)
|
||||||
|
|
||||||
|
For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
|
||||||
|
|
||||||
|
In case of PEM encoding, the private key can be encrypted with DES or 3TDES according to a certain ``pass phrase``.
|
||||||
|
Only OpenSSL-compatible pass phrases are supported.
|
||||||
|
:Type externKey: string
|
||||||
|
|
||||||
|
:Parameter passphrase:
|
||||||
|
In case of an encrypted PEM key, this is the pass phrase from which the encryption key is derived.
|
||||||
|
:Type passphrase: string
|
||||||
|
|
||||||
|
:Return: An RSA key object (`_RSAobj`).
|
||||||
|
|
||||||
|
:Raise ValueError/IndexError/TypeError:
|
||||||
|
When the given key cannot be parsed (possibly because the pass phrase is wrong).
|
||||||
|
|
||||||
|
.. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
|
||||||
|
.. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
|
||||||
|
.. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
|
||||||
|
.. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
|
||||||
|
"""
|
||||||
|
externKey = tobytes(externKey)
|
||||||
|
if passphrase is not None:
|
||||||
|
passphrase = tobytes(passphrase)
|
||||||
|
|
||||||
|
if externKey.startswith(b('-----')):
|
||||||
|
# This is probably a PEM encoded key
|
||||||
|
lines = externKey.replace(b(" "),b('')).split()
|
||||||
|
keyobj = None
|
||||||
|
|
||||||
|
# The encrypted PEM format
|
||||||
|
if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
|
||||||
|
DEK = lines[2].split(b(':'))
|
||||||
|
if len(DEK)!=2 or DEK[0]!=b('DEK-Info') or not passphrase:
|
||||||
|
raise ValueError("PEM encryption format not supported.")
|
||||||
|
algo, salt = DEK[1].split(b(','))
|
||||||
|
salt = binascii.a2b_hex(salt)
|
||||||
|
import Crypto.Hash.MD5
|
||||||
|
from Crypto.Cipher import DES, DES3
|
||||||
|
from Crypto.Protocol.KDF import PBKDF1
|
||||||
|
if algo==b("DES-CBC"):
|
||||||
|
# This is EVP_BytesToKey in OpenSSL
|
||||||
|
key = PBKDF1(passphrase, salt, 8, 1, Crypto.Hash.MD5)
|
||||||
|
keyobj = DES.new(key, Crypto.Cipher.DES.MODE_CBC, salt)
|
||||||
|
elif algo==b("DES-EDE3-CBC"):
|
||||||
|
# Note that EVP_BytesToKey is note exactly the same as PBKDF1
|
||||||
|
key = PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
|
||||||
|
key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD5)
|
||||||
|
keyobj = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt)
|
||||||
|
else:
|
||||||
|
raise ValueError("Unsupport PEM encryption algorithm.")
|
||||||
|
lines = lines[2:]
|
||||||
|
|
||||||
|
der = binascii.a2b_base64(b('').join(lines[1:-1]))
|
||||||
|
if keyobj:
|
||||||
|
der = keyobj.decrypt(der)
|
||||||
|
padding = bord(der[-1])
|
||||||
|
der = der[:-padding]
|
||||||
|
return self._importKeyDER(der)
|
||||||
|
|
||||||
|
if externKey.startswith(b('ssh-rsa ')):
|
||||||
|
# This is probably an OpenSSH key
|
||||||
|
keystring = binascii.a2b_base64(externKey.split(b(' '))[1])
|
||||||
|
keyparts = []
|
||||||
|
while len(keystring)>4:
|
||||||
|
l = struct.unpack(">I",keystring[:4])[0]
|
||||||
|
keyparts.append(keystring[4:4+l])
|
||||||
|
keystring = keystring[4+l:]
|
||||||
|
e = bytes_to_long(keyparts[1])
|
||||||
|
n = bytes_to_long(keyparts[2])
|
||||||
|
return self.construct([n, e])
|
||||||
|
if bord(externKey[0])==0x30:
|
||||||
|
# This is probably a DER encoded key
|
||||||
|
return self._importKeyDER(externKey)
|
||||||
|
|
||||||
|
raise ValueError("RSA key format is not supported")
|
||||||
|
|
||||||
|
#: This is the ASN.1 DER object that qualifies an algorithm as
|
||||||
|
#: compliant to PKCS#1 (that is, the standard RSA).
|
||||||
|
# It is found in all 'algorithm' fields (also called 'algorithmIdentifier').
|
||||||
|
# It is a SEQUENCE with the oid assigned to RSA and with its parameters (none).
|
||||||
|
# 0x06 0x09 OBJECT IDENTIFIER, 9 bytes of payload
|
||||||
|
# 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01
|
||||||
|
# rsaEncryption (1 2 840 113549 1 1 1) (PKCS #1)
|
||||||
|
# 0x05 0x00 NULL
|
||||||
|
algorithmIdentifier = DerSequence(
|
||||||
|
[ b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'),
|
||||||
|
DerNull().encode() ]
|
||||||
|
).encode()
|
||||||
|
|
||||||
|
_impl = RSAImplementation()
|
||||||
|
#:
|
||||||
|
#: Randomly generate a fresh, new RSA key object.
|
||||||
|
#:
|
||||||
|
#: See `RSAImplementation.generate`.
|
||||||
|
#:
|
||||||
|
generate = _impl.generate
|
||||||
|
#:
|
||||||
|
#: Construct an RSA key object from a tuple of valid RSA components.
|
||||||
|
#:
|
||||||
|
#: See `RSAImplementation.construct`.
|
||||||
|
#:
|
||||||
|
construct = _impl.construct
|
||||||
|
#:
|
||||||
|
#: Import an RSA key (public or private half), encoded in standard form.
|
||||||
|
#:
|
||||||
|
#: See `RSAImplementation.importKey`.
|
||||||
|
#:
|
||||||
|
importKey = _impl.importKey
|
||||||
|
error = _impl.error
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||||
|
|
115
Lib/site-packages/Crypto/PublicKey/_DSA.py
Normal file
115
Lib/site-packages/Crypto/PublicKey/_DSA.py
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
|
||||||
|
#
|
||||||
|
# DSA.py : Digital Signature Algorithm
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# Written by Andrew Kuchling, Paul Swartz, and others
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.PublicKey.pubkey import *
|
||||||
|
from Crypto.Util import number
|
||||||
|
from Crypto.Util.number import bytes_to_long, long_to_bytes
|
||||||
|
from Crypto.Hash import SHA
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
class error (Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def generateQ(randfunc):
|
||||||
|
S=randfunc(20)
|
||||||
|
hash1=SHA.new(S).digest()
|
||||||
|
hash2=SHA.new(long_to_bytes(bytes_to_long(S)+1)).digest()
|
||||||
|
q = bignum(0)
|
||||||
|
for i in range(0,20):
|
||||||
|
c=bord(hash1[i])^bord(hash2[i])
|
||||||
|
if i==0:
|
||||||
|
c=c | 128
|
||||||
|
if i==19:
|
||||||
|
c= c | 1
|
||||||
|
q=q*256+c
|
||||||
|
while (not isPrime(q)):
|
||||||
|
q=q+2
|
||||||
|
if pow(2,159) < q < pow(2,160):
|
||||||
|
return S, q
|
||||||
|
raise RuntimeError('Bad q value generated')
|
||||||
|
|
||||||
|
def generate_py(bits, randfunc, progress_func=None):
|
||||||
|
"""generate(bits:int, randfunc:callable, progress_func:callable)
|
||||||
|
|
||||||
|
Generate a DSA key of length 'bits', using 'randfunc' to get
|
||||||
|
random data and 'progress_func', if present, to display
|
||||||
|
the progress of the key generation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if bits<160:
|
||||||
|
raise ValueError('Key length < 160 bits')
|
||||||
|
obj=DSAobj()
|
||||||
|
# Generate string S and prime q
|
||||||
|
if progress_func:
|
||||||
|
progress_func('p,q\n')
|
||||||
|
while (1):
|
||||||
|
S, obj.q = generateQ(randfunc)
|
||||||
|
n=divmod(bits-1, 160)[0]
|
||||||
|
C, N, V = 0, 2, {}
|
||||||
|
b=(obj.q >> 5) & 15
|
||||||
|
powb=pow(bignum(2), b)
|
||||||
|
powL1=pow(bignum(2), bits-1)
|
||||||
|
while C<4096:
|
||||||
|
for k in range(0, n+1):
|
||||||
|
V[k]=bytes_to_long(SHA.new(S+bstr(N)+bstr(k)).digest())
|
||||||
|
W=V[n] % powb
|
||||||
|
for k in range(n-1, -1, -1):
|
||||||
|
W=(W<<160)+V[k]
|
||||||
|
X=W+powL1
|
||||||
|
p=X-(X%(2*obj.q)-1)
|
||||||
|
if powL1<=p and isPrime(p):
|
||||||
|
break
|
||||||
|
C, N = C+1, N+n+1
|
||||||
|
if C<4096:
|
||||||
|
break
|
||||||
|
if progress_func:
|
||||||
|
progress_func('4096 multiples failed\n')
|
||||||
|
|
||||||
|
obj.p = p
|
||||||
|
power=divmod(p-1, obj.q)[0]
|
||||||
|
if progress_func:
|
||||||
|
progress_func('h,g\n')
|
||||||
|
while (1):
|
||||||
|
h=bytes_to_long(randfunc(bits)) % (p-1)
|
||||||
|
g=pow(h, power, p)
|
||||||
|
if 1<h<p-1 and g>1:
|
||||||
|
break
|
||||||
|
obj.g=g
|
||||||
|
if progress_func:
|
||||||
|
progress_func('x,y\n')
|
||||||
|
while (1):
|
||||||
|
x=bytes_to_long(randfunc(20))
|
||||||
|
if 0 < x < obj.q:
|
||||||
|
break
|
||||||
|
obj.x, obj.y = x, pow(g, x, p)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
class DSAobj:
|
||||||
|
pass
|
||||||
|
|
81
Lib/site-packages/Crypto/PublicKey/_RSA.py
Normal file
81
Lib/site-packages/Crypto/PublicKey/_RSA.py
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#
|
||||||
|
# RSA.py : RSA encryption/decryption
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# Written by Andrew Kuchling, Paul Swartz, and others
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.PublicKey import pubkey
|
||||||
|
from Crypto.Util import number
|
||||||
|
|
||||||
|
def generate_py(bits, randfunc, progress_func=None, e=65537):
|
||||||
|
"""generate(bits:int, randfunc:callable, progress_func:callable, e:int)
|
||||||
|
|
||||||
|
Generate an RSA key of length 'bits', public exponent 'e'(which must be
|
||||||
|
odd), using 'randfunc' to get random data and 'progress_func',
|
||||||
|
if present, to display the progress of the key generation.
|
||||||
|
"""
|
||||||
|
obj=RSAobj()
|
||||||
|
obj.e = int(e)
|
||||||
|
|
||||||
|
# Generate the prime factors of n
|
||||||
|
if progress_func:
|
||||||
|
progress_func('p,q\n')
|
||||||
|
p = q = 1
|
||||||
|
while number.size(p*q) < bits:
|
||||||
|
# Note that q might be one bit longer than p if somebody specifies an odd
|
||||||
|
# number of bits for the key. (Why would anyone do that? You don't get
|
||||||
|
# more security.)
|
||||||
|
p = pubkey.getStrongPrime(bits>>1, obj.e, 1e-12, randfunc)
|
||||||
|
q = pubkey.getStrongPrime(bits - (bits>>1), obj.e, 1e-12, randfunc)
|
||||||
|
|
||||||
|
# It's OK for p to be larger than q, but let's be
|
||||||
|
# kind to the function that will invert it for
|
||||||
|
# th calculation of u.
|
||||||
|
if p > q:
|
||||||
|
(p, q)=(q, p)
|
||||||
|
obj.p = p
|
||||||
|
obj.q = q
|
||||||
|
|
||||||
|
if progress_func:
|
||||||
|
progress_func('u\n')
|
||||||
|
obj.u = pubkey.inverse(obj.p, obj.q)
|
||||||
|
obj.n = obj.p*obj.q
|
||||||
|
|
||||||
|
if progress_func:
|
||||||
|
progress_func('d\n')
|
||||||
|
obj.d=pubkey.inverse(obj.e, (obj.p-1)*(obj.q-1))
|
||||||
|
|
||||||
|
assert bits <= 1+obj.size(), "Generated key is too small"
|
||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
|
class RSAobj(pubkey.pubkey):
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
"""size() : int
|
||||||
|
Return the maximum number of bits that can be handled by this key.
|
||||||
|
"""
|
||||||
|
return number.size(self.n) - 1
|
||||||
|
|
41
Lib/site-packages/Crypto/PublicKey/__init__.py
Normal file
41
Lib/site-packages/Crypto/PublicKey/__init__.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Public-key encryption and signature algorithms.
|
||||||
|
|
||||||
|
Public-key encryption uses two different keys, one for encryption and
|
||||||
|
one for decryption. The encryption key can be made public, and the
|
||||||
|
decryption key is kept private. Many public-key algorithms can also
|
||||||
|
be used to sign messages, and some can *only* be used for signatures.
|
||||||
|
|
||||||
|
======================== =============================================
|
||||||
|
Module Description
|
||||||
|
======================== =============================================
|
||||||
|
Crypto.PublicKey.DSA Digital Signature Algorithm (Signature only)
|
||||||
|
Crypto.PublicKey.ElGamal (Signing and encryption)
|
||||||
|
Crypto.PublicKey.RSA (Signing, encryption, and blinding)
|
||||||
|
======================== =============================================
|
||||||
|
|
||||||
|
:undocumented: _DSA, _RSA, _fastmath, _slowmath, pubkey
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['RSA', 'DSA', 'ElGamal']
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
187
Lib/site-packages/Crypto/PublicKey/_slowmath.py
Normal file
187
Lib/site-packages/Crypto/PublicKey/_slowmath.py
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# PubKey/RSA/_slowmath.py : Pure Python implementation of the RSA portions of _fastmath
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Pure Python implementation of the RSA-related portions of Crypto.PublicKey._fastmath."""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
__all__ = ['rsa_construct']
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.number import size, inverse, GCD
|
||||||
|
|
||||||
|
class error(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class _RSAKey(object):
|
||||||
|
def _blind(self, m, r):
|
||||||
|
# compute r**e * m (mod n)
|
||||||
|
return m * pow(r, self.e, self.n)
|
||||||
|
|
||||||
|
def _unblind(self, m, r):
|
||||||
|
# compute m / r (mod n)
|
||||||
|
return inverse(r, self.n) * m % self.n
|
||||||
|
|
||||||
|
def _decrypt(self, c):
|
||||||
|
# compute c**d (mod n)
|
||||||
|
if not self.has_private():
|
||||||
|
raise TypeError("No private key")
|
||||||
|
if (hasattr(self,'p') and hasattr(self,'q') and hasattr(self,'u')):
|
||||||
|
m1 = pow(c, self.d % (self.p-1), self.p)
|
||||||
|
m2 = pow(c, self.d % (self.q-1), self.q)
|
||||||
|
h = m2 - m1
|
||||||
|
if (h<0):
|
||||||
|
h = h + self.q
|
||||||
|
h = h*self.u % self.q
|
||||||
|
return h*self.p+m1
|
||||||
|
return pow(c, self.d, self.n)
|
||||||
|
|
||||||
|
def _encrypt(self, m):
|
||||||
|
# compute m**d (mod n)
|
||||||
|
return pow(m, self.e, self.n)
|
||||||
|
|
||||||
|
def _sign(self, m): # alias for _decrypt
|
||||||
|
if not self.has_private():
|
||||||
|
raise TypeError("No private key")
|
||||||
|
return self._decrypt(m)
|
||||||
|
|
||||||
|
def _verify(self, m, sig):
|
||||||
|
return self._encrypt(sig) == m
|
||||||
|
|
||||||
|
def has_private(self):
|
||||||
|
return hasattr(self, 'd')
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
"""Return the maximum number of bits that can be encrypted"""
|
||||||
|
return size(self.n) - 1
|
||||||
|
|
||||||
|
def rsa_construct(n, e, d=None, p=None, q=None, u=None):
|
||||||
|
"""Construct an RSAKey object"""
|
||||||
|
assert isinstance(n, int)
|
||||||
|
assert isinstance(e, int)
|
||||||
|
assert isinstance(d, (int, type(None)))
|
||||||
|
assert isinstance(p, (int, type(None)))
|
||||||
|
assert isinstance(q, (int, type(None)))
|
||||||
|
assert isinstance(u, (int, type(None)))
|
||||||
|
obj = _RSAKey()
|
||||||
|
obj.n = n
|
||||||
|
obj.e = e
|
||||||
|
if d is None:
|
||||||
|
return obj
|
||||||
|
obj.d = d
|
||||||
|
if p is not None and q is not None:
|
||||||
|
obj.p = p
|
||||||
|
obj.q = q
|
||||||
|
else:
|
||||||
|
# Compute factors p and q from the private exponent d.
|
||||||
|
# We assume that n has no more than two factors.
|
||||||
|
# See 8.2.2(i) in Handbook of Applied Cryptography.
|
||||||
|
ktot = d*e-1
|
||||||
|
# The quantity d*e-1 is a multiple of phi(n), even,
|
||||||
|
# and can be represented as t*2^s.
|
||||||
|
t = ktot
|
||||||
|
while t%2==0:
|
||||||
|
t=divmod(t,2)[0]
|
||||||
|
# Cycle through all multiplicative inverses in Zn.
|
||||||
|
# The algorithm is non-deterministic, but there is a 50% chance
|
||||||
|
# any candidate a leads to successful factoring.
|
||||||
|
# See "Digitalized Signatures and Public Key Functions as Intractable
|
||||||
|
# as Factorization", M. Rabin, 1979
|
||||||
|
spotted = 0
|
||||||
|
a = 2
|
||||||
|
while not spotted and a<100:
|
||||||
|
k = t
|
||||||
|
# Cycle through all values a^{t*2^i}=a^k
|
||||||
|
while k<ktot:
|
||||||
|
cand = pow(a,k,n)
|
||||||
|
# Check if a^k is a non-trivial root of unity (mod n)
|
||||||
|
if cand!=1 and cand!=(n-1) and pow(cand,2,n)==1:
|
||||||
|
# We have found a number such that (cand-1)(cand+1)=0 (mod n).
|
||||||
|
# Either of the terms divides n.
|
||||||
|
obj.p = GCD(cand+1,n)
|
||||||
|
spotted = 1
|
||||||
|
break
|
||||||
|
k = k*2
|
||||||
|
# This value was not any good... let's try another!
|
||||||
|
a = a+2
|
||||||
|
if not spotted:
|
||||||
|
raise ValueError("Unable to compute factors p and q from exponent d.")
|
||||||
|
# Found !
|
||||||
|
assert ((n % obj.p)==0)
|
||||||
|
obj.q = divmod(n,obj.p)[0]
|
||||||
|
if u is not None:
|
||||||
|
obj.u = u
|
||||||
|
else:
|
||||||
|
obj.u = inverse(obj.p, obj.q)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
class _DSAKey(object):
|
||||||
|
def size(self):
|
||||||
|
"""Return the maximum number of bits that can be encrypted"""
|
||||||
|
return size(self.p) - 1
|
||||||
|
|
||||||
|
def has_private(self):
|
||||||
|
return hasattr(self, 'x')
|
||||||
|
|
||||||
|
def _sign(self, m, k): # alias for _decrypt
|
||||||
|
# SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API.
|
||||||
|
if not self.has_private():
|
||||||
|
raise TypeError("No private key")
|
||||||
|
if not (1 < k < self.q):
|
||||||
|
raise ValueError("k is not between 2 and q-1")
|
||||||
|
inv_k = inverse(k, self.q) # Compute k**-1 mod q
|
||||||
|
r = pow(self.g, k, self.p) % self.q # r = (g**k mod p) mod q
|
||||||
|
s = (inv_k * (m + self.x * r)) % self.q
|
||||||
|
return (r, s)
|
||||||
|
|
||||||
|
def _verify(self, m, r, s):
|
||||||
|
# SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API.
|
||||||
|
if not (0 < r < self.q) or not (0 < s < self.q):
|
||||||
|
return False
|
||||||
|
w = inverse(s, self.q)
|
||||||
|
u1 = (m*w) % self.q
|
||||||
|
u2 = (r*w) % self.q
|
||||||
|
v = (pow(self.g, u1, self.p) * pow(self.y, u2, self.p) % self.p) % self.q
|
||||||
|
return v == r
|
||||||
|
|
||||||
|
def dsa_construct(y, g, p, q, x=None):
|
||||||
|
assert isinstance(y, int)
|
||||||
|
assert isinstance(g, int)
|
||||||
|
assert isinstance(p, int)
|
||||||
|
assert isinstance(q, int)
|
||||||
|
assert isinstance(x, (int, type(None)))
|
||||||
|
obj = _DSAKey()
|
||||||
|
obj.y = y
|
||||||
|
obj.g = g
|
||||||
|
obj.p = p
|
||||||
|
obj.q = q
|
||||||
|
if x is not None: obj.x = x
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||||
|
|
240
Lib/site-packages/Crypto/PublicKey/pubkey.py
Normal file
240
Lib/site-packages/Crypto/PublicKey/pubkey.py
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
#
|
||||||
|
# pubkey.py : Internal functions for public key operations
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# Written by Andrew Kuchling, Paul Swartz, and others
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import types, warnings
|
||||||
|
from Crypto.Util.number import *
|
||||||
|
|
||||||
|
# Basic public key class
|
||||||
|
class pubkey:
|
||||||
|
"""An abstract class for a public key object.
|
||||||
|
|
||||||
|
:undocumented: __getstate__, __setstate__, __eq__, __ne__, validate
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __getstate__(self):
|
||||||
|
"""To keep key objects platform-independent, the key data is
|
||||||
|
converted to standard Python long integers before being
|
||||||
|
written out. It will then be reconverted as necessary on
|
||||||
|
restoration."""
|
||||||
|
d=self.__dict__
|
||||||
|
for key in self.keydata:
|
||||||
|
if key in d: d[key]=int(d[key])
|
||||||
|
return d
|
||||||
|
|
||||||
|
def __setstate__(self, d):
|
||||||
|
"""On unpickling a key object, the key data is converted to the big
|
||||||
|
number representation being used, whether that is Python long
|
||||||
|
integers, MPZ objects, or whatever."""
|
||||||
|
for key in self.keydata:
|
||||||
|
if key in d: self.__dict__[key]=bignum(d[key])
|
||||||
|
|
||||||
|
def encrypt(self, plaintext, K):
|
||||||
|
"""Encrypt a piece of data.
|
||||||
|
|
||||||
|
:Parameter plaintext: The piece of data to encrypt.
|
||||||
|
:Type plaintext: byte string or long
|
||||||
|
|
||||||
|
:Parameter K: A random parameter required by some algorithms
|
||||||
|
:Type K: byte string or long
|
||||||
|
|
||||||
|
:Return: A tuple with two items. Each item is of the same type as the
|
||||||
|
plaintext (string or long).
|
||||||
|
"""
|
||||||
|
wasString=0
|
||||||
|
if isinstance(plaintext, bytes):
|
||||||
|
plaintext=bytes_to_long(plaintext) ; wasString=1
|
||||||
|
if isinstance(K, bytes):
|
||||||
|
K=bytes_to_long(K)
|
||||||
|
ciphertext=self._encrypt(plaintext, K)
|
||||||
|
if wasString: return tuple(map(long_to_bytes, ciphertext))
|
||||||
|
else: return ciphertext
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt a piece of data.
|
||||||
|
|
||||||
|
:Parameter ciphertext: The piece of data to decrypt.
|
||||||
|
:Type ciphertext: byte string, long or a 2-item tuple as returned by `encrypt`
|
||||||
|
|
||||||
|
:Return: A byte string if ciphertext was a byte string or a tuple
|
||||||
|
of byte strings. A long otherwise.
|
||||||
|
"""
|
||||||
|
wasString=0
|
||||||
|
if not isinstance(ciphertext, tuple):
|
||||||
|
ciphertext=(ciphertext,)
|
||||||
|
if isinstance(ciphertext[0], bytes):
|
||||||
|
ciphertext=tuple(map(bytes_to_long, ciphertext)) ; wasString=1
|
||||||
|
plaintext=self._decrypt(ciphertext)
|
||||||
|
if wasString: return long_to_bytes(plaintext)
|
||||||
|
else: return plaintext
|
||||||
|
|
||||||
|
def sign(self, M, K):
|
||||||
|
"""Sign a piece of data.
|
||||||
|
|
||||||
|
:Parameter M: The piece of data to encrypt.
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter K: A random parameter required by some algorithms
|
||||||
|
:Type K: byte string or long
|
||||||
|
|
||||||
|
:Return: A tuple with two items.
|
||||||
|
"""
|
||||||
|
if (not self.has_private()):
|
||||||
|
raise TypeError('Private key not available in this object')
|
||||||
|
if isinstance(M, bytes): M=bytes_to_long(M)
|
||||||
|
if isinstance(K, bytes): K=bytes_to_long(K)
|
||||||
|
return self._sign(M, K)
|
||||||
|
|
||||||
|
def verify (self, M, signature):
|
||||||
|
"""Verify the validity of a signature.
|
||||||
|
|
||||||
|
:Parameter M: The expected message.
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter signature: The signature to verify.
|
||||||
|
:Type signature: tuple with two items, as return by `sign`
|
||||||
|
|
||||||
|
:Return: True if the signature is correct, False otherwise.
|
||||||
|
"""
|
||||||
|
if isinstance(M, bytes): M=bytes_to_long(M)
|
||||||
|
return self._verify(M, signature)
|
||||||
|
|
||||||
|
# alias to compensate for the old validate() name
|
||||||
|
def validate (self, M, signature):
|
||||||
|
warnings.warn("validate() method name is obsolete; use verify()",
|
||||||
|
DeprecationWarning)
|
||||||
|
|
||||||
|
def blind(self, M, B):
|
||||||
|
"""Blind a message to prevent certain side-channel attacks.
|
||||||
|
|
||||||
|
:Parameter M: The message to blind.
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter B: Blinding factor.
|
||||||
|
:Type B: byte string or long
|
||||||
|
|
||||||
|
:Return: A byte string if M was so. A long otherwise.
|
||||||
|
"""
|
||||||
|
wasString=0
|
||||||
|
if isinstance(M, bytes):
|
||||||
|
M=bytes_to_long(M) ; wasString=1
|
||||||
|
if isinstance(B, bytes): B=bytes_to_long(B)
|
||||||
|
blindedmessage=self._blind(M, B)
|
||||||
|
if wasString: return long_to_bytes(blindedmessage)
|
||||||
|
else: return blindedmessage
|
||||||
|
|
||||||
|
def unblind(self, M, B):
|
||||||
|
"""Unblind a message after cryptographic processing.
|
||||||
|
|
||||||
|
:Parameter M: The encoded message to unblind.
|
||||||
|
:Type M: byte string or long
|
||||||
|
|
||||||
|
:Parameter B: Blinding factor.
|
||||||
|
:Type B: byte string or long
|
||||||
|
"""
|
||||||
|
wasString=0
|
||||||
|
if isinstance(M, bytes):
|
||||||
|
M=bytes_to_long(M) ; wasString=1
|
||||||
|
if isinstance(B, bytes): B=bytes_to_long(B)
|
||||||
|
unblindedmessage=self._unblind(M, B)
|
||||||
|
if wasString: return long_to_bytes(unblindedmessage)
|
||||||
|
else: return unblindedmessage
|
||||||
|
|
||||||
|
|
||||||
|
# The following methods will usually be left alone, except for
|
||||||
|
# signature-only algorithms. They both return Boolean values
|
||||||
|
# recording whether this key's algorithm can sign and encrypt.
|
||||||
|
def can_sign (self):
|
||||||
|
"""Tell if the algorithm can deal with cryptographic signatures.
|
||||||
|
|
||||||
|
This property concerns the *algorithm*, not the key itself.
|
||||||
|
It may happen that this particular key object hasn't got
|
||||||
|
the private information required to generate a signature.
|
||||||
|
|
||||||
|
:Return: boolean
|
||||||
|
"""
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def can_encrypt (self):
|
||||||
|
"""Tell if the algorithm can deal with data encryption.
|
||||||
|
|
||||||
|
This property concerns the *algorithm*, not the key itself.
|
||||||
|
It may happen that this particular key object hasn't got
|
||||||
|
the private information required to decrypt data.
|
||||||
|
|
||||||
|
:Return: boolean
|
||||||
|
"""
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def can_blind (self):
|
||||||
|
"""Tell if the algorithm can deal with data blinding.
|
||||||
|
|
||||||
|
This property concerns the *algorithm*, not the key itself.
|
||||||
|
It may happen that this particular key object hasn't got
|
||||||
|
the private information required carry out blinding.
|
||||||
|
|
||||||
|
:Return: boolean
|
||||||
|
"""
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# The following methods will certainly be overridden by
|
||||||
|
# subclasses.
|
||||||
|
|
||||||
|
def size (self):
|
||||||
|
"""Tell the maximum number of bits that can be handled by this key.
|
||||||
|
|
||||||
|
:Return: int
|
||||||
|
"""
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def has_private (self):
|
||||||
|
"""Tell if the key object contains private components.
|
||||||
|
|
||||||
|
:Return: bool
|
||||||
|
"""
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def publickey (self):
|
||||||
|
"""Construct a new key carrying only the public information.
|
||||||
|
|
||||||
|
:Return: A new `pubkey` object.
|
||||||
|
"""
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __eq__ (self, other):
|
||||||
|
"""__eq__(other): 0, 1
|
||||||
|
Compare us to other for equality.
|
||||||
|
"""
|
||||||
|
return self.__getstate__() == other.__getstate__()
|
||||||
|
|
||||||
|
def __ne__ (self, other):
|
||||||
|
"""__ne__(other): 0, 1
|
||||||
|
Compare us to other for inequality.
|
||||||
|
"""
|
||||||
|
return not self.__eq__(other)
|
171
Lib/site-packages/Crypto/Random/Fortuna/FortunaAccumulator.py
Normal file
171
Lib/site-packages/Crypto/Random/Fortuna/FortunaAccumulator.py
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
# -*- coding: ascii -*-
|
||||||
|
#
|
||||||
|
# FortunaAccumulator.py : Fortuna's internal accumulator
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
from binascii import b2a_hex
|
||||||
|
import time
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
from Crypto.pct_warnings import ClockRewindWarning
|
||||||
|
from . import SHAd256
|
||||||
|
|
||||||
|
from . import FortunaGenerator
|
||||||
|
|
||||||
|
class FortunaPool(object):
|
||||||
|
"""Fortuna pool type
|
||||||
|
|
||||||
|
This object acts like a hash object, with the following differences:
|
||||||
|
|
||||||
|
- It keeps a count (the .length attribute) of the number of bytes that
|
||||||
|
have been added to the pool
|
||||||
|
- It supports a .reset() method for in-place reinitialization
|
||||||
|
- The method to add bytes to the pool is .append(), not .update().
|
||||||
|
"""
|
||||||
|
|
||||||
|
digest_size = SHAd256.digest_size
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def append(self, data):
|
||||||
|
self._h.update(data)
|
||||||
|
self.length += len(data)
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
return self._h.digest()
|
||||||
|
|
||||||
|
def hexdigest(self):
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
return b2a_hex(self.digest())
|
||||||
|
else:
|
||||||
|
return b2a_hex(self.digest()).decode()
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self._h = SHAd256.new()
|
||||||
|
self.length = 0
|
||||||
|
|
||||||
|
def which_pools(r):
|
||||||
|
"""Return a list of pools indexes (in range(32)) that are to be included during reseed number r.
|
||||||
|
|
||||||
|
According to _Practical Cryptography_, chapter 10.5.2 "Pools":
|
||||||
|
|
||||||
|
"Pool P_i is included if 2**i is a divisor of r. Thus P_0 is used
|
||||||
|
every reseed, P_1 every other reseed, P_2 every fourth reseed, etc."
|
||||||
|
"""
|
||||||
|
# This is a separate function so that it can be unit-tested.
|
||||||
|
assert r >= 1
|
||||||
|
retval = []
|
||||||
|
mask = 0
|
||||||
|
for i in range(32):
|
||||||
|
# "Pool P_i is included if 2**i is a divisor of [reseed_count]"
|
||||||
|
if (r & mask) == 0:
|
||||||
|
retval.append(i)
|
||||||
|
else:
|
||||||
|
break # optimization. once this fails, it always fails
|
||||||
|
mask = (mask << 1) | 1
|
||||||
|
return retval
|
||||||
|
|
||||||
|
class FortunaAccumulator(object):
|
||||||
|
|
||||||
|
# An estimate of how many bytes we must append to pool 0 before it will
|
||||||
|
# contain 128 bits of entropy (with respect to an attack). We reseed the
|
||||||
|
# generator only after pool 0 contains `min_pool_size` bytes. Note that
|
||||||
|
# unlike with some other PRNGs, Fortuna's security does not rely on the
|
||||||
|
# accuracy of this estimate---we can accord to be optimistic here.
|
||||||
|
min_pool_size = 64 # size in bytes
|
||||||
|
|
||||||
|
# If an attacker can predict some (but not all) of our entropy sources, the
|
||||||
|
# `min_pool_size` check may not be sufficient to prevent a successful state
|
||||||
|
# compromise extension attack. To resist this attack, Fortuna spreads the
|
||||||
|
# input across 32 pools, which are then consumed (to reseed the output
|
||||||
|
# generator) with exponentially decreasing frequency.
|
||||||
|
#
|
||||||
|
# In order to prevent an attacker from gaining knowledge of all 32 pools
|
||||||
|
# before we have a chance to fill them with enough information that the
|
||||||
|
# attacker cannot predict, we impose a rate limit of 10 reseeds/second (one
|
||||||
|
# per 100 ms). This ensures that a hypothetical 33rd pool would only be
|
||||||
|
# needed after a minimum of 13 years of sustained attack.
|
||||||
|
reseed_interval = 0.100 # time in seconds
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.reseed_count = 0
|
||||||
|
self.generator = FortunaGenerator.AESGenerator()
|
||||||
|
self.last_reseed = None
|
||||||
|
|
||||||
|
# Initialize 32 FortunaPool instances.
|
||||||
|
# NB: This is _not_ equivalent to [FortunaPool()]*32, which would give
|
||||||
|
# us 32 references to the _same_ FortunaPool instance (and cause the
|
||||||
|
# assertion below to fail).
|
||||||
|
self.pools = [FortunaPool() for i in range(32)] # 32 pools
|
||||||
|
assert(self.pools[0] is not self.pools[1])
|
||||||
|
|
||||||
|
def _forget_last_reseed(self):
|
||||||
|
# This is not part of the standard Fortuna definition, and using this
|
||||||
|
# function frequently can weaken Fortuna's ability to resist a state
|
||||||
|
# compromise extension attack, but we need this in order to properly
|
||||||
|
# implement Crypto.Random.atfork(). Otherwise, forked child processes
|
||||||
|
# might continue to use their parent's PRNG state for up to 100ms in
|
||||||
|
# some cases. (e.g. CVE-2013-1445)
|
||||||
|
self.last_reseed = None
|
||||||
|
|
||||||
|
def random_data(self, bytes):
|
||||||
|
current_time = time.time()
|
||||||
|
if (self.last_reseed is not None and self.last_reseed > current_time): # Avoid float comparison to None to make Py3k happy
|
||||||
|
warnings.warn("Clock rewind detected. Resetting last_reseed.", ClockRewindWarning)
|
||||||
|
self.last_reseed = None
|
||||||
|
if (self.pools[0].length >= self.min_pool_size and
|
||||||
|
(self.last_reseed is None or
|
||||||
|
current_time > self.last_reseed + self.reseed_interval)):
|
||||||
|
self._reseed(current_time)
|
||||||
|
# The following should fail if we haven't seeded the pool yet.
|
||||||
|
return self.generator.pseudo_random_data(bytes)
|
||||||
|
|
||||||
|
def _reseed(self, current_time=None):
|
||||||
|
if current_time is None:
|
||||||
|
current_time = time.time()
|
||||||
|
seed = []
|
||||||
|
self.reseed_count += 1
|
||||||
|
self.last_reseed = current_time
|
||||||
|
for i in which_pools(self.reseed_count):
|
||||||
|
seed.append(self.pools[i].digest())
|
||||||
|
self.pools[i].reset()
|
||||||
|
|
||||||
|
seed = b("").join(seed)
|
||||||
|
self.generator.reseed(seed)
|
||||||
|
|
||||||
|
def add_random_event(self, source_number, pool_number, data):
|
||||||
|
assert 1 <= len(data) <= 32
|
||||||
|
assert 0 <= source_number <= 255
|
||||||
|
assert 0 <= pool_number <= 31
|
||||||
|
self.pools[pool_number].append(bchr(source_number))
|
||||||
|
self.pools[pool_number].append(bchr(len(data)))
|
||||||
|
self.pools[pool_number].append(data)
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
132
Lib/site-packages/Crypto/Random/Fortuna/FortunaGenerator.py
Normal file
132
Lib/site-packages/Crypto/Random/Fortuna/FortunaGenerator.py
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
# -*- coding: ascii -*-
|
||||||
|
#
|
||||||
|
# FortunaGenerator.py : Fortuna's internal PRNG
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] is 2 and sys.version_info[1] is 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
import struct
|
||||||
|
|
||||||
|
from Crypto.Util.number import ceil_shift, exact_log2, exact_div
|
||||||
|
from Crypto.Util import Counter
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
|
||||||
|
from . import SHAd256
|
||||||
|
|
||||||
|
class AESGenerator(object):
|
||||||
|
"""The Fortuna "generator"
|
||||||
|
|
||||||
|
This is used internally by the Fortuna PRNG to generate arbitrary amounts
|
||||||
|
of pseudorandom data from a smaller amount of seed data.
|
||||||
|
|
||||||
|
The output is generated by running AES-256 in counter mode and re-keying
|
||||||
|
after every mebibyte (2**16 blocks) of output.
|
||||||
|
"""
|
||||||
|
|
||||||
|
block_size = AES.block_size # output block size in octets (128 bits)
|
||||||
|
key_size = 32 # key size in octets (256 bits)
|
||||||
|
|
||||||
|
# Because of the birthday paradox, we expect to find approximately one
|
||||||
|
# collision for every 2**64 blocks of output from a real random source.
|
||||||
|
# However, this code generates pseudorandom data by running AES in
|
||||||
|
# counter mode, so there will be no collisions until the counter
|
||||||
|
# (theoretically) wraps around at 2**128 blocks. Thus, in order to prevent
|
||||||
|
# Fortuna's pseudorandom output from deviating perceptibly from a true
|
||||||
|
# random source, Ferguson and Schneier specify a limit of 2**16 blocks
|
||||||
|
# without rekeying.
|
||||||
|
max_blocks_per_request = 2**16 # Allow no more than this number of blocks per _pseudo_random_data request
|
||||||
|
|
||||||
|
_four_kiblocks_of_zeros = b("\0") * block_size * 4096
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.counter = Counter.new(nbits=self.block_size*8, initial_value=0, little_endian=True)
|
||||||
|
self.key = None
|
||||||
|
|
||||||
|
# Set some helper constants
|
||||||
|
self.block_size_shift = exact_log2(self.block_size)
|
||||||
|
assert (1 << self.block_size_shift) == self.block_size
|
||||||
|
|
||||||
|
self.blocks_per_key = exact_div(self.key_size, self.block_size)
|
||||||
|
assert self.key_size == self.blocks_per_key * self.block_size
|
||||||
|
|
||||||
|
self.max_bytes_per_request = self.max_blocks_per_request * self.block_size
|
||||||
|
|
||||||
|
def reseed(self, seed):
|
||||||
|
if self.key is None:
|
||||||
|
self.key = b("\0") * self.key_size
|
||||||
|
|
||||||
|
self._set_key(SHAd256.new(self.key + seed).digest())
|
||||||
|
self.counter() # increment counter
|
||||||
|
assert len(self.key) == self.key_size
|
||||||
|
|
||||||
|
def pseudo_random_data(self, bytes):
|
||||||
|
assert bytes >= 0
|
||||||
|
|
||||||
|
num_full_blocks = bytes >> 20
|
||||||
|
remainder = bytes & ((1<<20)-1)
|
||||||
|
|
||||||
|
retval = []
|
||||||
|
for i in range(num_full_blocks):
|
||||||
|
retval.append(self._pseudo_random_data(1<<20))
|
||||||
|
retval.append(self._pseudo_random_data(remainder))
|
||||||
|
|
||||||
|
return b("").join(retval)
|
||||||
|
|
||||||
|
def _set_key(self, key):
|
||||||
|
self.key = key
|
||||||
|
self._cipher = AES.new(key, AES.MODE_CTR, counter=self.counter)
|
||||||
|
|
||||||
|
def _pseudo_random_data(self, bytes):
|
||||||
|
if not (0 <= bytes <= self.max_bytes_per_request):
|
||||||
|
raise AssertionError("You cannot ask for more than 1 MiB of data per request")
|
||||||
|
|
||||||
|
num_blocks = ceil_shift(bytes, self.block_size_shift) # num_blocks = ceil(bytes / self.block_size)
|
||||||
|
|
||||||
|
# Compute the output
|
||||||
|
retval = self._generate_blocks(num_blocks)[:bytes]
|
||||||
|
|
||||||
|
# Switch to a new key to avoid later compromises of this output (i.e.
|
||||||
|
# state compromise extension attacks)
|
||||||
|
self._set_key(self._generate_blocks(self.blocks_per_key))
|
||||||
|
|
||||||
|
assert len(retval) == bytes
|
||||||
|
assert len(self.key) == self.key_size
|
||||||
|
|
||||||
|
return retval
|
||||||
|
|
||||||
|
def _generate_blocks(self, num_blocks):
|
||||||
|
if self.key is None:
|
||||||
|
raise AssertionError("generator must be seeded before use")
|
||||||
|
assert 0 <= num_blocks <= self.max_blocks_per_request
|
||||||
|
retval = []
|
||||||
|
for i in range(num_blocks >> 12): # xrange(num_blocks / 4096)
|
||||||
|
retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros))
|
||||||
|
remaining_bytes = (num_blocks & 4095) << self.block_size_shift # (num_blocks % 4095) * self.block_size
|
||||||
|
retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros[:remaining_bytes]))
|
||||||
|
return b("").join(retval)
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
98
Lib/site-packages/Crypto/Random/Fortuna/SHAd256.py
Normal file
98
Lib/site-packages/Crypto/Random/Fortuna/SHAd256.py
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
# -*- coding: ascii -*-
|
||||||
|
#
|
||||||
|
# Random/Fortuna/SHAd256.py : SHA_d-256 hash function implementation
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""\
|
||||||
|
SHA_d-256 hash function implementation.
|
||||||
|
|
||||||
|
This module should comply with PEP 247.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
__all__ = ['new', 'digest_size']
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
from binascii import b2a_hex
|
||||||
|
|
||||||
|
from Crypto.Hash import SHA256
|
||||||
|
|
||||||
|
assert SHA256.digest_size == 32
|
||||||
|
|
||||||
|
class _SHAd256(object):
|
||||||
|
"""SHA-256, doubled.
|
||||||
|
|
||||||
|
Returns SHA-256(SHA-256(data)).
|
||||||
|
"""
|
||||||
|
|
||||||
|
digest_size = SHA256.digest_size
|
||||||
|
|
||||||
|
_internal = object()
|
||||||
|
|
||||||
|
def __init__(self, internal_api_check, sha256_hash_obj):
|
||||||
|
if internal_api_check is not self._internal:
|
||||||
|
raise AssertionError("Do not instantiate this class directly. Use %s.new()" % (__name__,))
|
||||||
|
self._h = sha256_hash_obj
|
||||||
|
|
||||||
|
# PEP 247 "copy" method
|
||||||
|
def copy(self):
|
||||||
|
"""Return a copy of this hashing object"""
|
||||||
|
return _SHAd256(SHAd256._internal, self._h.copy())
|
||||||
|
|
||||||
|
# PEP 247 "digest" method
|
||||||
|
def digest(self):
|
||||||
|
"""Return the hash value of this object as a binary string"""
|
||||||
|
retval = SHA256.new(self._h.digest()).digest()
|
||||||
|
assert len(retval) == 32
|
||||||
|
return retval
|
||||||
|
|
||||||
|
# PEP 247 "hexdigest" method
|
||||||
|
def hexdigest(self):
|
||||||
|
"""Return the hash value of this object as a (lowercase) hexadecimal string"""
|
||||||
|
retval = b2a_hex(self.digest())
|
||||||
|
assert len(retval) == 64
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
return retval
|
||||||
|
else:
|
||||||
|
return retval.decode()
|
||||||
|
|
||||||
|
# PEP 247 "update" method
|
||||||
|
def update(self, data):
|
||||||
|
self._h.update(data)
|
||||||
|
|
||||||
|
# PEP 247 module-level "digest_size" variable
|
||||||
|
digest_size = _SHAd256.digest_size
|
||||||
|
|
||||||
|
# PEP 247 module-level "new" function
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a new SHAd256 hashing object"""
|
||||||
|
if not data:
|
||||||
|
data=b("")
|
||||||
|
sha = _SHAd256(_SHAd256._internal, SHA256.new(data))
|
||||||
|
sha.new = globals()['new']
|
||||||
|
return sha
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
0
Lib/site-packages/Crypto/Random/Fortuna/__init__.py
Normal file
0
Lib/site-packages/Crypto/Random/Fortuna/__init__.py
Normal file
40
Lib/site-packages/Crypto/Random/OSRNG/__init__.py
Normal file
40
Lib/site-packages/Crypto/Random/OSRNG/__init__.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#
|
||||||
|
# Random/OSRNG/__init__.py : Platform-independent OS RNG API
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Provides a platform-independent interface to the random number generators
|
||||||
|
supplied by various operating systems."""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
if os.name == 'posix':
|
||||||
|
from Crypto.Random.OSRNG.posix import new
|
||||||
|
elif os.name == 'nt':
|
||||||
|
from Crypto.Random.OSRNG.nt import new
|
||||||
|
elif hasattr(os, 'urandom'):
|
||||||
|
from Crypto.Random.OSRNG.fallback import new
|
||||||
|
else:
|
||||||
|
raise ImportError("Not implemented")
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
46
Lib/site-packages/Crypto/Random/OSRNG/fallback.py
Normal file
46
Lib/site-packages/Crypto/Random/OSRNG/fallback.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#
|
||||||
|
# Random/OSRNG/fallback.py : Fallback entropy source for systems with os.urandom
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
__all__ = ['PythonOSURandomRNG']
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from .rng_base import BaseRNG
|
||||||
|
|
||||||
|
class PythonOSURandomRNG(BaseRNG):
|
||||||
|
|
||||||
|
name = "<os.urandom>"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._read = os.urandom
|
||||||
|
BaseRNG.__init__(self)
|
||||||
|
|
||||||
|
def _close(self):
|
||||||
|
self._read = None
|
||||||
|
|
||||||
|
def new(*args, **kwargs):
|
||||||
|
return PythonOSURandomRNG(*args, **kwargs)
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
74
Lib/site-packages/Crypto/Random/OSRNG/nt.py
Normal file
74
Lib/site-packages/Crypto/Random/OSRNG/nt.py
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#
|
||||||
|
# Random/OSRNG/nt.py : OS entropy source for MS Windows
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
__all__ = ['WindowsRNG']
|
||||||
|
|
||||||
|
from . import winrandom
|
||||||
|
from .rng_base import BaseRNG
|
||||||
|
|
||||||
|
class WindowsRNG(BaseRNG):
|
||||||
|
|
||||||
|
name = "<CryptGenRandom>"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.__winrand = winrandom.new()
|
||||||
|
BaseRNG.__init__(self)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
"""Work around weakness in Windows RNG.
|
||||||
|
|
||||||
|
The CryptGenRandom mechanism in some versions of Windows allows an
|
||||||
|
attacker to learn 128 KiB of past and future output. As a workaround,
|
||||||
|
this function reads 128 KiB of 'random' data from Windows and discards
|
||||||
|
it.
|
||||||
|
|
||||||
|
For more information about the weaknesses in CryptGenRandom, see
|
||||||
|
_Cryptanalysis of the Random Number Generator of the Windows Operating
|
||||||
|
System_, by Leo Dorrendorf and Zvi Gutterman and Benny Pinkas
|
||||||
|
http://eprint.iacr.org/2007/419
|
||||||
|
"""
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("I/O operation on closed file")
|
||||||
|
data = self.__winrand.get_bytes(128*1024)
|
||||||
|
assert (len(data) == 128*1024)
|
||||||
|
BaseRNG.flush(self)
|
||||||
|
|
||||||
|
def _close(self):
|
||||||
|
self.__winrand = None
|
||||||
|
|
||||||
|
def _read(self, N):
|
||||||
|
# Unfortunately, research shows that CryptGenRandom doesn't provide
|
||||||
|
# forward secrecy and fails the next-bit test unless we apply a
|
||||||
|
# workaround, which we do here. See http://eprint.iacr.org/2007/419
|
||||||
|
# for information on the vulnerability.
|
||||||
|
self.flush()
|
||||||
|
data = self.__winrand.get_bytes(N)
|
||||||
|
self.flush()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def new(*args, **kwargs):
|
||||||
|
return WindowsRNG(*args, **kwargs)
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
86
Lib/site-packages/Crypto/Random/OSRNG/posix.py
Normal file
86
Lib/site-packages/Crypto/Random/OSRNG/posix.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#
|
||||||
|
# Random/OSRNG/posix.py : OS entropy source for POSIX systems
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
__all__ = ['DevURandomRNG']
|
||||||
|
|
||||||
|
import errno
|
||||||
|
import os
|
||||||
|
import stat
|
||||||
|
|
||||||
|
from .rng_base import BaseRNG
|
||||||
|
from Crypto.Util.py3compat import b
|
||||||
|
|
||||||
|
class DevURandomRNG(BaseRNG):
|
||||||
|
|
||||||
|
def __init__(self, devname=None):
|
||||||
|
if devname is None:
|
||||||
|
self.name = "/dev/urandom"
|
||||||
|
else:
|
||||||
|
self.name = devname
|
||||||
|
|
||||||
|
# Test that /dev/urandom is a character special device
|
||||||
|
f = open(self.name, "rb", 0)
|
||||||
|
fmode = os.fstat(f.fileno())[stat.ST_MODE]
|
||||||
|
if not stat.S_ISCHR(fmode):
|
||||||
|
f.close()
|
||||||
|
raise TypeError("%r is not a character special device" % (self.name,))
|
||||||
|
|
||||||
|
self.__file = f
|
||||||
|
|
||||||
|
BaseRNG.__init__(self)
|
||||||
|
|
||||||
|
def _close(self):
|
||||||
|
self.__file.close()
|
||||||
|
|
||||||
|
def _read(self, N):
|
||||||
|
# Starting with Python 3 open with buffering=0 returns a FileIO object.
|
||||||
|
# FileIO.read behaves like read(2) and not like fread(3) and thus we
|
||||||
|
# have to handle the case that read returns less data as requested here
|
||||||
|
# more carefully.
|
||||||
|
data = b("")
|
||||||
|
while len(data) < N:
|
||||||
|
try:
|
||||||
|
d = self.__file.read(N - len(data))
|
||||||
|
except IOError as e:
|
||||||
|
# read(2) has been interrupted by a signal; redo the read
|
||||||
|
if e.errno == errno.EINTR:
|
||||||
|
continue
|
||||||
|
raise
|
||||||
|
|
||||||
|
if d is None:
|
||||||
|
# __file is in non-blocking mode and no data is available
|
||||||
|
return data
|
||||||
|
if len(d) == 0:
|
||||||
|
# __file is in blocking mode and arrived at EOF
|
||||||
|
return data
|
||||||
|
|
||||||
|
data += d
|
||||||
|
return data
|
||||||
|
|
||||||
|
def new(*args, **kwargs):
|
||||||
|
return DevURandomRNG(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
88
Lib/site-packages/Crypto/Random/OSRNG/rng_base.py
Normal file
88
Lib/site-packages/Crypto/Random/OSRNG/rng_base.py
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
#
|
||||||
|
# Random/OSRNG/rng_base.py : Base class for OSRNG
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
|
||||||
|
class BaseRNG(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.closed = False
|
||||||
|
self._selftest()
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def _selftest(self):
|
||||||
|
# Test that urandom can return data
|
||||||
|
data = self.read(16)
|
||||||
|
if len(data) != 16:
|
||||||
|
raise AssertionError("read truncated")
|
||||||
|
|
||||||
|
# Test that we get different data every time (if we don't, the RNG is
|
||||||
|
# probably malfunctioning)
|
||||||
|
data2 = self.read(16)
|
||||||
|
if data == data2:
|
||||||
|
raise AssertionError("OS RNG returned duplicate data")
|
||||||
|
|
||||||
|
# PEP 343: Support for the "with" statement
|
||||||
|
def __enter__(self):
|
||||||
|
pass
|
||||||
|
def __exit__(self):
|
||||||
|
"""PEP 343 support"""
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if not self.closed:
|
||||||
|
self._close()
|
||||||
|
self.closed = True
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def read(self, N=-1):
|
||||||
|
"""Return N bytes from the RNG."""
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("I/O operation on closed file")
|
||||||
|
if not isinstance(N, int):
|
||||||
|
raise TypeError("an integer is required")
|
||||||
|
if N < 0:
|
||||||
|
raise ValueError("cannot read to end of infinite stream")
|
||||||
|
elif N == 0:
|
||||||
|
return ""
|
||||||
|
data = self._read(N)
|
||||||
|
if len(data) != N:
|
||||||
|
raise AssertionError("%s produced truncated output (requested %d, got %d)" % (self.name, N, len(data)))
|
||||||
|
return data
|
||||||
|
|
||||||
|
def _close(self):
|
||||||
|
raise NotImplementedError("child class must implement this")
|
||||||
|
|
||||||
|
def _read(self, N):
|
||||||
|
raise NotImplementedError("child class must implement this")
|
||||||
|
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
230
Lib/site-packages/Crypto/Random/_UserFriendlyRNG.py
Normal file
230
Lib/site-packages/Crypto/Random/_UserFriendlyRNG.py
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Random/_UserFriendlyRNG.py : A user-friendly random number generator
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
|
||||||
|
import os
|
||||||
|
import threading
|
||||||
|
import struct
|
||||||
|
import time
|
||||||
|
from math import floor
|
||||||
|
|
||||||
|
from Crypto.Random import OSRNG
|
||||||
|
from Crypto.Random.Fortuna import FortunaAccumulator
|
||||||
|
|
||||||
|
class _EntropySource(object):
|
||||||
|
def __init__(self, accumulator, src_num):
|
||||||
|
self._fortuna = accumulator
|
||||||
|
self._src_num = src_num
|
||||||
|
self._pool_num = 0
|
||||||
|
|
||||||
|
def feed(self, data):
|
||||||
|
self._fortuna.add_random_event(self._src_num, self._pool_num, data)
|
||||||
|
self._pool_num = (self._pool_num + 1) & 31
|
||||||
|
|
||||||
|
class _EntropyCollector(object):
|
||||||
|
|
||||||
|
def __init__(self, accumulator):
|
||||||
|
self._osrng = OSRNG.new()
|
||||||
|
self._osrng_es = _EntropySource(accumulator, 255)
|
||||||
|
self._time_es = _EntropySource(accumulator, 254)
|
||||||
|
self._clock_es = _EntropySource(accumulator, 253)
|
||||||
|
|
||||||
|
def reinit(self):
|
||||||
|
# Add 256 bits to each of the 32 pools, twice. (For a total of 16384
|
||||||
|
# bits collected from the operating system.)
|
||||||
|
for i in range(2):
|
||||||
|
block = self._osrng.read(32*32)
|
||||||
|
for p in range(32):
|
||||||
|
self._osrng_es.feed(block[p*32:(p+1)*32])
|
||||||
|
block = None
|
||||||
|
self._osrng.flush()
|
||||||
|
|
||||||
|
def collect(self):
|
||||||
|
# Collect 64 bits of entropy from the operating system and feed it to Fortuna.
|
||||||
|
self._osrng_es.feed(self._osrng.read(8))
|
||||||
|
|
||||||
|
# Add the fractional part of time.time()
|
||||||
|
t = time.time()
|
||||||
|
self._time_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
|
||||||
|
|
||||||
|
# Add the fractional part of time.clock()
|
||||||
|
t = time.clock()
|
||||||
|
self._clock_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
|
||||||
|
|
||||||
|
|
||||||
|
class _UserFriendlyRNG(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.closed = False
|
||||||
|
self._fa = FortunaAccumulator.FortunaAccumulator()
|
||||||
|
self._ec = _EntropyCollector(self._fa)
|
||||||
|
self.reinit()
|
||||||
|
|
||||||
|
def reinit(self):
|
||||||
|
"""Initialize the random number generator and seed it with entropy from
|
||||||
|
the operating system.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Save the pid (helps ensure that Crypto.Random.atfork() gets called)
|
||||||
|
self._pid = os.getpid()
|
||||||
|
|
||||||
|
# Collect entropy from the operating system and feed it to
|
||||||
|
# FortunaAccumulator
|
||||||
|
self._ec.reinit()
|
||||||
|
|
||||||
|
# Override FortunaAccumulator's 100ms minimum re-seed interval. This
|
||||||
|
# is necessary to avoid a race condition between this function and
|
||||||
|
# self.read(), which that can otherwise cause forked child processes to
|
||||||
|
# produce identical output. (e.g. CVE-2013-1445)
|
||||||
|
#
|
||||||
|
# Note that if this function can be called frequently by an attacker,
|
||||||
|
# (and if the bits from OSRNG are insufficiently random) it will weaken
|
||||||
|
# Fortuna's ability to resist a state compromise extension attack.
|
||||||
|
self._fa._forget_last_reseed()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.closed = True
|
||||||
|
self._osrng = None
|
||||||
|
self._fa = None
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def read(self, N):
|
||||||
|
"""Return N bytes from the RNG."""
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("I/O operation on closed file")
|
||||||
|
if not isinstance(N, int):
|
||||||
|
raise TypeError("an integer is required")
|
||||||
|
if N < 0:
|
||||||
|
raise ValueError("cannot read to end of infinite stream")
|
||||||
|
|
||||||
|
# Collect some entropy and feed it to Fortuna
|
||||||
|
self._ec.collect()
|
||||||
|
|
||||||
|
# Ask Fortuna to generate some bytes
|
||||||
|
retval = self._fa.random_data(N)
|
||||||
|
|
||||||
|
# Check that we haven't forked in the meantime. (If we have, we don't
|
||||||
|
# want to use the data, because it might have been duplicated in the
|
||||||
|
# parent process.
|
||||||
|
self._check_pid()
|
||||||
|
|
||||||
|
# Return the random data.
|
||||||
|
return retval
|
||||||
|
|
||||||
|
def _check_pid(self):
|
||||||
|
# Lame fork detection to remind developers to invoke Random.atfork()
|
||||||
|
# after every call to os.fork(). Note that this check is not reliable,
|
||||||
|
# since process IDs can be reused on most operating systems.
|
||||||
|
#
|
||||||
|
# You need to do Random.atfork() in the child process after every call
|
||||||
|
# to os.fork() to avoid reusing PRNG state. If you want to avoid
|
||||||
|
# leaking PRNG state to child processes (for example, if you are using
|
||||||
|
# os.setuid()) then you should also invoke Random.atfork() in the
|
||||||
|
# *parent* process.
|
||||||
|
if os.getpid() != self._pid:
|
||||||
|
raise AssertionError("PID check failed. RNG must be re-initialized after fork(). Hint: Try Random.atfork()")
|
||||||
|
|
||||||
|
|
||||||
|
class _LockingUserFriendlyRNG(_UserFriendlyRNG):
|
||||||
|
def __init__(self):
|
||||||
|
self._lock = threading.Lock()
|
||||||
|
_UserFriendlyRNG.__init__(self)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self._lock.acquire()
|
||||||
|
try:
|
||||||
|
return _UserFriendlyRNG.close(self)
|
||||||
|
finally:
|
||||||
|
self._lock.release()
|
||||||
|
|
||||||
|
def reinit(self):
|
||||||
|
self._lock.acquire()
|
||||||
|
try:
|
||||||
|
return _UserFriendlyRNG.reinit(self)
|
||||||
|
finally:
|
||||||
|
self._lock.release()
|
||||||
|
|
||||||
|
def read(self, bytes):
|
||||||
|
self._lock.acquire()
|
||||||
|
try:
|
||||||
|
return _UserFriendlyRNG.read(self, bytes)
|
||||||
|
finally:
|
||||||
|
self._lock.release()
|
||||||
|
|
||||||
|
class RNGFile(object):
|
||||||
|
def __init__(self, singleton):
|
||||||
|
self.closed = False
|
||||||
|
self._singleton = singleton
|
||||||
|
|
||||||
|
# PEP 343: Support for the "with" statement
|
||||||
|
def __enter__(self):
|
||||||
|
"""PEP 343 support"""
|
||||||
|
def __exit__(self):
|
||||||
|
"""PEP 343 support"""
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
# Don't actually close the singleton, just close this RNGFile instance.
|
||||||
|
self.closed = True
|
||||||
|
self._singleton = None
|
||||||
|
|
||||||
|
def read(self, bytes):
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("I/O operation on closed file")
|
||||||
|
return self._singleton.read(bytes)
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("I/O operation on closed file")
|
||||||
|
|
||||||
|
_singleton_lock = threading.Lock()
|
||||||
|
_singleton = None
|
||||||
|
def _get_singleton():
|
||||||
|
global _singleton
|
||||||
|
_singleton_lock.acquire()
|
||||||
|
try:
|
||||||
|
if _singleton is None:
|
||||||
|
_singleton = _LockingUserFriendlyRNG()
|
||||||
|
return _singleton
|
||||||
|
finally:
|
||||||
|
_singleton_lock.release()
|
||||||
|
|
||||||
|
def new():
|
||||||
|
return RNGFile(_get_singleton())
|
||||||
|
|
||||||
|
def reinit():
|
||||||
|
_get_singleton().reinit()
|
||||||
|
|
||||||
|
def get_random_bytes(n):
|
||||||
|
"""Return the specified number of cryptographically-strong random bytes."""
|
||||||
|
return _get_singleton().read(n)
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
43
Lib/site-packages/Crypto/Random/__init__.py
Normal file
43
Lib/site-packages/Crypto/Random/__init__.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Random/__init__.py : PyCrypto random number generation
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
__all__ = ['new']
|
||||||
|
|
||||||
|
from Crypto.Random import OSRNG
|
||||||
|
from Crypto.Random import _UserFriendlyRNG
|
||||||
|
|
||||||
|
def new(*args, **kwargs):
|
||||||
|
"""Return a file-like object that outputs cryptographically random bytes."""
|
||||||
|
return _UserFriendlyRNG.new(*args, **kwargs)
|
||||||
|
|
||||||
|
def atfork():
|
||||||
|
"""Call this whenever you call os.fork()"""
|
||||||
|
_UserFriendlyRNG.reinit()
|
||||||
|
|
||||||
|
def get_random_bytes(n):
|
||||||
|
"""Return the specified number of cryptographically-strong random bytes."""
|
||||||
|
return _UserFriendlyRNG.get_random_bytes(n)
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
142
Lib/site-packages/Crypto/Random/random.py
Normal file
142
Lib/site-packages/Crypto/Random/random.py
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Random/random.py : Strong alternative for the standard 'random' module
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""A cryptographically strong version of Python's standard "random" module."""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample']
|
||||||
|
|
||||||
|
from Crypto import Random
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
|
||||||
|
class StrongRandom(object):
|
||||||
|
def __init__(self, rng=None, randfunc=None):
|
||||||
|
if randfunc is None and rng is None:
|
||||||
|
self._randfunc = None
|
||||||
|
elif randfunc is not None and rng is None:
|
||||||
|
self._randfunc = randfunc
|
||||||
|
elif randfunc is None and rng is not None:
|
||||||
|
self._randfunc = rng.read
|
||||||
|
else:
|
||||||
|
raise ValueError("Cannot specify both 'rng' and 'randfunc'")
|
||||||
|
|
||||||
|
def getrandbits(self, k):
|
||||||
|
"""Return a python long integer with k random bits."""
|
||||||
|
if self._randfunc is None:
|
||||||
|
self._randfunc = Random.new().read
|
||||||
|
mask = (1 << k) - 1
|
||||||
|
return mask & bytes_to_long(self._randfunc(ceil_div(k, 8)))
|
||||||
|
|
||||||
|
def randrange(self, *args):
|
||||||
|
"""randrange([start,] stop[, step]):
|
||||||
|
Return a randomly-selected element from range(start, stop, step)."""
|
||||||
|
if len(args) == 3:
|
||||||
|
(start, stop, step) = args
|
||||||
|
elif len(args) == 2:
|
||||||
|
(start, stop) = args
|
||||||
|
step = 1
|
||||||
|
elif len(args) == 1:
|
||||||
|
(stop,) = args
|
||||||
|
start = 0
|
||||||
|
step = 1
|
||||||
|
else:
|
||||||
|
raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),))
|
||||||
|
if (not isinstance(start, int)
|
||||||
|
or not isinstance(stop, int)
|
||||||
|
or not isinstance(step, int)):
|
||||||
|
raise TypeError("randrange requires integer arguments")
|
||||||
|
if step == 0:
|
||||||
|
raise ValueError("randrange step argument must not be zero")
|
||||||
|
|
||||||
|
num_choices = ceil_div(stop - start, step)
|
||||||
|
if num_choices < 0:
|
||||||
|
num_choices = 0
|
||||||
|
if num_choices < 1:
|
||||||
|
raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step))
|
||||||
|
|
||||||
|
# Pick a random number in the range of possible numbers
|
||||||
|
r = num_choices
|
||||||
|
while r >= num_choices:
|
||||||
|
r = self.getrandbits(size(num_choices))
|
||||||
|
|
||||||
|
return start + (step * r)
|
||||||
|
|
||||||
|
def randint(self, a, b):
|
||||||
|
"""Return a random integer N such that a <= N <= b."""
|
||||||
|
if not isinstance(a, int) or not isinstance(b, int):
|
||||||
|
raise TypeError("randint requires integer arguments")
|
||||||
|
N = self.randrange(a, b+1)
|
||||||
|
assert a <= N <= b
|
||||||
|
return N
|
||||||
|
|
||||||
|
def choice(self, seq):
|
||||||
|
"""Return a random element from a (non-empty) sequence.
|
||||||
|
|
||||||
|
If the seqence is empty, raises IndexError.
|
||||||
|
"""
|
||||||
|
if len(seq) == 0:
|
||||||
|
raise IndexError("empty sequence")
|
||||||
|
return seq[self.randrange(len(seq))]
|
||||||
|
|
||||||
|
def shuffle(self, x):
|
||||||
|
"""Shuffle the sequence in place."""
|
||||||
|
# Make a (copy) of the list of objects we want to shuffle
|
||||||
|
items = list(x)
|
||||||
|
|
||||||
|
# Choose a random item (without replacement) until all the items have been
|
||||||
|
# chosen.
|
||||||
|
for i in range(len(x)):
|
||||||
|
x[i] = items.pop(self.randrange(len(items)))
|
||||||
|
|
||||||
|
def sample(self, population, k):
|
||||||
|
"""Return a k-length list of unique elements chosen from the population sequence."""
|
||||||
|
|
||||||
|
num_choices = len(population)
|
||||||
|
if k > num_choices:
|
||||||
|
raise ValueError("sample larger than population")
|
||||||
|
|
||||||
|
retval = []
|
||||||
|
selected = {} # we emulate a set using a dict here
|
||||||
|
for i in range(k):
|
||||||
|
r = None
|
||||||
|
while r is None or r in selected:
|
||||||
|
r = self.randrange(num_choices)
|
||||||
|
retval.append(population[r])
|
||||||
|
selected[r] = 1
|
||||||
|
return retval
|
||||||
|
|
||||||
|
_r = StrongRandom()
|
||||||
|
getrandbits = _r.getrandbits
|
||||||
|
randrange = _r.randrange
|
||||||
|
randint = _r.randint
|
||||||
|
choice = _r.choice
|
||||||
|
shuffle = _r.shuffle
|
||||||
|
sample = _r.sample
|
||||||
|
|
||||||
|
# These are at the bottom to avoid problems with recursive imports
|
||||||
|
from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes, size
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
48
Lib/site-packages/Crypto/SelfTest/Cipher/__init__.py
Normal file
48
Lib/site-packages/Crypto/SelfTest/Cipher/__init__.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/__init__.py: Self-test for cipher modules
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test for cipher modules"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
from Crypto.SelfTest.Cipher import test_AES; tests += test_AES.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Cipher import test_ARC2; tests += test_ARC2.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Cipher import test_ARC4; tests += test_ARC4.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Cipher import test_Blowfish; tests += test_Blowfish.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Cipher import test_CAST; tests += test_CAST.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Cipher import test_DES3; tests += test_DES3.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Cipher import test_DES; tests += test_DES.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Cipher import test_XOR; tests += test_XOR.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Cipher import test_pkcs1_15; tests += test_pkcs1_15.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Cipher import test_pkcs1_oaep; tests += test_pkcs1_oaep.get_tests(config=config)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
399
Lib/site-packages/Crypto/SelfTest/Cipher/common.py
Normal file
399
Lib/site-packages/Crypto/SelfTest/Cipher/common.py
Normal file
|
@ -0,0 +1,399 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/common.py: Common code for Crypto.SelfTest.Hash
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-testing for PyCrypto hash modules"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from binascii import a2b_hex, b2a_hex
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# For compatibility with Python 2.1 and Python 2.2
|
||||||
|
if sys.hexversion < 0x02030000:
|
||||||
|
# Python 2.1 doesn't have a dict() function
|
||||||
|
# Python 2.2 dict() function raises TypeError if you do dict(MD5='blah')
|
||||||
|
def dict(**kwargs):
|
||||||
|
return kwargs.copy()
|
||||||
|
else:
|
||||||
|
dict = dict
|
||||||
|
|
||||||
|
class _NoDefault: pass # sentinel object
|
||||||
|
def _extract(d, k, default=_NoDefault):
|
||||||
|
"""Get an item from a dictionary, and remove it from the dictionary."""
|
||||||
|
try:
|
||||||
|
retval = d[k]
|
||||||
|
except KeyError:
|
||||||
|
if default is _NoDefault:
|
||||||
|
raise
|
||||||
|
return default
|
||||||
|
del d[k]
|
||||||
|
return retval
|
||||||
|
|
||||||
|
# Generic cipher test case
|
||||||
|
class CipherSelfTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def __init__(self, module, params):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.module = module
|
||||||
|
|
||||||
|
# Extract the parameters
|
||||||
|
params = params.copy()
|
||||||
|
self.description = _extract(params, 'description')
|
||||||
|
self.key = b(_extract(params, 'key'))
|
||||||
|
self.plaintext = b(_extract(params, 'plaintext'))
|
||||||
|
self.ciphertext = b(_extract(params, 'ciphertext'))
|
||||||
|
self.module_name = _extract(params, 'module_name', None)
|
||||||
|
|
||||||
|
mode = _extract(params, 'mode', None)
|
||||||
|
self.mode_name = str(mode)
|
||||||
|
if mode is not None:
|
||||||
|
# Block cipher
|
||||||
|
self.mode = getattr(self.module, "MODE_" + mode)
|
||||||
|
self.iv = _extract(params, 'iv', None)
|
||||||
|
if self.iv is not None: self.iv = b(self.iv)
|
||||||
|
|
||||||
|
# Only relevant for OPENPGP mode
|
||||||
|
self.encrypted_iv = _extract(params, 'encrypted_iv', None)
|
||||||
|
if self.encrypted_iv is not None:
|
||||||
|
self.encrypted_iv = b(self.encrypted_iv)
|
||||||
|
else:
|
||||||
|
# Stream cipher
|
||||||
|
self.mode = None
|
||||||
|
self.iv = None
|
||||||
|
|
||||||
|
self.extra_params = params
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return self.description
|
||||||
|
|
||||||
|
def _new(self, do_decryption=0):
|
||||||
|
params = self.extra_params.copy()
|
||||||
|
|
||||||
|
# Handle CTR mode parameters. By default, we use Counter.new(self.module.block_size)
|
||||||
|
if hasattr(self.module, "MODE_CTR") and self.mode == self.module.MODE_CTR:
|
||||||
|
from Crypto.Util import Counter
|
||||||
|
ctr_class = _extract(params, 'ctr_class', Counter.new)
|
||||||
|
ctr_params = _extract(params, 'ctr_params', {}).copy()
|
||||||
|
if 'prefix' in ctr_params: ctr_params['prefix'] = a2b_hex(b(ctr_params['prefix']))
|
||||||
|
if 'suffix' in ctr_params: ctr_params['suffix'] = a2b_hex(b(ctr_params['suffix']))
|
||||||
|
if 'nbits' not in ctr_params:
|
||||||
|
ctr_params['nbits'] = 8*(self.module.block_size - len(ctr_params.get('prefix', '')) - len(ctr_params.get('suffix', '')))
|
||||||
|
params['counter'] = ctr_class(**ctr_params)
|
||||||
|
|
||||||
|
if self.mode is None:
|
||||||
|
# Stream cipher
|
||||||
|
return self.module.new(a2b_hex(self.key), **params)
|
||||||
|
elif self.iv is None:
|
||||||
|
# Block cipher without iv
|
||||||
|
return self.module.new(a2b_hex(self.key), self.mode, **params)
|
||||||
|
else:
|
||||||
|
# Block cipher with iv
|
||||||
|
if do_decryption and self.mode == self.module.MODE_OPENPGP:
|
||||||
|
# In PGP mode, the IV to feed for decryption is the *encrypted* one
|
||||||
|
return self.module.new(a2b_hex(self.key), self.mode, a2b_hex(self.encrypted_iv), **params)
|
||||||
|
else:
|
||||||
|
return self.module.new(a2b_hex(self.key), self.mode, a2b_hex(self.iv), **params)
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
plaintext = a2b_hex(self.plaintext)
|
||||||
|
ciphertext = a2b_hex(self.ciphertext)
|
||||||
|
|
||||||
|
ct1 = b2a_hex(self._new().encrypt(plaintext))
|
||||||
|
pt1 = b2a_hex(self._new(1).decrypt(ciphertext))
|
||||||
|
ct2 = b2a_hex(self._new().encrypt(plaintext))
|
||||||
|
pt2 = b2a_hex(self._new(1).decrypt(ciphertext))
|
||||||
|
|
||||||
|
if hasattr(self.module, "MODE_OPENPGP") and self.mode == self.module.MODE_OPENPGP:
|
||||||
|
# In PGP mode, data returned by the first encrypt()
|
||||||
|
# is prefixed with the encrypted IV.
|
||||||
|
# Here we check it and then remove it from the ciphertexts.
|
||||||
|
eilen = len(self.encrypted_iv)
|
||||||
|
self.assertEqual(self.encrypted_iv, ct1[:eilen])
|
||||||
|
self.assertEqual(self.encrypted_iv, ct2[:eilen])
|
||||||
|
ct1 = ct1[eilen:]
|
||||||
|
ct2 = ct2[eilen:]
|
||||||
|
|
||||||
|
self.assertEqual(self.ciphertext, ct1) # encrypt
|
||||||
|
self.assertEqual(self.ciphertext, ct2) # encrypt (second time)
|
||||||
|
self.assertEqual(self.plaintext, pt1) # decrypt
|
||||||
|
self.assertEqual(self.plaintext, pt2) # decrypt (second time)
|
||||||
|
|
||||||
|
class CipherStreamingSelfTest(CipherSelfTest):
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
desc = self.module_name
|
||||||
|
if self.mode is not None:
|
||||||
|
desc += " in %s mode" % (self.mode_name,)
|
||||||
|
return "%s should behave like a stream cipher" % (desc,)
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
plaintext = a2b_hex(self.plaintext)
|
||||||
|
ciphertext = a2b_hex(self.ciphertext)
|
||||||
|
|
||||||
|
# The cipher should work like a stream cipher
|
||||||
|
|
||||||
|
# Test counter mode encryption, 3 bytes at a time
|
||||||
|
ct3 = []
|
||||||
|
cipher = self._new()
|
||||||
|
for i in range(0, len(plaintext), 3):
|
||||||
|
ct3.append(cipher.encrypt(plaintext[i:i+3]))
|
||||||
|
ct3 = b2a_hex(b("").join(ct3))
|
||||||
|
self.assertEqual(self.ciphertext, ct3) # encryption (3 bytes at a time)
|
||||||
|
|
||||||
|
# Test counter mode decryption, 3 bytes at a time
|
||||||
|
pt3 = []
|
||||||
|
cipher = self._new()
|
||||||
|
for i in range(0, len(ciphertext), 3):
|
||||||
|
pt3.append(cipher.encrypt(ciphertext[i:i+3]))
|
||||||
|
# PY3K: This is meant to be text, do not change to bytes (data)
|
||||||
|
pt3 = b2a_hex(b("").join(pt3))
|
||||||
|
self.assertEqual(self.plaintext, pt3) # decryption (3 bytes at a time)
|
||||||
|
|
||||||
|
class CTRSegfaultTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def __init__(self, module, params):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.module = module
|
||||||
|
self.key = b(params['key'])
|
||||||
|
self.module_name = params.get('module_name', None)
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return """Regression test: %s.new(key, %s.MODE_CTR) should raise TypeError, not segfault""" % (self.module_name, self.module_name)
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
self.assertRaises(TypeError, self.module.new, a2b_hex(self.key), self.module.MODE_CTR)
|
||||||
|
|
||||||
|
class CTRWraparoundTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def __init__(self, module, params):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.module = module
|
||||||
|
self.key = b(params['key'])
|
||||||
|
self.module_name = params.get('module_name', None)
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return """Regression test: %s with MODE_CTR should raise OverflowError on wraparound when shortcut used""" % (self.module_name,)
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
from Crypto.Util import Counter
|
||||||
|
|
||||||
|
for disable_shortcut in (0, 1): # (False, True) Test CTR-mode shortcut and PyObject_CallObject code paths
|
||||||
|
for little_endian in (0, 1): # (False, True) Test both endiannesses
|
||||||
|
ctr = Counter.new(8*self.module.block_size, initial_value=2**(8*self.module.block_size)-1, little_endian=little_endian, disable_shortcut=disable_shortcut)
|
||||||
|
cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=ctr)
|
||||||
|
block = b("\x00") * self.module.block_size
|
||||||
|
cipher.encrypt(block)
|
||||||
|
self.assertRaises(OverflowError, cipher.encrypt, block)
|
||||||
|
|
||||||
|
class CFBSegmentSizeTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def __init__(self, module, params):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.module = module
|
||||||
|
self.key = b(params['key'])
|
||||||
|
self.description = params['description']
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return self.description
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
"""Regression test: m.new(key, m.MODE_CFB, segment_size=N) should require segment_size to be a multiple of 8 bits"""
|
||||||
|
for i in range(1, 8):
|
||||||
|
self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), self.module.MODE_CFB, segment_size=i)
|
||||||
|
self.module.new(a2b_hex(self.key), self.module.MODE_CFB, "\0"*self.module.block_size, segment_size=8) # should succeed
|
||||||
|
|
||||||
|
class RoundtripTest(unittest.TestCase):
|
||||||
|
def __init__(self, module, params):
|
||||||
|
from Crypto import Random
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.module = module
|
||||||
|
self.iv = Random.get_random_bytes(module.block_size)
|
||||||
|
self.key = b(params['key'])
|
||||||
|
self.plaintext = 100 * b(params['plaintext'])
|
||||||
|
self.module_name = params.get('module_name', None)
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,)
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
for mode in (self.module.MODE_ECB, self.module.MODE_CBC, self.module.MODE_CFB, self.module.MODE_OFB, self.module.MODE_OPENPGP):
|
||||||
|
encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv)
|
||||||
|
ciphertext = encryption_cipher.encrypt(self.plaintext)
|
||||||
|
|
||||||
|
if mode != self.module.MODE_OPENPGP:
|
||||||
|
decryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv)
|
||||||
|
else:
|
||||||
|
eiv = ciphertext[:self.module.block_size+2]
|
||||||
|
ciphertext = ciphertext[self.module.block_size+2:]
|
||||||
|
decryption_cipher = self.module.new(a2b_hex(self.key), mode, eiv)
|
||||||
|
decrypted_plaintext = decryption_cipher.decrypt(ciphertext)
|
||||||
|
self.assertEqual(self.plaintext, decrypted_plaintext)
|
||||||
|
|
||||||
|
class PGPTest(unittest.TestCase):
|
||||||
|
def __init__(self, module, params):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.module = module
|
||||||
|
self.key = b(params['key'])
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return "MODE_PGP was implemented incorrectly and insecurely. It's completely banished now."
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
self.assertRaises(ValueError, self.module.new, a2b_hex(self.key),
|
||||||
|
self.module.MODE_PGP)
|
||||||
|
|
||||||
|
class IVLengthTest(unittest.TestCase):
|
||||||
|
def __init__(self, module, params):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.module = module
|
||||||
|
self.key = b(params['key'])
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return "Check that all modes except MODE_ECB and MODE_CTR require an IV of the proper length"
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
self.assertRaises(ValueError, self.module.new, a2b_hex(self.key),
|
||||||
|
self.module.MODE_CBC, "")
|
||||||
|
self.assertRaises(ValueError, self.module.new, a2b_hex(self.key),
|
||||||
|
self.module.MODE_CFB, "")
|
||||||
|
self.assertRaises(ValueError, self.module.new, a2b_hex(self.key),
|
||||||
|
self.module.MODE_OFB, "")
|
||||||
|
self.assertRaises(ValueError, self.module.new, a2b_hex(self.key),
|
||||||
|
self.module.MODE_OPENPGP, "")
|
||||||
|
self.module.new(a2b_hex(self.key), self.module.MODE_ECB, "")
|
||||||
|
self.module.new(a2b_hex(self.key), self.module.MODE_CTR, "", counter=self._dummy_counter)
|
||||||
|
|
||||||
|
def _dummy_counter(self):
|
||||||
|
return "\0" * self.module.block_size
|
||||||
|
|
||||||
|
def make_block_tests(module, module_name, test_data):
|
||||||
|
tests = []
|
||||||
|
extra_tests_added = 0
|
||||||
|
for i in range(len(test_data)):
|
||||||
|
row = test_data[i]
|
||||||
|
|
||||||
|
# Build the "params" dictionary
|
||||||
|
params = {'mode': 'ECB'}
|
||||||
|
if len(row) == 3:
|
||||||
|
(params['plaintext'], params['ciphertext'], params['key']) = row
|
||||||
|
elif len(row) == 4:
|
||||||
|
(params['plaintext'], params['ciphertext'], params['key'], params['description']) = row
|
||||||
|
elif len(row) == 5:
|
||||||
|
(params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row
|
||||||
|
params.update(extra_params)
|
||||||
|
else:
|
||||||
|
raise AssertionError("Unsupported tuple size %d" % (len(row),))
|
||||||
|
|
||||||
|
# Build the display-name for the test
|
||||||
|
p2 = params.copy()
|
||||||
|
p_key = _extract(p2, 'key')
|
||||||
|
p_plaintext = _extract(p2, 'plaintext')
|
||||||
|
p_ciphertext = _extract(p2, 'ciphertext')
|
||||||
|
p_description = _extract(p2, 'description', None)
|
||||||
|
p_mode = p2.get('mode', 'ECB')
|
||||||
|
if p_mode == 'ECB':
|
||||||
|
_extract(p2, 'mode', 'ECB')
|
||||||
|
|
||||||
|
if p_description is not None:
|
||||||
|
description = p_description
|
||||||
|
elif p_mode == 'ECB' and not p2:
|
||||||
|
description = "p=%s, k=%s" % (p_plaintext, p_key)
|
||||||
|
else:
|
||||||
|
description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2)
|
||||||
|
name = "%s #%d: %s" % (module_name, i+1, description)
|
||||||
|
params['description'] = name
|
||||||
|
params['module_name'] = module_name
|
||||||
|
|
||||||
|
# Add extra test(s) to the test suite before the current test
|
||||||
|
if not extra_tests_added:
|
||||||
|
tests += [
|
||||||
|
CTRSegfaultTest(module, params),
|
||||||
|
CTRWraparoundTest(module, params),
|
||||||
|
CFBSegmentSizeTest(module, params),
|
||||||
|
RoundtripTest(module, params),
|
||||||
|
PGPTest(module, params),
|
||||||
|
IVLengthTest(module, params),
|
||||||
|
]
|
||||||
|
extra_tests_added = 1
|
||||||
|
|
||||||
|
# Add the current test to the test suite
|
||||||
|
tests.append(CipherSelfTest(module, params))
|
||||||
|
|
||||||
|
# When using CTR mode, test that the interface behaves like a stream cipher
|
||||||
|
if p_mode == 'CTR':
|
||||||
|
tests.append(CipherStreamingSelfTest(module, params))
|
||||||
|
|
||||||
|
# When using CTR mode, test the non-shortcut code path.
|
||||||
|
if p_mode == 'CTR' and 'ctr_class' not in params:
|
||||||
|
params2 = params.copy()
|
||||||
|
params2['description'] += " (shortcut disabled)"
|
||||||
|
ctr_params2 = params.get('ctr_params', {}).copy()
|
||||||
|
params2['ctr_params'] = ctr_params2
|
||||||
|
if 'disable_shortcut' not in params2['ctr_params']:
|
||||||
|
params2['ctr_params']['disable_shortcut'] = 1
|
||||||
|
tests.append(CipherSelfTest(module, params2))
|
||||||
|
return tests
|
||||||
|
|
||||||
|
def make_stream_tests(module, module_name, test_data):
|
||||||
|
tests = []
|
||||||
|
for i in range(len(test_data)):
|
||||||
|
row = test_data[i]
|
||||||
|
|
||||||
|
# Build the "params" dictionary
|
||||||
|
params = {}
|
||||||
|
if len(row) == 3:
|
||||||
|
(params['plaintext'], params['ciphertext'], params['key']) = row
|
||||||
|
elif len(row) == 4:
|
||||||
|
(params['plaintext'], params['ciphertext'], params['key'], params['description']) = row
|
||||||
|
elif len(row) == 5:
|
||||||
|
(params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row
|
||||||
|
params.update(extra_params)
|
||||||
|
else:
|
||||||
|
raise AssertionError("Unsupported tuple size %d" % (len(row),))
|
||||||
|
|
||||||
|
# Build the display-name for the test
|
||||||
|
p2 = params.copy()
|
||||||
|
p_key = _extract(p2, 'key')
|
||||||
|
p_plaintext = _extract(p2, 'plaintext')
|
||||||
|
p_ciphertext = _extract(p2, 'ciphertext')
|
||||||
|
p_description = _extract(p2, 'description', None)
|
||||||
|
|
||||||
|
if p_description is not None:
|
||||||
|
description = p_description
|
||||||
|
elif not p2:
|
||||||
|
description = "p=%s, k=%s" % (p_plaintext, p_key)
|
||||||
|
else:
|
||||||
|
description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2)
|
||||||
|
name = "%s #%d: %s" % (module_name, i+1, description)
|
||||||
|
params['description'] = name
|
||||||
|
params['module_name'] = module_name
|
||||||
|
|
||||||
|
# Add the test to the test suite
|
||||||
|
tests.append(CipherSelfTest(module, params))
|
||||||
|
tests.append(CipherStreamingSelfTest(module, params))
|
||||||
|
return tests
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
1433
Lib/site-packages/Crypto/SelfTest/Cipher/test_AES.py
Normal file
1433
Lib/site-packages/Crypto/SelfTest/Cipher/test_AES.py
Normal file
File diff suppressed because it is too large
Load diff
124
Lib/site-packages/Crypto/SelfTest/Cipher/test_ARC2.py
Normal file
124
Lib/site-packages/Crypto/SelfTest/Cipher/test_ARC2.py
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/ARC2.py: Self-test for the Alleged-RC2 cipher
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Cipher.ARC2"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from .common import dict # For compatibility with Python 2.1 and 2.2
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (plaintext, ciphertext, key[, description[, extra_params]]) tuples.
|
||||||
|
test_data = [
|
||||||
|
# Test vectors from RFC 2268
|
||||||
|
|
||||||
|
# 63-bit effective key length
|
||||||
|
('0000000000000000', 'ebb773f993278eff', '0000000000000000',
|
||||||
|
'RFC2268-1', dict(effective_keylen=63)),
|
||||||
|
|
||||||
|
# 64-bit effective key length
|
||||||
|
('ffffffffffffffff', '278b27e42e2f0d49', 'ffffffffffffffff',
|
||||||
|
'RFC2268-2', dict(effective_keylen=64)),
|
||||||
|
('1000000000000001', '30649edf9be7d2c2', '3000000000000000',
|
||||||
|
'RFC2268-3', dict(effective_keylen=64)),
|
||||||
|
('0000000000000000', '61a8a244adacccf0', '88',
|
||||||
|
'RFC2268-4', dict(effective_keylen=64)),
|
||||||
|
('0000000000000000', '6ccf4308974c267f', '88bca90e90875a',
|
||||||
|
'RFC2268-5', dict(effective_keylen=64)),
|
||||||
|
('0000000000000000', '1a807d272bbe5db1', '88bca90e90875a7f0f79c384627bafb2',
|
||||||
|
'RFC2268-6', dict(effective_keylen=64)),
|
||||||
|
|
||||||
|
# 128-bit effective key length
|
||||||
|
('0000000000000000', '2269552ab0f85ca6', '88bca90e90875a7f0f79c384627bafb2',
|
||||||
|
"RFC2268-7", dict(effective_keylen=128)),
|
||||||
|
('0000000000000000', '5b78d3a43dfff1f1',
|
||||||
|
'88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e',
|
||||||
|
"RFC2268-8", dict(effective_keylen=129)),
|
||||||
|
|
||||||
|
# Test vectors from PyCrypto 2.0.1's testdata.py
|
||||||
|
# 1024-bit effective key length
|
||||||
|
('0000000000000000', '624fb3e887419e48', '5068696c6970476c617373',
|
||||||
|
'PCTv201-0'),
|
||||||
|
('ffffffffffffffff', '79cadef44c4a5a85', '5068696c6970476c617373',
|
||||||
|
'PCTv201-1'),
|
||||||
|
('0001020304050607', '90411525b34e4c2c', '5068696c6970476c617373',
|
||||||
|
'PCTv201-2'),
|
||||||
|
('0011223344556677', '078656aaba61cbfb', '5068696c6970476c617373',
|
||||||
|
'PCTv201-3'),
|
||||||
|
('0000000000000000', 'd7bcc5dbb4d6e56a', 'ffffffffffffffff',
|
||||||
|
'PCTv201-4'),
|
||||||
|
('ffffffffffffffff', '7259018ec557b357', 'ffffffffffffffff',
|
||||||
|
'PCTv201-5'),
|
||||||
|
('0001020304050607', '93d20a497f2ccb62', 'ffffffffffffffff',
|
||||||
|
'PCTv201-6'),
|
||||||
|
('0011223344556677', 'cb15a7f819c0014d', 'ffffffffffffffff',
|
||||||
|
'PCTv201-7'),
|
||||||
|
('0000000000000000', '63ac98cdf3843a7a', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553',
|
||||||
|
'PCTv201-8'),
|
||||||
|
('ffffffffffffffff', '3fb49e2fa12371dd', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553',
|
||||||
|
'PCTv201-9'),
|
||||||
|
('0001020304050607', '46414781ab387d5f', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553',
|
||||||
|
'PCTv201-10'),
|
||||||
|
('0011223344556677', 'be09dc81feaca271', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553',
|
||||||
|
'PCTv201-11'),
|
||||||
|
('0000000000000000', 'e64221e608be30ab', '53e5ffe553',
|
||||||
|
'PCTv201-12'),
|
||||||
|
('ffffffffffffffff', '862bc60fdcd4d9a9', '53e5ffe553',
|
||||||
|
'PCTv201-13'),
|
||||||
|
('0001020304050607', '6a34da50fa5e47de', '53e5ffe553',
|
||||||
|
'PCTv201-14'),
|
||||||
|
('0011223344556677', '584644c34503122c', '53e5ffe553',
|
||||||
|
'PCTv201-15'),
|
||||||
|
]
|
||||||
|
|
||||||
|
class BufferOverflowTest(unittest.TestCase):
|
||||||
|
# Test a buffer overflow found in older versions of PyCrypto
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
global ARC2
|
||||||
|
from Crypto.Cipher import ARC2
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
"""ARC2 with keylength > 128"""
|
||||||
|
key = "x" * 16384
|
||||||
|
mode = ARC2.MODE_ECB
|
||||||
|
self.assertRaises(ValueError, ARC2.new, key, mode)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Cipher import ARC2
|
||||||
|
from .common import make_block_tests
|
||||||
|
|
||||||
|
tests = make_block_tests(ARC2, "ARC2", test_data)
|
||||||
|
tests.append(BufferOverflowTest())
|
||||||
|
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
81
Lib/site-packages/Crypto/SelfTest/Cipher/test_ARC4.py
Normal file
81
Lib/site-packages/Crypto/SelfTest/Cipher/test_ARC4.py
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/ARC4.py: Self-test for the Alleged-RC4 cipher
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Cipher.ARC4"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (plaintext, ciphertext, key[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
# Test vectors from Eric Rescorla's message with the subject
|
||||||
|
# "RC4 compatibility testing", sent to the cipherpunks mailing list on
|
||||||
|
# September 13, 1994.
|
||||||
|
# http://cypherpunks.venona.com/date/1994/09/msg00420.html
|
||||||
|
|
||||||
|
('0123456789abcdef', '75b7878099e0c596', '0123456789abcdef',
|
||||||
|
'Test vector 0'),
|
||||||
|
|
||||||
|
('0000000000000000', '7494c2e7104b0879', '0123456789abcdef',
|
||||||
|
'Test vector 1'),
|
||||||
|
|
||||||
|
('0000000000000000', 'de188941a3375d3a', '0000000000000000',
|
||||||
|
'Test vector 2'),
|
||||||
|
|
||||||
|
('00000000000000000000', 'd6a141a7ec3c38dfbd61', 'ef012345',
|
||||||
|
'Test vector 3'),
|
||||||
|
|
||||||
|
('01' * 512,
|
||||||
|
'7595c3e6114a09780c4ad452338e1ffd9a1be9498f813d76533449b6778dcad8'
|
||||||
|
+ 'c78a8d2ba9ac66085d0e53d59c26c2d1c490c1ebbe0ce66d1b6b1b13b6b919b8'
|
||||||
|
+ '47c25a91447a95e75e4ef16779cde8bf0a95850e32af9689444fd377108f98fd'
|
||||||
|
+ 'cbd4e726567500990bcc7e0ca3c4aaa304a387d20f3b8fbbcd42a1bd311d7a43'
|
||||||
|
+ '03dda5ab078896ae80c18b0af66dff319616eb784e495ad2ce90d7f772a81747'
|
||||||
|
+ 'b65f62093b1e0db9e5ba532fafec47508323e671327df9444432cb7367cec82f'
|
||||||
|
+ '5d44c0d00b67d650a075cd4b70dedd77eb9b10231b6b5b741347396d62897421'
|
||||||
|
+ 'd43df9b42e446e358e9c11a9b2184ecbef0cd8e7a877ef968f1390ec9b3d35a5'
|
||||||
|
+ '585cb009290e2fcde7b5ec66d9084be44055a619d9dd7fc3166f9487f7cb2729'
|
||||||
|
+ '12426445998514c15d53a18c864ce3a2b7555793988126520eacf2e3066e230c'
|
||||||
|
+ '91bee4dd5304f5fd0405b35bd99c73135d3d9bc335ee049ef69b3867bf2d7bd1'
|
||||||
|
+ 'eaa595d8bfc0066ff8d31509eb0c6caa006c807a623ef84c3d33c195d23ee320'
|
||||||
|
+ 'c40de0558157c822d4b8c569d849aed59d4e0fd7f379586b4b7ff684ed6a189f'
|
||||||
|
+ '7486d49b9c4bad9ba24b96abf924372c8a8fffb10d55354900a77a3db5f205e1'
|
||||||
|
+ 'b99fcd8660863a159ad4abe40fa48934163ddde542a6585540fd683cbfd8c00f'
|
||||||
|
+ '12129a284deacc4cdefe58be7137541c047126c8d49e2755ab181ab7e940b0c0',
|
||||||
|
'0123456789abcdef',
|
||||||
|
"Test vector 4"),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Cipher import ARC4
|
||||||
|
from .common import make_stream_tests
|
||||||
|
return make_stream_tests(ARC4, "ARC4", test_data)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
113
Lib/site-packages/Crypto/SelfTest/Cipher/test_Blowfish.py
Normal file
113
Lib/site-packages/Crypto/SelfTest/Cipher/test_Blowfish.py
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/test_Blowfish.py: Self-test for the Blowfish cipher
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Cipher.Blowfish"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (plaintext, ciphertext, key) tuples.
|
||||||
|
test_data = [
|
||||||
|
# Test vectors from http://www.schneier.com/code/vectors.txt
|
||||||
|
('0000000000000000', '4ef997456198dd78', '0000000000000000'),
|
||||||
|
('ffffffffffffffff', '51866fd5b85ecb8a', 'ffffffffffffffff'),
|
||||||
|
('1000000000000001', '7d856f9a613063f2', '3000000000000000'),
|
||||||
|
('1111111111111111', '2466dd878b963c9d', '1111111111111111'),
|
||||||
|
('1111111111111111', '61f9c3802281b096', '0123456789abcdef'),
|
||||||
|
('0123456789abcdef', '7d0cc630afda1ec7', '1111111111111111'),
|
||||||
|
('0000000000000000', '4ef997456198dd78', '0000000000000000'),
|
||||||
|
('0123456789abcdef', '0aceab0fc6a0a28d', 'fedcba9876543210'),
|
||||||
|
('01a1d6d039776742', '59c68245eb05282b', '7ca110454a1a6e57'),
|
||||||
|
('5cd54ca83def57da', 'b1b8cc0b250f09a0', '0131d9619dc1376e'),
|
||||||
|
('0248d43806f67172', '1730e5778bea1da4', '07a1133e4a0b2686'),
|
||||||
|
('51454b582ddf440a', 'a25e7856cf2651eb', '3849674c2602319e'),
|
||||||
|
('42fd443059577fa2', '353882b109ce8f1a', '04b915ba43feb5b6'),
|
||||||
|
('059b5e0851cf143a', '48f4d0884c379918', '0113b970fd34f2ce'),
|
||||||
|
('0756d8e0774761d2', '432193b78951fc98', '0170f175468fb5e6'),
|
||||||
|
('762514b829bf486a', '13f04154d69d1ae5', '43297fad38e373fe'),
|
||||||
|
('3bdd119049372802', '2eedda93ffd39c79', '07a7137045da2a16'),
|
||||||
|
('26955f6835af609a', 'd887e0393c2da6e3', '04689104c2fd3b2f'),
|
||||||
|
('164d5e404f275232', '5f99d04f5b163969', '37d06bb516cb7546'),
|
||||||
|
('6b056e18759f5cca', '4a057a3b24d3977b', '1f08260d1ac2465e'),
|
||||||
|
('004bd6ef09176062', '452031c1e4fada8e', '584023641aba6176'),
|
||||||
|
('480d39006ee762f2', '7555ae39f59b87bd', '025816164629b007'),
|
||||||
|
('437540c8698f3cfa', '53c55f9cb49fc019', '49793ebc79b3258f'),
|
||||||
|
('072d43a077075292', '7a8e7bfa937e89a3', '4fb05e1515ab73a7'),
|
||||||
|
('02fe55778117f12a', 'cf9c5d7a4986adb5', '49e95d6d4ca229bf'),
|
||||||
|
('1d9d5c5018f728c2', 'd1abb290658bc778', '018310dc409b26d6'),
|
||||||
|
('305532286d6f295a', '55cb3774d13ef201', '1c587f1c13924fef'),
|
||||||
|
('0123456789abcdef', 'fa34ec4847b268b2', '0101010101010101'),
|
||||||
|
('0123456789abcdef', 'a790795108ea3cae', '1f1f1f1f0e0e0e0e'),
|
||||||
|
('0123456789abcdef', 'c39e072d9fac631d', 'e0fee0fef1fef1fe'),
|
||||||
|
('ffffffffffffffff', '014933e0cdaff6e4', '0000000000000000'),
|
||||||
|
('0000000000000000', 'f21e9a77b71c49bc', 'ffffffffffffffff'),
|
||||||
|
('0000000000000000', '245946885754369a', '0123456789abcdef'),
|
||||||
|
('ffffffffffffffff', '6b5c5a9c5d9e0a5a', 'fedcba9876543210'),
|
||||||
|
('fedcba9876543210', 'f9ad597c49db005e', 'f0'),
|
||||||
|
('fedcba9876543210', 'e91d21c1d961a6d6', 'f0e1'),
|
||||||
|
('fedcba9876543210', 'e9c2b70a1bc65cf3', 'f0e1d2'),
|
||||||
|
('fedcba9876543210', 'be1e639408640f05', 'f0e1d2c3'),
|
||||||
|
('fedcba9876543210', 'b39e44481bdb1e6e', 'f0e1d2c3b4'),
|
||||||
|
('fedcba9876543210', '9457aa83b1928c0d', 'f0e1d2c3b4a5'),
|
||||||
|
('fedcba9876543210', '8bb77032f960629d', 'f0e1d2c3b4a596'),
|
||||||
|
('fedcba9876543210', 'e87a244e2cc85e82', 'f0e1d2c3b4a59687'),
|
||||||
|
('fedcba9876543210', '15750e7a4f4ec577', 'f0e1d2c3b4a5968778'),
|
||||||
|
('fedcba9876543210', '122ba70b3ab64ae0', 'f0e1d2c3b4a596877869'),
|
||||||
|
('fedcba9876543210', '3a833c9affc537f6', 'f0e1d2c3b4a5968778695a'),
|
||||||
|
('fedcba9876543210', '9409da87a90f6bf2', 'f0e1d2c3b4a5968778695a4b'),
|
||||||
|
('fedcba9876543210', '884f80625060b8b4', 'f0e1d2c3b4a5968778695a4b3c'),
|
||||||
|
('fedcba9876543210', '1f85031c19e11968', 'f0e1d2c3b4a5968778695a4b3c2d'),
|
||||||
|
('fedcba9876543210', '79d9373a714ca34f', 'f0e1d2c3b4a5968778695a4b3c2d1e'),
|
||||||
|
('fedcba9876543210', '93142887ee3be15c',
|
||||||
|
'f0e1d2c3b4a5968778695a4b3c2d1e0f'),
|
||||||
|
('fedcba9876543210', '03429e838ce2d14b',
|
||||||
|
'f0e1d2c3b4a5968778695a4b3c2d1e0f00'),
|
||||||
|
('fedcba9876543210', 'a4299e27469ff67b',
|
||||||
|
'f0e1d2c3b4a5968778695a4b3c2d1e0f0011'),
|
||||||
|
('fedcba9876543210', 'afd5aed1c1bc96a8',
|
||||||
|
'f0e1d2c3b4a5968778695a4b3c2d1e0f001122'),
|
||||||
|
('fedcba9876543210', '10851c0e3858da9f',
|
||||||
|
'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233'),
|
||||||
|
('fedcba9876543210', 'e6f51ed79b9db21f',
|
||||||
|
'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344'),
|
||||||
|
('fedcba9876543210', '64a6e14afd36b46f',
|
||||||
|
'f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455'),
|
||||||
|
('fedcba9876543210', '80c7d7d45a5479ad',
|
||||||
|
'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566'),
|
||||||
|
('fedcba9876543210', '05044b62fa52d080',
|
||||||
|
'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Cipher import Blowfish
|
||||||
|
from .common import make_block_tests
|
||||||
|
return make_block_tests(Blowfish, "Blowfish", test_data)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
57
Lib/site-packages/Crypto/SelfTest/Cipher/test_CAST.py
Normal file
57
Lib/site-packages/Crypto/SelfTest/Cipher/test_CAST.py
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/CAST.py: Self-test for the CAST-128 (CAST5) cipher
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Cipher.CAST"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (plaintext, ciphertext, key) tuples.
|
||||||
|
test_data = [
|
||||||
|
# Test vectors from RFC 2144, B.1
|
||||||
|
('0123456789abcdef', '238b4fe5847e44b2',
|
||||||
|
'0123456712345678234567893456789a',
|
||||||
|
'128-bit key'),
|
||||||
|
|
||||||
|
('0123456789abcdef', 'eb6a711a2c02271b',
|
||||||
|
'01234567123456782345',
|
||||||
|
'80-bit key'),
|
||||||
|
|
||||||
|
('0123456789abcdef', '7ac816d16e9b302e',
|
||||||
|
'0123456712',
|
||||||
|
'40-bit key'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Cipher import CAST
|
||||||
|
from .common import make_block_tests
|
||||||
|
return make_block_tests(CAST, "CAST", test_data)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
339
Lib/site-packages/Crypto/SelfTest/Cipher/test_DES.py
Normal file
339
Lib/site-packages/Crypto/SelfTest/Cipher/test_DES.py
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/DES.py: Self-test for the (Single) DES cipher
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Cipher.DES"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from .common import dict # For compatibility with Python 2.1 and 2.2
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# This is a list of (plaintext, ciphertext, key, description) tuples.
|
||||||
|
SP800_17_B1_KEY = '01' * 8
|
||||||
|
SP800_17_B2_PT = '00' * 8
|
||||||
|
test_data = [
|
||||||
|
# Test vectors from Appendix A of NIST SP 800-17
|
||||||
|
# "Modes of Operation Validation System (MOVS): Requirements and Procedures"
|
||||||
|
# http://csrc.nist.gov/publications/nistpubs/800-17/800-17.pdf
|
||||||
|
|
||||||
|
# Appendix A - "Sample Round Outputs for the DES"
|
||||||
|
('0000000000000000', '82dcbafbdeab6602', '10316e028c8f3b4a',
|
||||||
|
"NIST SP800-17 A"),
|
||||||
|
|
||||||
|
# Table B.1 - Variable Plaintext Known Answer Test
|
||||||
|
('8000000000000000', '95f8a5e5dd31d900', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #0'),
|
||||||
|
('4000000000000000', 'dd7f121ca5015619', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #1'),
|
||||||
|
('2000000000000000', '2e8653104f3834ea', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #2'),
|
||||||
|
('1000000000000000', '4bd388ff6cd81d4f', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #3'),
|
||||||
|
('0800000000000000', '20b9e767b2fb1456', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #4'),
|
||||||
|
('0400000000000000', '55579380d77138ef', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #5'),
|
||||||
|
('0200000000000000', '6cc5defaaf04512f', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #6'),
|
||||||
|
('0100000000000000', '0d9f279ba5d87260', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #7'),
|
||||||
|
('0080000000000000', 'd9031b0271bd5a0a', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #8'),
|
||||||
|
('0040000000000000', '424250b37c3dd951', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #9'),
|
||||||
|
('0020000000000000', 'b8061b7ecd9a21e5', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #10'),
|
||||||
|
('0010000000000000', 'f15d0f286b65bd28', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #11'),
|
||||||
|
('0008000000000000', 'add0cc8d6e5deba1', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #12'),
|
||||||
|
('0004000000000000', 'e6d5f82752ad63d1', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #13'),
|
||||||
|
('0002000000000000', 'ecbfe3bd3f591a5e', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #14'),
|
||||||
|
('0001000000000000', 'f356834379d165cd', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #15'),
|
||||||
|
('0000800000000000', '2b9f982f20037fa9', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #16'),
|
||||||
|
('0000400000000000', '889de068a16f0be6', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #17'),
|
||||||
|
('0000200000000000', 'e19e275d846a1298', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #18'),
|
||||||
|
('0000100000000000', '329a8ed523d71aec', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #19'),
|
||||||
|
('0000080000000000', 'e7fce22557d23c97', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #20'),
|
||||||
|
('0000040000000000', '12a9f5817ff2d65d', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #21'),
|
||||||
|
('0000020000000000', 'a484c3ad38dc9c19', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #22'),
|
||||||
|
('0000010000000000', 'fbe00a8a1ef8ad72', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #23'),
|
||||||
|
('0000008000000000', '750d079407521363', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #24'),
|
||||||
|
('0000004000000000', '64feed9c724c2faf', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #25'),
|
||||||
|
('0000002000000000', 'f02b263b328e2b60', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #26'),
|
||||||
|
('0000001000000000', '9d64555a9a10b852', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #27'),
|
||||||
|
('0000000800000000', 'd106ff0bed5255d7', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #28'),
|
||||||
|
('0000000400000000', 'e1652c6b138c64a5', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #29'),
|
||||||
|
('0000000200000000', 'e428581186ec8f46', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #30'),
|
||||||
|
('0000000100000000', 'aeb5f5ede22d1a36', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #31'),
|
||||||
|
('0000000080000000', 'e943d7568aec0c5c', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #32'),
|
||||||
|
('0000000040000000', 'df98c8276f54b04b', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #33'),
|
||||||
|
('0000000020000000', 'b160e4680f6c696f', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #34'),
|
||||||
|
('0000000010000000', 'fa0752b07d9c4ab8', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #35'),
|
||||||
|
('0000000008000000', 'ca3a2b036dbc8502', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #36'),
|
||||||
|
('0000000004000000', '5e0905517bb59bcf', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #37'),
|
||||||
|
('0000000002000000', '814eeb3b91d90726', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #38'),
|
||||||
|
('0000000001000000', '4d49db1532919c9f', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #39'),
|
||||||
|
('0000000000800000', '25eb5fc3f8cf0621', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #40'),
|
||||||
|
('0000000000400000', 'ab6a20c0620d1c6f', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #41'),
|
||||||
|
('0000000000200000', '79e90dbc98f92cca', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #42'),
|
||||||
|
('0000000000100000', '866ecedd8072bb0e', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #43'),
|
||||||
|
('0000000000080000', '8b54536f2f3e64a8', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #44'),
|
||||||
|
('0000000000040000', 'ea51d3975595b86b', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #45'),
|
||||||
|
('0000000000020000', 'caffc6ac4542de31', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #46'),
|
||||||
|
('0000000000010000', '8dd45a2ddf90796c', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #47'),
|
||||||
|
('0000000000008000', '1029d55e880ec2d0', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #48'),
|
||||||
|
('0000000000004000', '5d86cb23639dbea9', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #49'),
|
||||||
|
('0000000000002000', '1d1ca853ae7c0c5f', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #50'),
|
||||||
|
('0000000000001000', 'ce332329248f3228', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #51'),
|
||||||
|
('0000000000000800', '8405d1abe24fb942', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #52'),
|
||||||
|
('0000000000000400', 'e643d78090ca4207', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #53'),
|
||||||
|
('0000000000000200', '48221b9937748a23', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #54'),
|
||||||
|
('0000000000000100', 'dd7c0bbd61fafd54', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #55'),
|
||||||
|
('0000000000000080', '2fbc291a570db5c4', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #56'),
|
||||||
|
('0000000000000040', 'e07c30d7e4e26e12', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #57'),
|
||||||
|
('0000000000000020', '0953e2258e8e90a1', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #58'),
|
||||||
|
('0000000000000010', '5b711bc4ceebf2ee', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #59'),
|
||||||
|
('0000000000000008', 'cc083f1e6d9e85f6', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #60'),
|
||||||
|
('0000000000000004', 'd2fd8867d50d2dfe', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #61'),
|
||||||
|
('0000000000000002', '06e7ea22ce92708f', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #62'),
|
||||||
|
('0000000000000001', '166b40b44aba4bd6', SP800_17_B1_KEY,
|
||||||
|
'NIST SP800-17 B.1 #63'),
|
||||||
|
|
||||||
|
# Table B.2 - Variable Key Known Answer Test
|
||||||
|
(SP800_17_B2_PT, '95a8d72813daa94d', '8001010101010101',
|
||||||
|
'NIST SP800-17 B.2 #0'),
|
||||||
|
(SP800_17_B2_PT, '0eec1487dd8c26d5', '4001010101010101',
|
||||||
|
'NIST SP800-17 B.2 #1'),
|
||||||
|
(SP800_17_B2_PT, '7ad16ffb79c45926', '2001010101010101',
|
||||||
|
'NIST SP800-17 B.2 #2'),
|
||||||
|
(SP800_17_B2_PT, 'd3746294ca6a6cf3', '1001010101010101',
|
||||||
|
'NIST SP800-17 B.2 #3'),
|
||||||
|
(SP800_17_B2_PT, '809f5f873c1fd761', '0801010101010101',
|
||||||
|
'NIST SP800-17 B.2 #4'),
|
||||||
|
(SP800_17_B2_PT, 'c02faffec989d1fc', '0401010101010101',
|
||||||
|
'NIST SP800-17 B.2 #5'),
|
||||||
|
(SP800_17_B2_PT, '4615aa1d33e72f10', '0201010101010101',
|
||||||
|
'NIST SP800-17 B.2 #6'),
|
||||||
|
(SP800_17_B2_PT, '2055123350c00858', '0180010101010101',
|
||||||
|
'NIST SP800-17 B.2 #7'),
|
||||||
|
(SP800_17_B2_PT, 'df3b99d6577397c8', '0140010101010101',
|
||||||
|
'NIST SP800-17 B.2 #8'),
|
||||||
|
(SP800_17_B2_PT, '31fe17369b5288c9', '0120010101010101',
|
||||||
|
'NIST SP800-17 B.2 #9'),
|
||||||
|
(SP800_17_B2_PT, 'dfdd3cc64dae1642', '0110010101010101',
|
||||||
|
'NIST SP800-17 B.2 #10'),
|
||||||
|
(SP800_17_B2_PT, '178c83ce2b399d94', '0108010101010101',
|
||||||
|
'NIST SP800-17 B.2 #11'),
|
||||||
|
(SP800_17_B2_PT, '50f636324a9b7f80', '0104010101010101',
|
||||||
|
'NIST SP800-17 B.2 #12'),
|
||||||
|
(SP800_17_B2_PT, 'a8468ee3bc18f06d', '0102010101010101',
|
||||||
|
'NIST SP800-17 B.2 #13'),
|
||||||
|
(SP800_17_B2_PT, 'a2dc9e92fd3cde92', '0101800101010101',
|
||||||
|
'NIST SP800-17 B.2 #14'),
|
||||||
|
(SP800_17_B2_PT, 'cac09f797d031287', '0101400101010101',
|
||||||
|
'NIST SP800-17 B.2 #15'),
|
||||||
|
(SP800_17_B2_PT, '90ba680b22aeb525', '0101200101010101',
|
||||||
|
'NIST SP800-17 B.2 #16'),
|
||||||
|
(SP800_17_B2_PT, 'ce7a24f350e280b6', '0101100101010101',
|
||||||
|
'NIST SP800-17 B.2 #17'),
|
||||||
|
(SP800_17_B2_PT, '882bff0aa01a0b87', '0101080101010101',
|
||||||
|
'NIST SP800-17 B.2 #18'),
|
||||||
|
(SP800_17_B2_PT, '25610288924511c2', '0101040101010101',
|
||||||
|
'NIST SP800-17 B.2 #19'),
|
||||||
|
(SP800_17_B2_PT, 'c71516c29c75d170', '0101020101010101',
|
||||||
|
'NIST SP800-17 B.2 #20'),
|
||||||
|
(SP800_17_B2_PT, '5199c29a52c9f059', '0101018001010101',
|
||||||
|
'NIST SP800-17 B.2 #21'),
|
||||||
|
(SP800_17_B2_PT, 'c22f0a294a71f29f', '0101014001010101',
|
||||||
|
'NIST SP800-17 B.2 #22'),
|
||||||
|
(SP800_17_B2_PT, 'ee371483714c02ea', '0101012001010101',
|
||||||
|
'NIST SP800-17 B.2 #23'),
|
||||||
|
(SP800_17_B2_PT, 'a81fbd448f9e522f', '0101011001010101',
|
||||||
|
'NIST SP800-17 B.2 #24'),
|
||||||
|
(SP800_17_B2_PT, '4f644c92e192dfed', '0101010801010101',
|
||||||
|
'NIST SP800-17 B.2 #25'),
|
||||||
|
(SP800_17_B2_PT, '1afa9a66a6df92ae', '0101010401010101',
|
||||||
|
'NIST SP800-17 B.2 #26'),
|
||||||
|
(SP800_17_B2_PT, 'b3c1cc715cb879d8', '0101010201010101',
|
||||||
|
'NIST SP800-17 B.2 #27'),
|
||||||
|
(SP800_17_B2_PT, '19d032e64ab0bd8b', '0101010180010101',
|
||||||
|
'NIST SP800-17 B.2 #28'),
|
||||||
|
(SP800_17_B2_PT, '3cfaa7a7dc8720dc', '0101010140010101',
|
||||||
|
'NIST SP800-17 B.2 #29'),
|
||||||
|
(SP800_17_B2_PT, 'b7265f7f447ac6f3', '0101010120010101',
|
||||||
|
'NIST SP800-17 B.2 #30'),
|
||||||
|
(SP800_17_B2_PT, '9db73b3c0d163f54', '0101010110010101',
|
||||||
|
'NIST SP800-17 B.2 #31'),
|
||||||
|
(SP800_17_B2_PT, '8181b65babf4a975', '0101010108010101',
|
||||||
|
'NIST SP800-17 B.2 #32'),
|
||||||
|
(SP800_17_B2_PT, '93c9b64042eaa240', '0101010104010101',
|
||||||
|
'NIST SP800-17 B.2 #33'),
|
||||||
|
(SP800_17_B2_PT, '5570530829705592', '0101010102010101',
|
||||||
|
'NIST SP800-17 B.2 #34'),
|
||||||
|
(SP800_17_B2_PT, '8638809e878787a0', '0101010101800101',
|
||||||
|
'NIST SP800-17 B.2 #35'),
|
||||||
|
(SP800_17_B2_PT, '41b9a79af79ac208', '0101010101400101',
|
||||||
|
'NIST SP800-17 B.2 #36'),
|
||||||
|
(SP800_17_B2_PT, '7a9be42f2009a892', '0101010101200101',
|
||||||
|
'NIST SP800-17 B.2 #37'),
|
||||||
|
(SP800_17_B2_PT, '29038d56ba6d2745', '0101010101100101',
|
||||||
|
'NIST SP800-17 B.2 #38'),
|
||||||
|
(SP800_17_B2_PT, '5495c6abf1e5df51', '0101010101080101',
|
||||||
|
'NIST SP800-17 B.2 #39'),
|
||||||
|
(SP800_17_B2_PT, 'ae13dbd561488933', '0101010101040101',
|
||||||
|
'NIST SP800-17 B.2 #40'),
|
||||||
|
(SP800_17_B2_PT, '024d1ffa8904e389', '0101010101020101',
|
||||||
|
'NIST SP800-17 B.2 #41'),
|
||||||
|
(SP800_17_B2_PT, 'd1399712f99bf02e', '0101010101018001',
|
||||||
|
'NIST SP800-17 B.2 #42'),
|
||||||
|
(SP800_17_B2_PT, '14c1d7c1cffec79e', '0101010101014001',
|
||||||
|
'NIST SP800-17 B.2 #43'),
|
||||||
|
(SP800_17_B2_PT, '1de5279dae3bed6f', '0101010101012001',
|
||||||
|
'NIST SP800-17 B.2 #44'),
|
||||||
|
(SP800_17_B2_PT, 'e941a33f85501303', '0101010101011001',
|
||||||
|
'NIST SP800-17 B.2 #45'),
|
||||||
|
(SP800_17_B2_PT, 'da99dbbc9a03f379', '0101010101010801',
|
||||||
|
'NIST SP800-17 B.2 #46'),
|
||||||
|
(SP800_17_B2_PT, 'b7fc92f91d8e92e9', '0101010101010401',
|
||||||
|
'NIST SP800-17 B.2 #47'),
|
||||||
|
(SP800_17_B2_PT, 'ae8e5caa3ca04e85', '0101010101010201',
|
||||||
|
'NIST SP800-17 B.2 #48'),
|
||||||
|
(SP800_17_B2_PT, '9cc62df43b6eed74', '0101010101010180',
|
||||||
|
'NIST SP800-17 B.2 #49'),
|
||||||
|
(SP800_17_B2_PT, 'd863dbb5c59a91a0', '0101010101010140',
|
||||||
|
'NIST SP800-17 B.2 #50'),
|
||||||
|
(SP800_17_B2_PT, 'a1ab2190545b91d7', '0101010101010120',
|
||||||
|
'NIST SP800-17 B.2 #51'),
|
||||||
|
(SP800_17_B2_PT, '0875041e64c570f7', '0101010101010110',
|
||||||
|
'NIST SP800-17 B.2 #52'),
|
||||||
|
(SP800_17_B2_PT, '5a594528bebef1cc', '0101010101010108',
|
||||||
|
'NIST SP800-17 B.2 #53'),
|
||||||
|
(SP800_17_B2_PT, 'fcdb3291de21f0c0', '0101010101010104',
|
||||||
|
'NIST SP800-17 B.2 #54'),
|
||||||
|
(SP800_17_B2_PT, '869efd7f9f265a09', '0101010101010102',
|
||||||
|
'NIST SP800-17 B.2 #55'),
|
||||||
|
]
|
||||||
|
|
||||||
|
class RonRivestTest(unittest.TestCase):
|
||||||
|
""" Ronald L. Rivest's DES test, see
|
||||||
|
http://people.csail.mit.edu/rivest/Destest.txt
|
||||||
|
ABSTRACT
|
||||||
|
--------
|
||||||
|
|
||||||
|
We present a simple way to test the correctness of a DES implementation:
|
||||||
|
Use the recurrence relation:
|
||||||
|
|
||||||
|
X0 = 9474B8E8C73BCA7D (hexadecimal)
|
||||||
|
|
||||||
|
X(i+1) = IF (i is even) THEN E(Xi,Xi) ELSE D(Xi,Xi)
|
||||||
|
|
||||||
|
to compute a sequence of 64-bit values: X0, X1, X2, ..., X16. Here
|
||||||
|
E(X,K) denotes the DES encryption of X using key K, and D(X,K) denotes
|
||||||
|
the DES decryption of X using key K. If you obtain
|
||||||
|
|
||||||
|
X16 = 1B1A2DDB4C642438
|
||||||
|
|
||||||
|
your implementation does not have any of the 36,568 possible single-fault
|
||||||
|
errors described herein.
|
||||||
|
"""
|
||||||
|
def runTest(self):
|
||||||
|
from Crypto.Cipher import DES
|
||||||
|
from binascii import b2a_hex
|
||||||
|
|
||||||
|
X = []
|
||||||
|
X[0:] = [b('\x94\x74\xB8\xE8\xC7\x3B\xCA\x7D')]
|
||||||
|
|
||||||
|
for i in range(16):
|
||||||
|
c = DES.new(X[i],DES.MODE_ECB)
|
||||||
|
if not (i&1): # (num&1) returns 1 for odd numbers
|
||||||
|
X[i+1:] = [c.encrypt(X[i])] # even
|
||||||
|
else:
|
||||||
|
X[i+1:] = [c.decrypt(X[i])] # odd
|
||||||
|
|
||||||
|
self.assertEqual(b2a_hex(X[16]),
|
||||||
|
b2a_hex(b('\x1B\x1A\x2D\xDB\x4C\x64\x24\x38')))
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Cipher import DES
|
||||||
|
from .common import make_block_tests
|
||||||
|
return make_block_tests(DES, "DES", test_data) + [RonRivestTest()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
333
Lib/site-packages/Crypto/SelfTest/Cipher/test_DES3.py
Normal file
333
Lib/site-packages/Crypto/SelfTest/Cipher/test_DES3.py
Normal file
|
@ -0,0 +1,333 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/DES3.py: Self-test for the Triple-DES cipher
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Cipher.DES3"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from .common import dict # For compatibility with Python 2.1 and 2.2
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from binascii import hexlify
|
||||||
|
|
||||||
|
# This is a list of (plaintext, ciphertext, key, description) tuples.
|
||||||
|
SP800_20_A1_KEY = '01' * 24
|
||||||
|
SP800_20_A2_PT = '00' * 8
|
||||||
|
test_data = [
|
||||||
|
# Test vector from Appendix B of NIST SP 800-67
|
||||||
|
# "Recommendation for the Triple Data Encryption Algorithm (TDEA) Block
|
||||||
|
# Cipher"
|
||||||
|
# http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf
|
||||||
|
('54686520717566636b2062726f776e20666f78206a756d70',
|
||||||
|
'a826fd8ce53b855fcce21c8112256fe668d5c05dd9b6b900',
|
||||||
|
'0123456789abcdef23456789abcdef01456789abcdef0123',
|
||||||
|
'NIST SP800-67 B.1'),
|
||||||
|
|
||||||
|
# Test vectors "The Multi-block Message Test (MMT) for DES and TDES"
|
||||||
|
# http://csrc.nist.gov/groups/STM/cavp/documents/des/DESMMT.pdf
|
||||||
|
('326a494cd33fe756', 'b22b8d66de970692',
|
||||||
|
'627f460e08104a1043cd265d5840eaf1313edf97df2a8a8c',
|
||||||
|
'DESMMT #1', dict(mode='CBC', iv='8e29f75ea77e5475')),
|
||||||
|
|
||||||
|
('84401f78fe6c10876d8ea23094ea5309', '7b1f7c7e3b1c948ebd04a75ffba7d2f5',
|
||||||
|
'37ae5ebf46dff2dc0754b94f31cbb3855e7fd36dc870bfae',
|
||||||
|
'DESMMT #2', dict(mode='CBC', iv='3d1de3cc132e3b65')),
|
||||||
|
|
||||||
|
# Test vectors from Appendix A of NIST SP 800-20
|
||||||
|
# "Modes of Operation Validation System for the Triple Data Encryption
|
||||||
|
# Algorithm (TMOVS): Requirements and Procedures"
|
||||||
|
# http://csrc.nist.gov/publications/nistpubs/800-20/800-20.pdf
|
||||||
|
|
||||||
|
# Table A.1 - Variable Plaintext Known Answer Test
|
||||||
|
('8000000000000000', '95f8a5e5dd31d900', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #0'),
|
||||||
|
('4000000000000000', 'dd7f121ca5015619', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #1'),
|
||||||
|
('2000000000000000', '2e8653104f3834ea', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #2'),
|
||||||
|
('1000000000000000', '4bd388ff6cd81d4f', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #3'),
|
||||||
|
('0800000000000000', '20b9e767b2fb1456', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #4'),
|
||||||
|
('0400000000000000', '55579380d77138ef', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #5'),
|
||||||
|
('0200000000000000', '6cc5defaaf04512f', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #6'),
|
||||||
|
('0100000000000000', '0d9f279ba5d87260', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #7'),
|
||||||
|
('0080000000000000', 'd9031b0271bd5a0a', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #8'),
|
||||||
|
('0040000000000000', '424250b37c3dd951', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #9'),
|
||||||
|
('0020000000000000', 'b8061b7ecd9a21e5', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #10'),
|
||||||
|
('0010000000000000', 'f15d0f286b65bd28', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #11'),
|
||||||
|
('0008000000000000', 'add0cc8d6e5deba1', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #12'),
|
||||||
|
('0004000000000000', 'e6d5f82752ad63d1', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #13'),
|
||||||
|
('0002000000000000', 'ecbfe3bd3f591a5e', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #14'),
|
||||||
|
('0001000000000000', 'f356834379d165cd', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #15'),
|
||||||
|
('0000800000000000', '2b9f982f20037fa9', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #16'),
|
||||||
|
('0000400000000000', '889de068a16f0be6', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #17'),
|
||||||
|
('0000200000000000', 'e19e275d846a1298', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #18'),
|
||||||
|
('0000100000000000', '329a8ed523d71aec', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #19'),
|
||||||
|
('0000080000000000', 'e7fce22557d23c97', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #20'),
|
||||||
|
('0000040000000000', '12a9f5817ff2d65d', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #21'),
|
||||||
|
('0000020000000000', 'a484c3ad38dc9c19', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #22'),
|
||||||
|
('0000010000000000', 'fbe00a8a1ef8ad72', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #23'),
|
||||||
|
('0000008000000000', '750d079407521363', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #24'),
|
||||||
|
('0000004000000000', '64feed9c724c2faf', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #25'),
|
||||||
|
('0000002000000000', 'f02b263b328e2b60', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #26'),
|
||||||
|
('0000001000000000', '9d64555a9a10b852', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #27'),
|
||||||
|
('0000000800000000', 'd106ff0bed5255d7', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #28'),
|
||||||
|
('0000000400000000', 'e1652c6b138c64a5', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #29'),
|
||||||
|
('0000000200000000', 'e428581186ec8f46', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #30'),
|
||||||
|
('0000000100000000', 'aeb5f5ede22d1a36', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #31'),
|
||||||
|
('0000000080000000', 'e943d7568aec0c5c', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #32'),
|
||||||
|
('0000000040000000', 'df98c8276f54b04b', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #33'),
|
||||||
|
('0000000020000000', 'b160e4680f6c696f', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #34'),
|
||||||
|
('0000000010000000', 'fa0752b07d9c4ab8', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #35'),
|
||||||
|
('0000000008000000', 'ca3a2b036dbc8502', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #36'),
|
||||||
|
('0000000004000000', '5e0905517bb59bcf', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #37'),
|
||||||
|
('0000000002000000', '814eeb3b91d90726', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #38'),
|
||||||
|
('0000000001000000', '4d49db1532919c9f', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #39'),
|
||||||
|
('0000000000800000', '25eb5fc3f8cf0621', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #40'),
|
||||||
|
('0000000000400000', 'ab6a20c0620d1c6f', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #41'),
|
||||||
|
('0000000000200000', '79e90dbc98f92cca', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #42'),
|
||||||
|
('0000000000100000', '866ecedd8072bb0e', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #43'),
|
||||||
|
('0000000000080000', '8b54536f2f3e64a8', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #44'),
|
||||||
|
('0000000000040000', 'ea51d3975595b86b', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #45'),
|
||||||
|
('0000000000020000', 'caffc6ac4542de31', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #46'),
|
||||||
|
('0000000000010000', '8dd45a2ddf90796c', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #47'),
|
||||||
|
('0000000000008000', '1029d55e880ec2d0', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #48'),
|
||||||
|
('0000000000004000', '5d86cb23639dbea9', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #49'),
|
||||||
|
('0000000000002000', '1d1ca853ae7c0c5f', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #50'),
|
||||||
|
('0000000000001000', 'ce332329248f3228', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #51'),
|
||||||
|
('0000000000000800', '8405d1abe24fb942', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #52'),
|
||||||
|
('0000000000000400', 'e643d78090ca4207', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #53'),
|
||||||
|
('0000000000000200', '48221b9937748a23', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #54'),
|
||||||
|
('0000000000000100', 'dd7c0bbd61fafd54', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #55'),
|
||||||
|
('0000000000000080', '2fbc291a570db5c4', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #56'),
|
||||||
|
('0000000000000040', 'e07c30d7e4e26e12', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #57'),
|
||||||
|
('0000000000000020', '0953e2258e8e90a1', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #58'),
|
||||||
|
('0000000000000010', '5b711bc4ceebf2ee', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #59'),
|
||||||
|
('0000000000000008', 'cc083f1e6d9e85f6', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #60'),
|
||||||
|
('0000000000000004', 'd2fd8867d50d2dfe', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #61'),
|
||||||
|
('0000000000000002', '06e7ea22ce92708f', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #62'),
|
||||||
|
('0000000000000001', '166b40b44aba4bd6', SP800_20_A1_KEY,
|
||||||
|
'NIST SP800-20 A.1 #63'),
|
||||||
|
|
||||||
|
# Table A.2 - Variable Key Known Answer Test
|
||||||
|
(SP800_20_A2_PT, '95a8d72813daa94d', '8001010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #0'),
|
||||||
|
(SP800_20_A2_PT, '0eec1487dd8c26d5', '4001010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #1'),
|
||||||
|
(SP800_20_A2_PT, '7ad16ffb79c45926', '2001010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #2'),
|
||||||
|
(SP800_20_A2_PT, 'd3746294ca6a6cf3', '1001010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #3'),
|
||||||
|
(SP800_20_A2_PT, '809f5f873c1fd761', '0801010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #4'),
|
||||||
|
(SP800_20_A2_PT, 'c02faffec989d1fc', '0401010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #5'),
|
||||||
|
(SP800_20_A2_PT, '4615aa1d33e72f10', '0201010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #6'),
|
||||||
|
(SP800_20_A2_PT, '2055123350c00858', '0180010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #7'),
|
||||||
|
(SP800_20_A2_PT, 'df3b99d6577397c8', '0140010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #8'),
|
||||||
|
(SP800_20_A2_PT, '31fe17369b5288c9', '0120010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #9'),
|
||||||
|
(SP800_20_A2_PT, 'dfdd3cc64dae1642', '0110010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #10'),
|
||||||
|
(SP800_20_A2_PT, '178c83ce2b399d94', '0108010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #11'),
|
||||||
|
(SP800_20_A2_PT, '50f636324a9b7f80', '0104010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #12'),
|
||||||
|
(SP800_20_A2_PT, 'a8468ee3bc18f06d', '0102010101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #13'),
|
||||||
|
(SP800_20_A2_PT, 'a2dc9e92fd3cde92', '0101800101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #14'),
|
||||||
|
(SP800_20_A2_PT, 'cac09f797d031287', '0101400101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #15'),
|
||||||
|
(SP800_20_A2_PT, '90ba680b22aeb525', '0101200101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #16'),
|
||||||
|
(SP800_20_A2_PT, 'ce7a24f350e280b6', '0101100101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #17'),
|
||||||
|
(SP800_20_A2_PT, '882bff0aa01a0b87', '0101080101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #18'),
|
||||||
|
(SP800_20_A2_PT, '25610288924511c2', '0101040101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #19'),
|
||||||
|
(SP800_20_A2_PT, 'c71516c29c75d170', '0101020101010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #20'),
|
||||||
|
(SP800_20_A2_PT, '5199c29a52c9f059', '0101018001010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #21'),
|
||||||
|
(SP800_20_A2_PT, 'c22f0a294a71f29f', '0101014001010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #22'),
|
||||||
|
(SP800_20_A2_PT, 'ee371483714c02ea', '0101012001010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #23'),
|
||||||
|
(SP800_20_A2_PT, 'a81fbd448f9e522f', '0101011001010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #24'),
|
||||||
|
(SP800_20_A2_PT, '4f644c92e192dfed', '0101010801010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #25'),
|
||||||
|
(SP800_20_A2_PT, '1afa9a66a6df92ae', '0101010401010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #26'),
|
||||||
|
(SP800_20_A2_PT, 'b3c1cc715cb879d8', '0101010201010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #27'),
|
||||||
|
(SP800_20_A2_PT, '19d032e64ab0bd8b', '0101010180010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #28'),
|
||||||
|
(SP800_20_A2_PT, '3cfaa7a7dc8720dc', '0101010140010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #29'),
|
||||||
|
(SP800_20_A2_PT, 'b7265f7f447ac6f3', '0101010120010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #30'),
|
||||||
|
(SP800_20_A2_PT, '9db73b3c0d163f54', '0101010110010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #31'),
|
||||||
|
(SP800_20_A2_PT, '8181b65babf4a975', '0101010108010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #32'),
|
||||||
|
(SP800_20_A2_PT, '93c9b64042eaa240', '0101010104010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #33'),
|
||||||
|
(SP800_20_A2_PT, '5570530829705592', '0101010102010101'*3,
|
||||||
|
'NIST SP800-20 A.2 #34'),
|
||||||
|
(SP800_20_A2_PT, '8638809e878787a0', '0101010101800101'*3,
|
||||||
|
'NIST SP800-20 A.2 #35'),
|
||||||
|
(SP800_20_A2_PT, '41b9a79af79ac208', '0101010101400101'*3,
|
||||||
|
'NIST SP800-20 A.2 #36'),
|
||||||
|
(SP800_20_A2_PT, '7a9be42f2009a892', '0101010101200101'*3,
|
||||||
|
'NIST SP800-20 A.2 #37'),
|
||||||
|
(SP800_20_A2_PT, '29038d56ba6d2745', '0101010101100101'*3,
|
||||||
|
'NIST SP800-20 A.2 #38'),
|
||||||
|
(SP800_20_A2_PT, '5495c6abf1e5df51', '0101010101080101'*3,
|
||||||
|
'NIST SP800-20 A.2 #39'),
|
||||||
|
(SP800_20_A2_PT, 'ae13dbd561488933', '0101010101040101'*3,
|
||||||
|
'NIST SP800-20 A.2 #40'),
|
||||||
|
(SP800_20_A2_PT, '024d1ffa8904e389', '0101010101020101'*3,
|
||||||
|
'NIST SP800-20 A.2 #41'),
|
||||||
|
(SP800_20_A2_PT, 'd1399712f99bf02e', '0101010101018001'*3,
|
||||||
|
'NIST SP800-20 A.2 #42'),
|
||||||
|
(SP800_20_A2_PT, '14c1d7c1cffec79e', '0101010101014001'*3,
|
||||||
|
'NIST SP800-20 A.2 #43'),
|
||||||
|
(SP800_20_A2_PT, '1de5279dae3bed6f', '0101010101012001'*3,
|
||||||
|
'NIST SP800-20 A.2 #44'),
|
||||||
|
(SP800_20_A2_PT, 'e941a33f85501303', '0101010101011001'*3,
|
||||||
|
'NIST SP800-20 A.2 #45'),
|
||||||
|
(SP800_20_A2_PT, 'da99dbbc9a03f379', '0101010101010801'*3,
|
||||||
|
'NIST SP800-20 A.2 #46'),
|
||||||
|
(SP800_20_A2_PT, 'b7fc92f91d8e92e9', '0101010101010401'*3,
|
||||||
|
'NIST SP800-20 A.2 #47'),
|
||||||
|
(SP800_20_A2_PT, 'ae8e5caa3ca04e85', '0101010101010201'*3,
|
||||||
|
'NIST SP800-20 A.2 #48'),
|
||||||
|
(SP800_20_A2_PT, '9cc62df43b6eed74', '0101010101010180'*3,
|
||||||
|
'NIST SP800-20 A.2 #49'),
|
||||||
|
(SP800_20_A2_PT, 'd863dbb5c59a91a0', '0101010101010140'*3,
|
||||||
|
'NIST SP800-20 A.2 #50'),
|
||||||
|
(SP800_20_A2_PT, 'a1ab2190545b91d7', '0101010101010120'*3,
|
||||||
|
'NIST SP800-20 A.2 #51'),
|
||||||
|
(SP800_20_A2_PT, '0875041e64c570f7', '0101010101010110'*3,
|
||||||
|
'NIST SP800-20 A.2 #52'),
|
||||||
|
(SP800_20_A2_PT, '5a594528bebef1cc', '0101010101010108'*3,
|
||||||
|
'NIST SP800-20 A.2 #53'),
|
||||||
|
(SP800_20_A2_PT, 'fcdb3291de21f0c0', '0101010101010104'*3,
|
||||||
|
'NIST SP800-20 A.2 #54'),
|
||||||
|
(SP800_20_A2_PT, '869efd7f9f265a09', '0101010101010102'*3,
|
||||||
|
'NIST SP800-20 A.2 #55'),
|
||||||
|
|
||||||
|
# "Two-key 3DES". Test vector generated using PyCrypto 2.0.1.
|
||||||
|
# This test is designed to test the DES3 API, not the correctness of the
|
||||||
|
# output.
|
||||||
|
('21e81b7ade88a259', '5c577d4d9b20c0f8',
|
||||||
|
'9b397ebf81b1181e282f4bb8adbadc6b', 'Two-key 3DES'),
|
||||||
|
|
||||||
|
# The following test vectors have been generated with gpg v1.4.0.
|
||||||
|
# The command line used was:
|
||||||
|
# gpg -c -z 0 --cipher-algo 3DES --passphrase secret_passphrase \
|
||||||
|
# --disable-mdc --s2k-mode 0 --output ct pt
|
||||||
|
# For an explanation, see test_AES.py .
|
||||||
|
( 'ac1762037074324fb53ba3596f73656d69746556616c6c6579', # Plaintext, 'YosemiteValley'
|
||||||
|
'9979238528357b90e2e0be549cb0b2d5999b9a4a447e5c5c7d', # Ciphertext
|
||||||
|
'7ade65b460f5ea9be35f9e14aa883a2048e3824aa616c0b2', # Key (hash of 'BearsAhead')
|
||||||
|
'GPG Test Vector #1',
|
||||||
|
dict(mode='OPENPGP', iv='cd47e2afb8b7e4b0', encrypted_iv='6a7eef0b58050e8b904a' ) ),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Cipher import DES3
|
||||||
|
from .common import make_block_tests
|
||||||
|
return make_block_tests(DES3, "DES3", test_data)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
72
Lib/site-packages/Crypto/SelfTest/Cipher/test_XOR.py
Normal file
72
Lib/site-packages/Crypto/SelfTest/Cipher/test_XOR.py
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/XOR.py: Self-test for the XOR "cipher"
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Cipher.XOR"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (plaintext, ciphertext, key) tuples.
|
||||||
|
test_data = [
|
||||||
|
# Test vectors written from scratch. (Nobody posts XOR test vectors on the web? How disappointing.)
|
||||||
|
('01', '01',
|
||||||
|
'00',
|
||||||
|
'zero key'),
|
||||||
|
|
||||||
|
('0102040810204080', '0003050911214181',
|
||||||
|
'01',
|
||||||
|
'1-byte key'),
|
||||||
|
|
||||||
|
('0102040810204080', 'cda8c8a2dc8a8c2a',
|
||||||
|
'ccaa',
|
||||||
|
'2-byte key'),
|
||||||
|
|
||||||
|
('ff'*64, 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0'*2,
|
||||||
|
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||||
|
'32-byte key'),
|
||||||
|
]
|
||||||
|
|
||||||
|
class TruncationSelfTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
"""33-byte key (should raise ValueError under current implementation)"""
|
||||||
|
# Crypto.Cipher.XOR previously truncated its inputs at 32 bytes. Now
|
||||||
|
# it should raise a ValueError if the length is too long.
|
||||||
|
self.assertRaises(ValueError, XOR.new, "x"*33)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
global XOR
|
||||||
|
from Crypto.Cipher import XOR
|
||||||
|
from .common import make_stream_tests
|
||||||
|
return make_stream_tests(XOR, "XOR", test_data) + [TruncationSelfTest()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
174
Lib/site-packages/Crypto/SelfTest/Cipher/test_pkcs1_15.py
Normal file
174
Lib/site-packages/Crypto/SelfTest/Cipher/test_pkcs1_15.py
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/test_pkcs1_15.py: Self-test for PKCS#1 v1.5 encryption
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
|
||||||
|
from Crypto import Random
|
||||||
|
from Crypto.Cipher import PKCS1_v1_5 as PKCS
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
def rws(t):
|
||||||
|
"""Remove white spaces, tabs, and new lines from a string"""
|
||||||
|
for c in ['\n', '\t', ' ']:
|
||||||
|
t = t.replace(c,'')
|
||||||
|
return t
|
||||||
|
|
||||||
|
def t2b(t):
|
||||||
|
"""Convert a text string with bytes in hex form to a byte string"""
|
||||||
|
clean = b(rws(t))
|
||||||
|
if len(clean)%2 == 1:
|
||||||
|
print(clean)
|
||||||
|
raise ValueError("Even number of characters expected")
|
||||||
|
return a2b_hex(clean)
|
||||||
|
|
||||||
|
class PKCS1_15_Tests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.rng = Random.new().read
|
||||||
|
self.key1024 = RSA.generate(1024, self.rng)
|
||||||
|
|
||||||
|
# List of tuples with test data for PKCS#1 v1.5.
|
||||||
|
# Each tuple is made up by:
|
||||||
|
# Item #0: dictionary with RSA key component, or key to import
|
||||||
|
# Item #1: plaintext
|
||||||
|
# Item #2: ciphertext
|
||||||
|
# Item #3: random data
|
||||||
|
|
||||||
|
_testData = (
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generated with openssl 0.9.8o
|
||||||
|
#
|
||||||
|
(
|
||||||
|
# Private key
|
||||||
|
'''-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIICXAIBAAKBgQDAiAnvIAOvqVwJTaYzsKnefZftgtXGE2hPJppGsWl78yz9jeXY
|
||||||
|
W/FxX/gTPURArNhdnhP6n3p2ZaDIBrO2zizbgIXs0IsljTTcr4vnI8fMXzyNUOjA
|
||||||
|
zP3nzMqZDZK6757XQAobOssMkBFqRWwilT/3DsBhRpl3iMUhF+wvpTSHewIDAQAB
|
||||||
|
AoGAC4HV/inOrpgTvSab8Wj0riyZgQOZ3U3ZpSlsfR8ra9Ib9Uee3jCYnKscu6Gk
|
||||||
|
y6zI/cdt8EPJ4PuwAWSNJzbpbVaDvUq25OD+CX8/uRT08yBS4J8TzBitZJTD4lS7
|
||||||
|
atdTnKT0Wmwk+u8tDbhvMKwnUHdJLcuIsycts9rwJVapUtkCQQDvDpx2JMun0YKG
|
||||||
|
uUttjmL8oJ3U0m3ZvMdVwBecA0eebZb1l2J5PvI3EJD97eKe91Nsw8T3lwpoN40k
|
||||||
|
IocSVDklAkEAzi1HLHE6EzVPOe5+Y0kGvrIYRRhncOb72vCvBZvD6wLZpQgqo6c4
|
||||||
|
d3XHFBBQWA6xcvQb5w+VVEJZzw64y25sHwJBAMYReRl6SzL0qA0wIYrYWrOt8JeQ
|
||||||
|
8mthulcWHXmqTgC6FEXP9Es5GD7/fuKl4wqLKZgIbH4nqvvGay7xXLCXD/ECQH9a
|
||||||
|
1JYNMtRen5unSAbIOxRcKkWz92F0LKpm9ZW/S9vFHO+mBcClMGoKJHiuQxLBsLbT
|
||||||
|
NtEZfSJZAeS2sUtn3/0CQDb2M2zNBTF8LlM0nxmh0k9VGm5TVIyBEMcipmvOgqIs
|
||||||
|
HKukWBcq9f/UOmS0oEhai/6g+Uf7VHJdWaeO5LzuvwU=
|
||||||
|
-----END RSA PRIVATE KEY-----''',
|
||||||
|
# Plaintext
|
||||||
|
'''THIS IS PLAINTEXT\x0A''',
|
||||||
|
# Ciphertext
|
||||||
|
'''3f dc fd 3c cd 5c 9b 12 af 65 32 e3 f7 d0 da 36
|
||||||
|
8f 8f d9 e3 13 1c 7f c8 b3 f9 c1 08 e4 eb 79 9c
|
||||||
|
91 89 1f 96 3b 94 77 61 99 a4 b1 ee 5d e6 17 c9
|
||||||
|
5d 0a b5 63 52 0a eb 00 45 38 2a fb b0 71 3d 11
|
||||||
|
f7 a1 9e a7 69 b3 af 61 c0 bb 04 5b 5d 4b 27 44
|
||||||
|
1f 5b 97 89 ba 6a 08 95 ee 4f a2 eb 56 64 e5 0f
|
||||||
|
da 7c f9 9a 61 61 06 62 ed a0 bc 5f aa 6c 31 78
|
||||||
|
70 28 1a bb 98 3c e3 6a 60 3c d1 0b 0f 5a f4 75''',
|
||||||
|
# Random data
|
||||||
|
'''eb d7 7d 86 a4 35 23 a3 54 7e 02 0b 42 1d
|
||||||
|
61 6c af 67 b8 4e 17 56 80 66 36 04 64 34 26 8a
|
||||||
|
47 dd 44 b3 1a b2 17 60 f4 91 2e e2 b5 95 64 cc
|
||||||
|
f9 da c8 70 94 54 86 4c ef 5b 08 7d 18 c4 ab 8d
|
||||||
|
04 06 33 8f ca 15 5f 52 60 8a a1 0c f5 08 b5 4c
|
||||||
|
bb 99 b8 94 25 04 9c e6 01 75 e6 f9 63 7a 65 61
|
||||||
|
13 8a a7 47 77 81 ae 0d b8 2c 4d 50 a5'''
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def testEncrypt1(self):
|
||||||
|
for test in self._testData:
|
||||||
|
# Build the key
|
||||||
|
key = RSA.importKey(test[0])
|
||||||
|
# RNG that takes its random numbers from a pool given
|
||||||
|
# at initialization
|
||||||
|
class randGen:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
self.idx = 0
|
||||||
|
def __call__(self, N):
|
||||||
|
r = self.data[self.idx:N]
|
||||||
|
self.idx += N
|
||||||
|
return r
|
||||||
|
# The real test
|
||||||
|
key._randfunc = randGen(t2b(test[3]))
|
||||||
|
cipher = PKCS.new(key)
|
||||||
|
ct = cipher.encrypt(b(test[1]))
|
||||||
|
self.assertEqual(ct, t2b(test[2]))
|
||||||
|
|
||||||
|
def testEncrypt2(self):
|
||||||
|
# Verify that encryption fail if plaintext is too long
|
||||||
|
pt = '\x00'*(128-11+1)
|
||||||
|
cipher = PKCS.new(self.key1024)
|
||||||
|
self.assertRaises(ValueError, cipher.encrypt, pt)
|
||||||
|
|
||||||
|
def testVerify1(self):
|
||||||
|
for test in self._testData:
|
||||||
|
# Build the key
|
||||||
|
key = RSA.importKey(test[0])
|
||||||
|
# The real test
|
||||||
|
cipher = PKCS.new(key)
|
||||||
|
pt = cipher.decrypt(t2b(test[2]), "---")
|
||||||
|
self.assertEqual(pt, b(test[1]))
|
||||||
|
|
||||||
|
def testVerify2(self):
|
||||||
|
# Verify that decryption fails if ciphertext is not as long as
|
||||||
|
# RSA modulus
|
||||||
|
cipher = PKCS.new(self.key1024)
|
||||||
|
self.assertRaises(ValueError, cipher.decrypt, '\x00'*127, "---")
|
||||||
|
self.assertRaises(ValueError, cipher.decrypt, '\x00'*129, "---")
|
||||||
|
|
||||||
|
# Verify that decryption fails if there are less then 8 non-zero padding
|
||||||
|
# bytes
|
||||||
|
pt = b('\x00\x02' + '\xFF'*7 + '\x00' + '\x45'*118)
|
||||||
|
ct = self.key1024.encrypt(pt, 0)[0]
|
||||||
|
ct = b('\x00'*(128-len(ct))) + ct
|
||||||
|
self.assertEqual("---", cipher.decrypt(ct, "---"))
|
||||||
|
|
||||||
|
def testEncryptVerify1(self):
|
||||||
|
# Encrypt/Verify messages of length [0..RSAlen-11]
|
||||||
|
# and therefore padding [8..117]
|
||||||
|
for pt_len in range(0,128-11+1):
|
||||||
|
pt = self.rng(pt_len)
|
||||||
|
cipher = PKCS.new(self.key1024)
|
||||||
|
ct = cipher.encrypt(pt)
|
||||||
|
pt2 = cipher.decrypt(ct, "---")
|
||||||
|
self.assertEqual(pt,pt2)
|
||||||
|
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
tests += list_test_cases(PKCS1_15_Tests)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
372
Lib/site-packages/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py
Normal file
372
Lib/site-packages/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py
Normal file
|
@ -0,0 +1,372 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Cipher/test_pkcs1_oaep.py: Self-test for PKCS#1 OAEP encryption
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
from Crypto.Cipher import PKCS1_OAEP as PKCS
|
||||||
|
from Crypto.Hash import MD2,MD5,SHA as SHA1,SHA256,RIPEMD
|
||||||
|
from Crypto import Random
|
||||||
|
|
||||||
|
def rws(t):
|
||||||
|
"""Remove white spaces, tabs, and new lines from a string"""
|
||||||
|
for c in ['\n', '\t', ' ']:
|
||||||
|
t = t.replace(c,'')
|
||||||
|
return t
|
||||||
|
|
||||||
|
def t2b(t):
|
||||||
|
"""Convert a text string with bytes in hex form to a byte string"""
|
||||||
|
clean = rws(t)
|
||||||
|
if len(clean)%2 == 1:
|
||||||
|
raise ValueError("Even number of characters expected")
|
||||||
|
return a2b_hex(clean)
|
||||||
|
|
||||||
|
class PKCS1_OAEP_Tests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.rng = Random.new().read
|
||||||
|
self.key1024 = RSA.generate(1024, self.rng)
|
||||||
|
|
||||||
|
# List of tuples with test data for PKCS#1 OAEP
|
||||||
|
# Each tuple is made up by:
|
||||||
|
# Item #0: dictionary with RSA key component
|
||||||
|
# Item #1: plaintext
|
||||||
|
# Item #2: ciphertext
|
||||||
|
# Item #3: random data (=seed)
|
||||||
|
# Item #4: hash object
|
||||||
|
|
||||||
|
_testData = (
|
||||||
|
|
||||||
|
#
|
||||||
|
# From in oaep-int.txt to be found in
|
||||||
|
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
|
||||||
|
#
|
||||||
|
(
|
||||||
|
# Private key
|
||||||
|
{
|
||||||
|
'n':'''bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7
|
||||||
|
36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f
|
||||||
|
b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48
|
||||||
|
76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f
|
||||||
|
af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84
|
||||||
|
ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e
|
||||||
|
e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f
|
||||||
|
e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb''',
|
||||||
|
# Public key
|
||||||
|
'e':'11',
|
||||||
|
# In the test vector, only p and q were given...
|
||||||
|
# d is computed offline as e^{-1} mod (p-1)(q-1)
|
||||||
|
'd':'''a5dafc5341faf289c4b988db30c1cdf83f31251e0
|
||||||
|
668b42784813801579641b29410b3c7998d6bc465745e5c3
|
||||||
|
92669d6870da2c082a939e37fdcb82ec93edac97ff3ad595
|
||||||
|
0accfbc111c76f1a9529444e56aaf68c56c092cd38dc3bef
|
||||||
|
5d20a939926ed4f74a13eddfbe1a1cecc4894af9428c2b7b
|
||||||
|
8883fe4463a4bc85b1cb3c1'''
|
||||||
|
}
|
||||||
|
,
|
||||||
|
# Plaintext
|
||||||
|
'''d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49''',
|
||||||
|
# Ciphertext
|
||||||
|
'''12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0
|
||||||
|
39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7
|
||||||
|
63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6
|
||||||
|
53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb
|
||||||
|
6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0
|
||||||
|
24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48
|
||||||
|
da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d
|
||||||
|
51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55''',
|
||||||
|
# Random
|
||||||
|
'''aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2
|
||||||
|
f0 6c b5 8f''',
|
||||||
|
# Hash
|
||||||
|
SHA1,
|
||||||
|
),
|
||||||
|
|
||||||
|
#
|
||||||
|
# From in oaep-vect.txt to be found in Example 1.1
|
||||||
|
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
|
||||||
|
#
|
||||||
|
(
|
||||||
|
# Private key
|
||||||
|
{
|
||||||
|
'n':'''a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4
|
||||||
|
91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab
|
||||||
|
c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85
|
||||||
|
12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72
|
||||||
|
f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97
|
||||||
|
c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14
|
||||||
|
8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24
|
||||||
|
76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb''',
|
||||||
|
'e':'''01 00 01''',
|
||||||
|
'd':'''53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c
|
||||||
|
55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd
|
||||||
|
8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b
|
||||||
|
15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55
|
||||||
|
fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73
|
||||||
|
2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf
|
||||||
|
b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de
|
||||||
|
f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 '''
|
||||||
|
}
|
||||||
|
,
|
||||||
|
# Plaintext
|
||||||
|
'''66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23
|
||||||
|
97 d5 0d ba 79 b9 87 00 4a fe fe 34''',
|
||||||
|
# Ciphertext
|
||||||
|
'''35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f
|
||||||
|
7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb
|
||||||
|
21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01
|
||||||
|
03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f
|
||||||
|
a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22
|
||||||
|
d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26
|
||||||
|
d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c
|
||||||
|
40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a''',
|
||||||
|
# Random
|
||||||
|
'''18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1
|
||||||
|
dd a0 a5 ef''',
|
||||||
|
SHA1
|
||||||
|
),
|
||||||
|
|
||||||
|
#
|
||||||
|
# From in oaep-vect.txt to be found in Example 2.1
|
||||||
|
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
|
||||||
|
#
|
||||||
|
(
|
||||||
|
# Private key
|
||||||
|
{
|
||||||
|
'n':'''01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5
|
||||||
|
e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e
|
||||||
|
49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba
|
||||||
|
7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d
|
||||||
|
0a 67 f1 4b 16 94 c5 f0 37 94 51 a4 3e 49 a3 2d
|
||||||
|
de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05
|
||||||
|
5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66
|
||||||
|
32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f
|
||||||
|
45''',
|
||||||
|
'e':'''01 00 01''',
|
||||||
|
'd':'''08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa
|
||||||
|
4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93
|
||||||
|
c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47
|
||||||
|
39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc
|
||||||
|
d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0
|
||||||
|
8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59
|
||||||
|
41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25
|
||||||
|
25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39'''
|
||||||
|
},
|
||||||
|
# Plaintext
|
||||||
|
'''8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6
|
||||||
|
52 b5 8c f1 d9 2f ec 57 0b ee e7''',
|
||||||
|
# Ciphertext
|
||||||
|
'''01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99
|
||||||
|
2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a
|
||||||
|
5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a
|
||||||
|
ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34
|
||||||
|
56 65 3a a6 38 2e 9a e5 9b 54 45 52 57 eb 09 9d
|
||||||
|
56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a
|
||||||
|
bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f
|
||||||
|
ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72
|
||||||
|
0e''',
|
||||||
|
# Random
|
||||||
|
'''8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94
|
||||||
|
e7 1b 17 82''',
|
||||||
|
SHA1
|
||||||
|
),
|
||||||
|
|
||||||
|
#
|
||||||
|
# From in oaep-vect.txt to be found in Example 10.1
|
||||||
|
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
|
||||||
|
#
|
||||||
|
(
|
||||||
|
# Private key
|
||||||
|
{
|
||||||
|
'n':'''ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d
|
||||||
|
db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8
|
||||||
|
df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4
|
||||||
|
02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5
|
||||||
|
40 4b 56 9e 4e e1 bd cf 3c 1f b0 3e f1 13 80 2d
|
||||||
|
4f 85 5e b9 b5 13 4b 5a 7c 80 85 ad ca e6 fa 2f
|
||||||
|
a1 41 7e c3 76 3b e1 71 b0 c6 2b 76 0e de 23 c1
|
||||||
|
2a d9 2b 98 08 84 c6 41 f5 a8 fa c2 6b da d4 a0
|
||||||
|
33 81 a2 2f e1 b7 54 88 50 94 c8 25 06 d4 01 9a
|
||||||
|
53 5a 28 6a fe b2 71 bb 9b a5 92 de 18 dc f6 00
|
||||||
|
c2 ae ea e5 6e 02 f7 cf 79 fc 14 cf 3b dc 7c d8
|
||||||
|
4f eb bb f9 50 ca 90 30 4b 22 19 a7 aa 06 3a ef
|
||||||
|
a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76
|
||||||
|
57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88
|
||||||
|
d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc
|
||||||
|
36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb''',
|
||||||
|
'e':'''01 00 01''',
|
||||||
|
'd':'''05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85
|
||||||
|
25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59
|
||||||
|
6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0
|
||||||
|
d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d
|
||||||
|
19 e6 1d b7 c7 41 0a 6b 26 75 df bf 5d 34 5b 80
|
||||||
|
4d 20 1a dd 50 2d 5c e2 df cb 09 1c e9 99 7b be
|
||||||
|
be 57 30 6f 38 3e 4d 58 81 03 f0 36 f7 e8 5d 19
|
||||||
|
34 d1 52 a3 23 e4 a8 db 45 1d 6f 4a 5b 1b 0f 10
|
||||||
|
2c c1 50 e0 2f ee e2 b8 8d ea 4a d4 c1 ba cc b2
|
||||||
|
4d 84 07 2d 14 e1 d2 4a 67 71 f7 40 8e e3 05 64
|
||||||
|
fb 86 d4 39 3a 34 bc f0 b7 88 50 1d 19 33 03 f1
|
||||||
|
3a 22 84 b0 01 f0 f6 49 ea f7 93 28 d4 ac 5c 43
|
||||||
|
0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87
|
||||||
|
6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01
|
||||||
|
84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e
|
||||||
|
97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79'''
|
||||||
|
},
|
||||||
|
# Plaintext
|
||||||
|
'''8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70
|
||||||
|
b0 89 53 b0 6b 4e b2 05 bc 16 94 ee''',
|
||||||
|
# Ciphertext
|
||||||
|
'''53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15
|
||||||
|
52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19
|
||||||
|
ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee
|
||||||
|
e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14
|
||||||
|
4e 2d 0e 60 74 1f 89 93 c3 01 4b 58 b9 b1 95 7a
|
||||||
|
8b ab cd 23 af 85 4f 4c 35 6f b1 66 2a a7 2b fc
|
||||||
|
c7 e5 86 55 9d c4 28 0d 16 0c 12 67 85 a7 23 eb
|
||||||
|
ee be ff 71 f1 15 94 44 0a ae f8 7d 10 79 3a 87
|
||||||
|
74 a2 39 d4 a0 4c 87 fe 14 67 b9 da f8 52 08 ec
|
||||||
|
6c 72 55 79 4a 96 cc 29 14 2f 9a 8b d4 18 e3 c1
|
||||||
|
fd 67 34 4b 0c d0 82 9d f3 b2 be c6 02 53 19 62
|
||||||
|
93 c6 b3 4d 3f 75 d3 2f 21 3d d4 5c 62 73 d5 05
|
||||||
|
ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55
|
||||||
|
ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64
|
||||||
|
73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54
|
||||||
|
bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc''',
|
||||||
|
# Random
|
||||||
|
'''47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0
|
||||||
|
aa 63 bd 33''',
|
||||||
|
SHA1
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def testEncrypt1(self):
|
||||||
|
# Verify encryption using all test vectors
|
||||||
|
for test in self._testData:
|
||||||
|
# Build the key
|
||||||
|
comps = [ int(rws(test[0][x]),16) for x in ('n','e') ]
|
||||||
|
key = RSA.construct(comps)
|
||||||
|
# RNG that takes its random numbers from a pool given
|
||||||
|
# at initialization
|
||||||
|
class randGen:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
self.idx = 0
|
||||||
|
def __call__(self, N):
|
||||||
|
r = self.data[self.idx:N]
|
||||||
|
self.idx += N
|
||||||
|
return r
|
||||||
|
# The real test
|
||||||
|
key._randfunc = randGen(t2b(test[3]))
|
||||||
|
cipher = PKCS.new(key, test[4])
|
||||||
|
ct = cipher.encrypt(t2b(test[1]))
|
||||||
|
self.assertEqual(ct, t2b(test[2]))
|
||||||
|
|
||||||
|
def testEncrypt2(self):
|
||||||
|
# Verify that encryption fails if plaintext is too long
|
||||||
|
pt = '\x00'*(128-2*20-2+1)
|
||||||
|
cipher = PKCS.new(self.key1024)
|
||||||
|
self.assertRaises(ValueError, cipher.encrypt, pt)
|
||||||
|
|
||||||
|
def testDecrypt1(self):
|
||||||
|
# Verify decryption using all test vectors
|
||||||
|
for test in self._testData:
|
||||||
|
# Build the key
|
||||||
|
comps = [ int(rws(test[0][x]),16) for x in ('n','e','d') ]
|
||||||
|
key = RSA.construct(comps)
|
||||||
|
# The real test
|
||||||
|
cipher = PKCS.new(key, test[4])
|
||||||
|
pt = cipher.decrypt(t2b(test[2]))
|
||||||
|
self.assertEqual(pt, t2b(test[1]))
|
||||||
|
|
||||||
|
def testDecrypt2(self):
|
||||||
|
# Simplest possible negative tests
|
||||||
|
for ct_size in (127,128,129):
|
||||||
|
cipher = PKCS.new(self.key1024)
|
||||||
|
self.assertRaises(ValueError, cipher.decrypt, bchr(0x00)*ct_size)
|
||||||
|
|
||||||
|
def testEncryptDecrypt1(self):
|
||||||
|
# Encrypt/Decrypt messages of length [0..128-2*20-2]
|
||||||
|
for pt_len in range(0,128-2*20-2):
|
||||||
|
pt = self.rng(pt_len)
|
||||||
|
ct = PKCS.encrypt(pt, self.key1024)
|
||||||
|
pt2 = PKCS.decrypt(ct, self.key1024)
|
||||||
|
self.assertEqual(pt,pt2)
|
||||||
|
|
||||||
|
def testEncryptDecrypt1(self):
|
||||||
|
# Helper function to monitor what's requested from RNG
|
||||||
|
global asked
|
||||||
|
def localRng(N):
|
||||||
|
global asked
|
||||||
|
asked += N
|
||||||
|
return self.rng(N)
|
||||||
|
# Verify that OAEP is friendly to all hashes
|
||||||
|
for hashmod in (MD2,MD5,SHA1,SHA256,RIPEMD):
|
||||||
|
# Verify that encrypt() asks for as many random bytes
|
||||||
|
# as the hash output size
|
||||||
|
asked = 0
|
||||||
|
pt = self.rng(40)
|
||||||
|
self.key1024._randfunc = localRng
|
||||||
|
cipher = PKCS.new(self.key1024, hashmod)
|
||||||
|
ct = cipher.encrypt(pt)
|
||||||
|
self.assertEqual(cipher.decrypt(ct), pt)
|
||||||
|
self.assertTrue(asked > hashmod.digest_size)
|
||||||
|
|
||||||
|
def testEncryptDecrypt2(self):
|
||||||
|
# Verify that OAEP supports labels
|
||||||
|
pt = self.rng(35)
|
||||||
|
xlabel = self.rng(22)
|
||||||
|
cipher = PKCS.new(self.key1024, label=xlabel)
|
||||||
|
ct = cipher.encrypt(pt)
|
||||||
|
self.assertEqual(cipher.decrypt(ct), pt)
|
||||||
|
|
||||||
|
def testEncryptDecrypt3(self):
|
||||||
|
# Verify that encrypt() uses the custom MGF
|
||||||
|
global mgfcalls
|
||||||
|
# Helper function to monitor what's requested from MGF
|
||||||
|
def newMGF(seed,maskLen):
|
||||||
|
global mgfcalls
|
||||||
|
mgfcalls += 1
|
||||||
|
return bchr(0x00)*maskLen
|
||||||
|
mgfcalls = 0
|
||||||
|
pt = self.rng(32)
|
||||||
|
cipher = PKCS.new(self.key1024, mgfunc=newMGF)
|
||||||
|
ct = cipher.encrypt(pt)
|
||||||
|
self.assertEqual(mgfcalls, 2)
|
||||||
|
self.assertEqual(cipher.decrypt(ct), pt)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
tests += list_test_cases(PKCS1_OAEP_Tests)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
52
Lib/site-packages/Crypto/SelfTest/Hash/__init__.py
Normal file
52
Lib/site-packages/Crypto/SelfTest/Hash/__init__.py
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/__init__.py: Self-test for hash modules
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test for hash modules"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
from Crypto.SelfTest.Hash import test_HMAC; tests += test_HMAC.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Hash import test_MD2; tests += test_MD2.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Hash import test_MD4; tests += test_MD4.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Hash import test_MD5; tests += test_MD5.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Hash import test_RIPEMD; tests += test_RIPEMD.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Hash import test_SHA; tests += test_SHA.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Hash import test_SHA256; tests += test_SHA256.get_tests(config=config)
|
||||||
|
try:
|
||||||
|
from Crypto.SelfTest.Hash import test_SHA224; tests += test_SHA224.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Hash import test_SHA384; tests += test_SHA384.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Hash import test_SHA512; tests += test_SHA512.get_tests(config=config)
|
||||||
|
except ImportError:
|
||||||
|
import sys
|
||||||
|
sys.stderr.write("SelfTest: warning: not testing SHA224/SHA384/SHA512 modules (not available)\n")
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
197
Lib/site-packages/Crypto/SelfTest/Hash/common.py
Normal file
197
Lib/site-packages/Crypto/SelfTest/Hash/common.py
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/common.py: Common code for Crypto.SelfTest.Hash
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-testing for PyCrypto hash modules"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
import binascii
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# For compatibility with Python 2.1 and Python 2.2
|
||||||
|
if sys.hexversion < 0x02030000:
|
||||||
|
# Python 2.1 doesn't have a dict() function
|
||||||
|
# Python 2.2 dict() function raises TypeError if you do dict(MD5='blah')
|
||||||
|
def dict(**kwargs):
|
||||||
|
return kwargs.copy()
|
||||||
|
else:
|
||||||
|
dict = dict
|
||||||
|
|
||||||
|
|
||||||
|
class HashDigestSizeSelfTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def __init__(self, hashmod, description, expected):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.hashmod = hashmod
|
||||||
|
self.expected = expected
|
||||||
|
self.description = description
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return self.description
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
self.assertTrue(hasattr(self.hashmod, "digest_size"))
|
||||||
|
self.assertEqual(self.hashmod.digest_size, self.expected)
|
||||||
|
h = self.hashmod.new()
|
||||||
|
self.assertTrue(hasattr(h, "digest_size"))
|
||||||
|
self.assertEqual(h.digest_size, self.expected)
|
||||||
|
|
||||||
|
|
||||||
|
class HashSelfTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def __init__(self, hashmod, description, expected, input):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.hashmod = hashmod
|
||||||
|
self.expected = expected
|
||||||
|
self.input = input
|
||||||
|
self.description = description
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return self.description
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
h = self.hashmod.new()
|
||||||
|
h.update(self.input)
|
||||||
|
|
||||||
|
out1 = binascii.b2a_hex(h.digest())
|
||||||
|
out2 = h.hexdigest()
|
||||||
|
|
||||||
|
h = self.hashmod.new(self.input)
|
||||||
|
|
||||||
|
out3 = h.hexdigest()
|
||||||
|
out4 = binascii.b2a_hex(h.digest())
|
||||||
|
|
||||||
|
# PY3K: hexdigest() should return str(), and digest() bytes
|
||||||
|
self.assertEqual(self.expected, out1) # h = .new(); h.update(data); h.digest()
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
self.assertEqual(self.expected, out2) # h = .new(); h.update(data); h.hexdigest()
|
||||||
|
self.assertEqual(self.expected, out3) # h = .new(data); h.hexdigest()
|
||||||
|
else:
|
||||||
|
self.assertEqual(self.expected.decode(), out2) # h = .new(); h.update(data); h.hexdigest()
|
||||||
|
self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest()
|
||||||
|
self.assertEqual(self.expected, out4) # h = .new(data); h.digest()
|
||||||
|
|
||||||
|
# Verify that new() object method produces a fresh hash object
|
||||||
|
h2 = h.new()
|
||||||
|
h2.update(self.input)
|
||||||
|
out5 = binascii.b2a_hex(h2.digest())
|
||||||
|
self.assertEqual(self.expected, out5)
|
||||||
|
|
||||||
|
class HashTestOID(unittest.TestCase):
|
||||||
|
def __init__(self, hashmod, oid):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.hashmod = hashmod
|
||||||
|
self.oid = oid
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
h = self.hashmod.new()
|
||||||
|
if self.oid==None:
|
||||||
|
try:
|
||||||
|
raised = 0
|
||||||
|
a = h.oid
|
||||||
|
except AttributeError:
|
||||||
|
raised = 1
|
||||||
|
self.assertEqual(raised,1)
|
||||||
|
else:
|
||||||
|
self.assertEqual(h.oid, self.oid)
|
||||||
|
|
||||||
|
class MACSelfTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def __init__(self, hashmod, description, expected_dict, input, key, hashmods):
|
||||||
|
unittest.TestCase.__init__(self)
|
||||||
|
self.hashmod = hashmod
|
||||||
|
self.expected_dict = expected_dict
|
||||||
|
self.input = input
|
||||||
|
self.key = key
|
||||||
|
self.hashmods = hashmods
|
||||||
|
self.description = description
|
||||||
|
|
||||||
|
def shortDescription(self):
|
||||||
|
return self.description
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
for hashname in list(self.expected_dict.keys()):
|
||||||
|
hashmod = self.hashmods[hashname]
|
||||||
|
key = binascii.a2b_hex(b(self.key))
|
||||||
|
data = binascii.a2b_hex(b(self.input))
|
||||||
|
|
||||||
|
# Strip whitespace from the expected string (which should be in lowercase-hex)
|
||||||
|
expected = b("".join(self.expected_dict[hashname].split()))
|
||||||
|
|
||||||
|
h = self.hashmod.new(key, digestmod=hashmod)
|
||||||
|
h.update(data)
|
||||||
|
out1 = binascii.b2a_hex(h.digest())
|
||||||
|
out2 = h.hexdigest()
|
||||||
|
|
||||||
|
h = self.hashmod.new(key, data, hashmod)
|
||||||
|
|
||||||
|
out3 = h.hexdigest()
|
||||||
|
out4 = binascii.b2a_hex(h.digest())
|
||||||
|
|
||||||
|
# Test .copy()
|
||||||
|
h2 = h.copy()
|
||||||
|
h.update(b("blah blah blah")) # Corrupt the original hash object
|
||||||
|
out5 = binascii.b2a_hex(h2.digest()) # The copied hash object should return the correct result
|
||||||
|
|
||||||
|
# PY3K: hexdigest() should return str(), and digest() bytes
|
||||||
|
self.assertEqual(expected, out1)
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
self.assertEqual(expected, out2)
|
||||||
|
self.assertEqual(expected, out3)
|
||||||
|
else:
|
||||||
|
self.assertEqual(expected.decode(), out2)
|
||||||
|
self.assertEqual(expected.decode(), out3)
|
||||||
|
self.assertEqual(expected, out4)
|
||||||
|
self.assertEqual(expected, out5)
|
||||||
|
|
||||||
|
def make_hash_tests(module, module_name, test_data, digest_size, oid=None):
|
||||||
|
tests = []
|
||||||
|
for i in range(len(test_data)):
|
||||||
|
row = test_data[i]
|
||||||
|
(expected, input) = list(map(b,row[0:2]))
|
||||||
|
if len(row) < 3:
|
||||||
|
description = repr(input)
|
||||||
|
else:
|
||||||
|
description = row[2].encode('latin-1')
|
||||||
|
name = "%s #%d: %s" % (module_name, i+1, description)
|
||||||
|
tests.append(HashSelfTest(module, name, expected, input))
|
||||||
|
if oid is not None:
|
||||||
|
oid = b(oid)
|
||||||
|
name = "%s #%d: digest_size" % (module_name, i+1)
|
||||||
|
tests.append(HashDigestSizeSelfTest(module, name, digest_size))
|
||||||
|
tests.append(HashTestOID(module, oid))
|
||||||
|
return tests
|
||||||
|
|
||||||
|
def make_mac_tests(module, module_name, test_data, hashmods):
|
||||||
|
tests = []
|
||||||
|
for i in range(len(test_data)):
|
||||||
|
row = test_data[i]
|
||||||
|
(key, data, results, description) = row
|
||||||
|
name = "%s #%d: %s" % (module_name, i+1, description)
|
||||||
|
tests.append(MACSelfTest(module, name, results, data, key, hashmods))
|
||||||
|
return tests
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
223
Lib/site-packages/Crypto/SelfTest/Hash/test_HMAC.py
Normal file
223
Lib/site-packages/Crypto/SelfTest/Hash/test_HMAC.py
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/HMAC.py: Self-test for the HMAC module
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Hash.HMAC"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from .common import dict # For compatibility with Python 2.1 and 2.2
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (key, data, results, description) tuples.
|
||||||
|
test_data = [
|
||||||
|
## Test vectors from RFC 2202 ##
|
||||||
|
# Test that the default hashmod is MD5
|
||||||
|
('0b' * 16,
|
||||||
|
'4869205468657265',
|
||||||
|
dict(default='9294727a3638bb1c13f48ef8158bfc9d'),
|
||||||
|
'default-is-MD5'),
|
||||||
|
|
||||||
|
# Test case 1 (MD5)
|
||||||
|
('0b' * 16,
|
||||||
|
'4869205468657265',
|
||||||
|
dict(MD5='9294727a3638bb1c13f48ef8158bfc9d'),
|
||||||
|
'RFC 2202 #1-MD5 (HMAC-MD5)'),
|
||||||
|
|
||||||
|
# Test case 1 (SHA1)
|
||||||
|
('0b' * 20,
|
||||||
|
'4869205468657265',
|
||||||
|
dict(SHA1='b617318655057264e28bc0b6fb378c8ef146be00'),
|
||||||
|
'RFC 2202 #1-SHA1 (HMAC-SHA1)'),
|
||||||
|
|
||||||
|
# Test case 2
|
||||||
|
('4a656665',
|
||||||
|
'7768617420646f2079612077616e7420666f72206e6f7468696e673f',
|
||||||
|
dict(MD5='750c783e6ab0b503eaa86e310a5db738',
|
||||||
|
SHA1='effcdf6ae5eb2fa2d27416d5f184df9c259a7c79'),
|
||||||
|
'RFC 2202 #2 (HMAC-MD5/SHA1)'),
|
||||||
|
|
||||||
|
# Test case 3 (MD5)
|
||||||
|
('aa' * 16,
|
||||||
|
'dd' * 50,
|
||||||
|
dict(MD5='56be34521d144c88dbb8c733f0e8b3f6'),
|
||||||
|
'RFC 2202 #3-MD5 (HMAC-MD5)'),
|
||||||
|
|
||||||
|
# Test case 3 (SHA1)
|
||||||
|
('aa' * 20,
|
||||||
|
'dd' * 50,
|
||||||
|
dict(SHA1='125d7342b9ac11cd91a39af48aa17b4f63f175d3'),
|
||||||
|
'RFC 2202 #3-SHA1 (HMAC-SHA1)'),
|
||||||
|
|
||||||
|
# Test case 4
|
||||||
|
('0102030405060708090a0b0c0d0e0f10111213141516171819',
|
||||||
|
'cd' * 50,
|
||||||
|
dict(MD5='697eaf0aca3a3aea3a75164746ffaa79',
|
||||||
|
SHA1='4c9007f4026250c6bc8414f9bf50c86c2d7235da'),
|
||||||
|
'RFC 2202 #4 (HMAC-MD5/SHA1)'),
|
||||||
|
|
||||||
|
# Test case 5 (MD5)
|
||||||
|
('0c' * 16,
|
||||||
|
'546573742057697468205472756e636174696f6e',
|
||||||
|
dict(MD5='56461ef2342edc00f9bab995690efd4c'),
|
||||||
|
'RFC 2202 #5-MD5 (HMAC-MD5)'),
|
||||||
|
|
||||||
|
# Test case 5 (SHA1)
|
||||||
|
# NB: We do not implement hash truncation, so we only test the full hash here.
|
||||||
|
('0c' * 20,
|
||||||
|
'546573742057697468205472756e636174696f6e',
|
||||||
|
dict(SHA1='4c1a03424b55e07fe7f27be1d58bb9324a9a5a04'),
|
||||||
|
'RFC 2202 #5-SHA1 (HMAC-SHA1)'),
|
||||||
|
|
||||||
|
# Test case 6
|
||||||
|
('aa' * 80,
|
||||||
|
'54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a'
|
||||||
|
+ '65204b6579202d2048617368204b6579204669727374',
|
||||||
|
dict(MD5='6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd',
|
||||||
|
SHA1='aa4ae5e15272d00e95705637ce8a3b55ed402112'),
|
||||||
|
'RFC 2202 #6 (HMAC-MD5/SHA1)'),
|
||||||
|
|
||||||
|
# Test case 7
|
||||||
|
('aa' * 80,
|
||||||
|
'54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a'
|
||||||
|
+ '65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d'
|
||||||
|
+ '53697a652044617461',
|
||||||
|
dict(MD5='6f630fad67cda0ee1fb1f562db3aa53e',
|
||||||
|
SHA1='e8e99d0f45237d786d6bbaa7965c7808bbff1a91'),
|
||||||
|
'RFC 2202 #7 (HMAC-MD5/SHA1)'),
|
||||||
|
|
||||||
|
## Test vectors from RFC 4231 ##
|
||||||
|
# 4.2. Test Case 1
|
||||||
|
('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b',
|
||||||
|
'4869205468657265',
|
||||||
|
dict(SHA256='''
|
||||||
|
b0344c61d8db38535ca8afceaf0bf12b
|
||||||
|
881dc200c9833da726e9376c2e32cff7
|
||||||
|
'''),
|
||||||
|
'RFC 4231 #1 (HMAC-SHA256)'),
|
||||||
|
|
||||||
|
# 4.3. Test Case 2 - Test with a key shorter than the length of the HMAC
|
||||||
|
# output.
|
||||||
|
('4a656665',
|
||||||
|
'7768617420646f2079612077616e7420666f72206e6f7468696e673f',
|
||||||
|
dict(SHA256='''
|
||||||
|
5bdcc146bf60754e6a042426089575c7
|
||||||
|
5a003f089d2739839dec58b964ec3843
|
||||||
|
'''),
|
||||||
|
'RFC 4231 #2 (HMAC-SHA256)'),
|
||||||
|
|
||||||
|
# 4.4. Test Case 3 - Test with a combined length of key and data that is
|
||||||
|
# larger than 64 bytes (= block-size of SHA-224 and SHA-256).
|
||||||
|
('aa' * 20,
|
||||||
|
'dd' * 50,
|
||||||
|
dict(SHA256='''
|
||||||
|
773ea91e36800e46854db8ebd09181a7
|
||||||
|
2959098b3ef8c122d9635514ced565fe
|
||||||
|
'''),
|
||||||
|
'RFC 4231 #3 (HMAC-SHA256)'),
|
||||||
|
|
||||||
|
# 4.5. Test Case 4 - Test with a combined length of key and data that is
|
||||||
|
# larger than 64 bytes (= block-size of SHA-224 and SHA-256).
|
||||||
|
('0102030405060708090a0b0c0d0e0f10111213141516171819',
|
||||||
|
'cd' * 50,
|
||||||
|
dict(SHA256='''
|
||||||
|
82558a389a443c0ea4cc819899f2083a
|
||||||
|
85f0faa3e578f8077a2e3ff46729665b
|
||||||
|
'''),
|
||||||
|
'RFC 4231 #4 (HMAC-SHA256)'),
|
||||||
|
|
||||||
|
# 4.6. Test Case 5 - Test with a truncation of output to 128 bits.
|
||||||
|
#
|
||||||
|
# Not included because we do not implement hash truncation.
|
||||||
|
#
|
||||||
|
|
||||||
|
# 4.7. Test Case 6 - Test with a key larger than 128 bytes (= block-size of
|
||||||
|
# SHA-384 and SHA-512).
|
||||||
|
('aa' * 131,
|
||||||
|
'54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a'
|
||||||
|
+ '65204b6579202d2048617368204b6579204669727374',
|
||||||
|
dict(SHA256='''
|
||||||
|
60e431591ee0b67f0d8a26aacbf5b77f
|
||||||
|
8e0bc6213728c5140546040f0ee37f54
|
||||||
|
'''),
|
||||||
|
'RFC 4231 #6 (HMAC-SHA256)'),
|
||||||
|
|
||||||
|
# 4.8. Test Case 7 - Test with a key and data that is larger than 128 bytes
|
||||||
|
# (= block-size of SHA-384 and SHA-512).
|
||||||
|
('aa' * 131,
|
||||||
|
'5468697320697320612074657374207573696e672061206c6172676572207468'
|
||||||
|
+ '616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074'
|
||||||
|
+ '68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565'
|
||||||
|
+ '647320746f20626520686173686564206265666f7265206265696e6720757365'
|
||||||
|
+ '642062792074686520484d414320616c676f726974686d2e',
|
||||||
|
dict(SHA256='''
|
||||||
|
9b09ffa71b942fcb27635fbcd5b0e944
|
||||||
|
bfdc63644f0713938a7f51535c3a35e2
|
||||||
|
'''),
|
||||||
|
'RFC 4231 #7 (HMAC-SHA256)'),
|
||||||
|
]
|
||||||
|
|
||||||
|
hashlib_test_data = [
|
||||||
|
# Test case 8 (SHA224)
|
||||||
|
('4a656665',
|
||||||
|
'7768617420646f2079612077616e74'
|
||||||
|
+ '20666f72206e6f7468696e673f',
|
||||||
|
dict(SHA224='a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44'),
|
||||||
|
'RFC 4634 8.4 SHA224 (HMAC-SHA224)'),
|
||||||
|
|
||||||
|
# Test case 9 (SHA384)
|
||||||
|
('4a656665',
|
||||||
|
'7768617420646f2079612077616e74'
|
||||||
|
+ '20666f72206e6f7468696e673f',
|
||||||
|
dict(SHA384='af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649'),
|
||||||
|
'RFC 4634 8.4 SHA384 (HMAC-SHA384)'),
|
||||||
|
|
||||||
|
# Test case 10 (SHA512)
|
||||||
|
('4a656665',
|
||||||
|
'7768617420646f2079612077616e74'
|
||||||
|
+ '20666f72206e6f7468696e673f',
|
||||||
|
dict(SHA512='164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'),
|
||||||
|
'RFC 4634 8.4 SHA512 (HMAC-SHA512)'),
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
global test_data
|
||||||
|
from Crypto.Hash import HMAC, MD5, SHA as SHA1, SHA256
|
||||||
|
from .common import make_mac_tests
|
||||||
|
hashmods = dict(MD5=MD5, SHA1=SHA1, SHA256=SHA256, default=None)
|
||||||
|
try:
|
||||||
|
from Crypto.Hash import SHA224, SHA384, SHA512
|
||||||
|
hashmods.update(dict(SHA224=SHA224, SHA384=SHA384, SHA512=SHA512))
|
||||||
|
test_data += hashlib_test_data
|
||||||
|
except ImportError:
|
||||||
|
import sys
|
||||||
|
sys.stderr.write("SelfTest: warning: not testing HMAC-SHA224/384/512 (not available)\n")
|
||||||
|
return make_mac_tests(HMAC, "HMAC", test_data, hashmods)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
64
Lib/site-packages/Crypto/SelfTest/Hash/test_MD2.py
Normal file
64
Lib/site-packages/Crypto/SelfTest/Hash/test_MD2.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/MD2.py: Self-test for the MD2 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Hash.MD2"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
# Test vectors from RFC 1319
|
||||||
|
('8350e5a3e24c153df2275c9f80692773', '', "'' (empty string)"),
|
||||||
|
('32ec01ec4a6dac72c0ab96fb34c0b5d1', 'a'),
|
||||||
|
('da853b0d3f88d99b30283a69e6ded6bb', 'abc'),
|
||||||
|
('ab4f496bfb2a530b219ff33031fe06b0', 'message digest'),
|
||||||
|
|
||||||
|
('4e8ddff3650292ab5a4108c3aa47940b', 'abcdefghijklmnopqrstuvwxyz',
|
||||||
|
'a-z'),
|
||||||
|
|
||||||
|
('da33def2a42df13975352846c30338cd',
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
|
||||||
|
'A-Z, a-z, 0-9'),
|
||||||
|
|
||||||
|
('d5976f79d83d3a0dc9806c3c66f3efd8',
|
||||||
|
'1234567890123456789012345678901234567890123456'
|
||||||
|
+ '7890123456789012345678901234567890',
|
||||||
|
"'1234567890' * 8"),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Hash import MD2
|
||||||
|
from .common import make_hash_tests
|
||||||
|
return make_hash_tests(MD2, "MD2", test_data,
|
||||||
|
digest_size=16,
|
||||||
|
oid="\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
64
Lib/site-packages/Crypto/SelfTest/Hash/test_MD4.py
Normal file
64
Lib/site-packages/Crypto/SelfTest/Hash/test_MD4.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/MD4.py: Self-test for the MD4 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Hash.MD4"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
# Test vectors from RFC 1320
|
||||||
|
('31d6cfe0d16ae931b73c59d7e0c089c0', '', "'' (empty string)"),
|
||||||
|
('bde52cb31de33e46245e05fbdbd6fb24', 'a'),
|
||||||
|
('a448017aaf21d8525fc10ae87aa6729d', 'abc'),
|
||||||
|
('d9130a8164549fe818874806e1c7014b', 'message digest'),
|
||||||
|
|
||||||
|
('d79e1c308aa5bbcdeea8ed63df412da9', 'abcdefghijklmnopqrstuvwxyz',
|
||||||
|
'a-z'),
|
||||||
|
|
||||||
|
('043f8582f241db351ce627e153e7f0e4',
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
|
||||||
|
'A-Z, a-z, 0-9'),
|
||||||
|
|
||||||
|
('e33b4ddc9c38f2199c3e7b164fcc0536',
|
||||||
|
'1234567890123456789012345678901234567890123456'
|
||||||
|
+ '7890123456789012345678901234567890',
|
||||||
|
"'1234567890' * 8"),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Hash import MD4
|
||||||
|
from .common import make_hash_tests
|
||||||
|
return make_hash_tests(MD4, "MD4", test_data,
|
||||||
|
digest_size=16,
|
||||||
|
oid="\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
64
Lib/site-packages/Crypto/SelfTest/Hash/test_MD5.py
Normal file
64
Lib/site-packages/Crypto/SelfTest/Hash/test_MD5.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/MD5.py: Self-test for the MD5 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Hash.MD5"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
# Test vectors from RFC 1321
|
||||||
|
('d41d8cd98f00b204e9800998ecf8427e', '', "'' (empty string)"),
|
||||||
|
('0cc175b9c0f1b6a831c399e269772661', 'a'),
|
||||||
|
('900150983cd24fb0d6963f7d28e17f72', 'abc'),
|
||||||
|
('f96b697d7cb7938d525a2f31aaf161d0', 'message digest'),
|
||||||
|
|
||||||
|
('c3fcd3d76192e4007dfb496cca67e13b', 'abcdefghijklmnopqrstuvwxyz',
|
||||||
|
'a-z'),
|
||||||
|
|
||||||
|
('d174ab98d277d9f5a5611c2c9f419d9f',
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
|
||||||
|
'A-Z, a-z, 0-9'),
|
||||||
|
|
||||||
|
('57edf4a22be3c955ac49da2e2107b67a',
|
||||||
|
'1234567890123456789012345678901234567890123456'
|
||||||
|
+ '7890123456789012345678901234567890',
|
||||||
|
"'1234567890' * 8"),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Hash import MD5
|
||||||
|
from .common import make_hash_tests
|
||||||
|
return make_hash_tests(MD5, "MD5", test_data,
|
||||||
|
digest_size=16,
|
||||||
|
oid="\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
73
Lib/site-packages/Crypto/SelfTest/Hash/test_RIPEMD.py
Normal file
73
Lib/site-packages/Crypto/SelfTest/Hash/test_RIPEMD.py
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/test_RIPEMD.py: Self-test for the RIPEMD-160 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
#"""Self-test suite for Crypto.Hash.RIPEMD"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
# Test vectors downloaded 2008-09-12 from
|
||||||
|
# http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
|
||||||
|
('9c1185a5c5e9fc54612808977ee8f548b2258d31', '', "'' (empty string)"),
|
||||||
|
('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe', 'a'),
|
||||||
|
('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc', 'abc'),
|
||||||
|
('5d0689ef49d2fae572b881b123a85ffa21595f36', 'message digest'),
|
||||||
|
|
||||||
|
('f71c27109c692c1b56bbdceb5b9d2865b3708dbc',
|
||||||
|
'abcdefghijklmnopqrstuvwxyz',
|
||||||
|
'a-z'),
|
||||||
|
|
||||||
|
('12a053384a9c0c88e405a06c27dcf49ada62eb2b',
|
||||||
|
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
|
||||||
|
'abcdbcd...pnopq'),
|
||||||
|
|
||||||
|
('b0e20b6e3116640286ed3a87a5713079b21f5189',
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
|
||||||
|
'A-Z, a-z, 0-9'),
|
||||||
|
|
||||||
|
('9b752e45573d4b39f4dbd3323cab82bf63326bfb',
|
||||||
|
'1234567890' * 8,
|
||||||
|
"'1234567890' * 8"),
|
||||||
|
|
||||||
|
('52783243c1697bdbe16d37f97f68f08325dc1528',
|
||||||
|
'a' * 10**6,
|
||||||
|
'"a" * 10**6'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Hash import RIPEMD
|
||||||
|
from .common import make_hash_tests
|
||||||
|
return make_hash_tests(RIPEMD, "RIPEMD", test_data,
|
||||||
|
digest_size=20,
|
||||||
|
oid="\x06\x05\x2b\x24\x03\02\x01")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
64
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA.py
Normal file
64
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/SHA.py: Self-test for the SHA-1 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Hash.SHA"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# Test vectors from various sources
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
# FIPS PUB 180-2, A.1 - "One-Block Message"
|
||||||
|
('a9993e364706816aba3e25717850c26c9cd0d89d', 'abc'),
|
||||||
|
|
||||||
|
# FIPS PUB 180-2, A.2 - "Multi-Block Message"
|
||||||
|
('84983e441c3bd26ebaae4aa1f95129e5e54670f1',
|
||||||
|
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'),
|
||||||
|
|
||||||
|
# FIPS PUB 180-2, A.3 - "Long Message"
|
||||||
|
# ('34aa973cd4c4daa4f61eeb2bdbad27316534016f',
|
||||||
|
# 'a' * 10**6,
|
||||||
|
# '"a" * 10**6'),
|
||||||
|
|
||||||
|
# RFC 3174: Section 7.3, "TEST4" (multiple of 512 bits)
|
||||||
|
('dea356a2cddd90c7a7ecedc5ebb563934f460452',
|
||||||
|
'01234567' * 80,
|
||||||
|
'"01234567" * 80'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Hash import SHA
|
||||||
|
from .common import make_hash_tests
|
||||||
|
return make_hash_tests(SHA, "SHA", test_data,
|
||||||
|
digest_size=20,
|
||||||
|
oid="\x06\x05\x2B\x0E\x03\x02\x1A")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
65
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA224.py
Normal file
65
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA224.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/test_SHA224.py: Self-test for the SHA-224 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Hash.SHA224"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
# Test vectors from various sources
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
|
||||||
|
# RFC 3874: Section 3.1, "Test Vector #1
|
||||||
|
('23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7', 'abc'),
|
||||||
|
|
||||||
|
# RFC 3874: Section 3.2, "Test Vector #2
|
||||||
|
('75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'),
|
||||||
|
|
||||||
|
# RFC 3874: Section 3.3, "Test Vector #3
|
||||||
|
('20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67', 'a' * 10**6, "'a' * 10**6"),
|
||||||
|
|
||||||
|
# Examples from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
|
||||||
|
('d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f', ''),
|
||||||
|
|
||||||
|
('49b08defa65e644cbf8a2dd9270bdededabc741997d1dadd42026d7b',
|
||||||
|
'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'),
|
||||||
|
|
||||||
|
('58911e7fccf2971a7d07f93162d8bd13568e71aa8fc86fc1fe9043d1',
|
||||||
|
'Frank jagt im komplett verwahrlosten Taxi quer durch Bayern'),
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Hash import SHA224
|
||||||
|
from .common import make_hash_tests
|
||||||
|
return make_hash_tests(SHA224, "SHA224", test_data,
|
||||||
|
digest_size=28,
|
||||||
|
oid='\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
96
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA256.py
Normal file
96
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA256.py
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/test_SHA256.py: Self-test for the SHA-256 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Hash.SHA256"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
class LargeSHA256Test(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
"""SHA256: 512/520 MiB test"""
|
||||||
|
from Crypto.Hash import SHA256
|
||||||
|
zeros = bchr(0x00) * (1024*1024)
|
||||||
|
|
||||||
|
h = SHA256.new(zeros)
|
||||||
|
for i in range(511):
|
||||||
|
h.update(zeros)
|
||||||
|
|
||||||
|
# This test vector is from PyCrypto's old testdata.py file.
|
||||||
|
self.assertEqual('9acca8e8c22201155389f65abbf6bc9723edc7384ead80503839f49dcc56d767', h.hexdigest()) # 512 MiB
|
||||||
|
|
||||||
|
for i in range(8):
|
||||||
|
h.update(zeros)
|
||||||
|
|
||||||
|
# This test vector is from PyCrypto's old testdata.py file.
|
||||||
|
self.assertEqual('abf51ad954b246009dfe5a50ecd582fd5b8f1b8b27f30393853c3ef721e7fa6e', h.hexdigest()) # 520 MiB
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
# Test vectors from FIPS PUB 180-2
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
# FIPS PUB 180-2, B.1 - "One-Block Message"
|
||||||
|
('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad',
|
||||||
|
'abc'),
|
||||||
|
|
||||||
|
# FIPS PUB 180-2, B.2 - "Multi-Block Message"
|
||||||
|
('248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1',
|
||||||
|
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'),
|
||||||
|
|
||||||
|
# FIPS PUB 180-2, B.3 - "Long Message"
|
||||||
|
('cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0',
|
||||||
|
'a' * 10**6,
|
||||||
|
'"a" * 10**6'),
|
||||||
|
|
||||||
|
# Test for an old PyCrypto bug.
|
||||||
|
('f7fd017a3c721ce7ff03f3552c0813adcc48b7f33f07e5e2ba71e23ea393d103',
|
||||||
|
'This message is precisely 55 bytes long, to test a bug.',
|
||||||
|
'Length = 55 (mod 64)'),
|
||||||
|
|
||||||
|
# Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
|
||||||
|
('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', ''),
|
||||||
|
|
||||||
|
('d32b568cd1b96d459e7291ebf4b25d007f275c9f13149beeb782fac0716613f8',
|
||||||
|
'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'),
|
||||||
|
]
|
||||||
|
|
||||||
|
from Crypto.Hash import SHA256
|
||||||
|
from .common import make_hash_tests
|
||||||
|
tests = make_hash_tests(SHA256, "SHA256", test_data,
|
||||||
|
digest_size=32,
|
||||||
|
oid="\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01")
|
||||||
|
|
||||||
|
if config.get('slow_tests'):
|
||||||
|
tests += [LargeSHA256Test()]
|
||||||
|
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
63
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA384.py
Normal file
63
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA384.py
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/test_SHA.py: Self-test for the SHA-384 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Hash.SHA384"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
# Test vectors from various sources
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
|
||||||
|
# RFC 4634: Section Page 8.4, "Test 1"
|
||||||
|
('cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7', 'abc'),
|
||||||
|
|
||||||
|
# RFC 4634: Section Page 8.4, "Test 2.2"
|
||||||
|
('09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'),
|
||||||
|
|
||||||
|
# RFC 4634: Section Page 8.4, "Test 3"
|
||||||
|
('9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985', 'a' * 10**6, "'a' * 10**6"),
|
||||||
|
|
||||||
|
# Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
|
||||||
|
('38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b', ''),
|
||||||
|
|
||||||
|
# Example from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
|
||||||
|
('71e8383a4cea32d6fd6877495db2ee353542f46fa44bc23100bca48f3366b84e809f0708e81041f427c6d5219a286677',
|
||||||
|
'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'),
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Hash import SHA384
|
||||||
|
from .common import make_hash_tests
|
||||||
|
return make_hash_tests(SHA384, "SHA384", test_data,
|
||||||
|
digest_size=48,
|
||||||
|
oid='\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
60
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA512.py
Normal file
60
Lib/site-packages/Crypto/SelfTest/Hash/test_SHA512.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Hash/test_SHA512.py: Self-test for the SHA-512 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Hash.SHA512"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
# Test vectors from various sources
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
|
||||||
|
# RFC 4634: Section Page 8.4, "Test 1"
|
||||||
|
('ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', 'abc'),
|
||||||
|
|
||||||
|
# RFC 4634: Section Page 8.4, "Test 2.1"
|
||||||
|
('8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'),
|
||||||
|
|
||||||
|
# RFC 4634: Section Page 8.4, "Test 3"
|
||||||
|
('e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b', 'a' * 10**6, "'a' * 10**6"),
|
||||||
|
|
||||||
|
# Taken from http://de.wikipedia.org/wiki/Secure_Hash_Algorithm
|
||||||
|
('cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', ''),
|
||||||
|
|
||||||
|
('af9ed2de700433b803240a552b41b5a472a6ef3fe1431a722b2063c75e9f07451f67a28e37d09cde769424c96aea6f8971389db9e1993d6c565c3c71b855723c', 'Franz jagt im komplett verwahrlosten Taxi quer durch Bayern'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Hash import SHA512
|
||||||
|
from .common import make_hash_tests
|
||||||
|
return make_hash_tests(SHA512, "SHA512", test_data,
|
||||||
|
digest_size=64,
|
||||||
|
oid="\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
41
Lib/site-packages/Crypto/SelfTest/Protocol/__init__.py
Normal file
41
Lib/site-packages/Crypto/SelfTest/Protocol/__init__.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Protocol/__init__.py: Self-tests for Crypto.Protocol
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test for Crypto.Protocol"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
from Crypto.SelfTest.Protocol import test_chaffing; tests += test_chaffing.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Protocol import test_rfc1751; tests += test_rfc1751.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Protocol import test_AllOrNothing; tests += test_AllOrNothing.get_tests(config=config)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
|
@ -0,0 +1,76 @@
|
||||||
|
#
|
||||||
|
# Test script for Crypto.Protocol.AllOrNothing
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# Written by Andrew Kuchling and others
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from Crypto.Protocol import AllOrNothing
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
text = b("""\
|
||||||
|
When in the Course of human events, it becomes necessary for one people to
|
||||||
|
dissolve the political bands which have connected them with another, and to
|
||||||
|
assume among the powers of the earth, the separate and equal station to which
|
||||||
|
the Laws of Nature and of Nature's God entitle them, a decent respect to the
|
||||||
|
opinions of mankind requires that they should declare the causes which impel
|
||||||
|
them to the separation.
|
||||||
|
|
||||||
|
We hold these truths to be self-evident, that all men are created equal, that
|
||||||
|
they are endowed by their Creator with certain unalienable Rights, that among
|
||||||
|
these are Life, Liberty, and the pursuit of Happiness. That to secure these
|
||||||
|
rights, Governments are instituted among Men, deriving their just powers from
|
||||||
|
the consent of the governed. That whenever any Form of Government becomes
|
||||||
|
destructive of these ends, it is the Right of the People to alter or to
|
||||||
|
abolish it, and to institute new Government, laying its foundation on such
|
||||||
|
principles and organizing its powers in such form, as to them shall seem most
|
||||||
|
likely to effect their Safety and Happiness.
|
||||||
|
""")
|
||||||
|
|
||||||
|
class AllOrNothingTest (unittest.TestCase):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
"Simple test of AllOrNothing"
|
||||||
|
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
import base64
|
||||||
|
|
||||||
|
# The current AllOrNothing will fail
|
||||||
|
# every so often. Repeat the test
|
||||||
|
# several times to force this.
|
||||||
|
for i in range(50):
|
||||||
|
x = AllOrNothing.AllOrNothing(AES)
|
||||||
|
|
||||||
|
msgblocks = x.digest(text)
|
||||||
|
|
||||||
|
# get a new undigest-only object so there's no leakage
|
||||||
|
y = AllOrNothing.AllOrNothing(AES)
|
||||||
|
text2 = y.undigest(msgblocks)
|
||||||
|
self.assertEqual(text, text2)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [AllOrNothingTest()]
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
98
Lib/site-packages/Crypto/SelfTest/Protocol/test_KDF.py
Normal file
98
Lib/site-packages/Crypto/SelfTest/Protocol/test_KDF.py
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Protocol/test_KDF.py: Self-test for key derivation functions
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from binascii import unhexlify
|
||||||
|
|
||||||
|
from Crypto.SelfTest.st_common import list_test_cases
|
||||||
|
from Crypto.Hash import SHA as SHA1,HMAC
|
||||||
|
|
||||||
|
from Crypto.Protocol.KDF import *
|
||||||
|
|
||||||
|
def t2b(t): return unhexlify(b(t))
|
||||||
|
|
||||||
|
class PBKDF1_Tests(unittest.TestCase):
|
||||||
|
|
||||||
|
# List of tuples with test data.
|
||||||
|
# Each tuple is made up by:
|
||||||
|
# Item #0: a pass phrase
|
||||||
|
# Item #1: salt (8 bytes encoded in hex)
|
||||||
|
# Item #2: output key length
|
||||||
|
# Item #3: iterations to use
|
||||||
|
# Item #4: expected result (encoded in hex)
|
||||||
|
_testData = (
|
||||||
|
# From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf
|
||||||
|
("password","78578E5A5D63CB06",16,1000,"DC19847E05C64D2FAF10EBFB4A3D2A20"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test1(self):
|
||||||
|
v = self._testData[0]
|
||||||
|
res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1)
|
||||||
|
self.assertEqual(res, t2b(v[4]))
|
||||||
|
|
||||||
|
class PBKDF2_Tests(unittest.TestCase):
|
||||||
|
|
||||||
|
# List of tuples with test data.
|
||||||
|
# Each tuple is made up by:
|
||||||
|
# Item #0: a pass phrase
|
||||||
|
# Item #1: salt (encoded in hex)
|
||||||
|
# Item #2: output key length
|
||||||
|
# Item #3: iterations to use
|
||||||
|
# Item #4: expected result (encoded in hex)
|
||||||
|
_testData = (
|
||||||
|
# From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf
|
||||||
|
("password","78578E5A5D63CB06",24,2048,"BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"),
|
||||||
|
# From RFC 6050
|
||||||
|
("password","73616c74", 20, 1, "0c60c80f961f0e71f3a9b524af6012062fe037a6"),
|
||||||
|
("password","73616c74", 20, 2, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"),
|
||||||
|
("password","73616c74", 20, 4096, "4b007901b765489abead49d926f721d065a429c1"),
|
||||||
|
("passwordPASSWORDpassword","73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74",
|
||||||
|
25, 4096, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"),
|
||||||
|
( 'pass\x00word',"7361006c74",16,4096, "56fa6aa75548099dcc37d7f03425e0c3"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test1(self):
|
||||||
|
# Test only for HMAC-SHA1 as PRF
|
||||||
|
|
||||||
|
def prf(p,s):
|
||||||
|
return HMAC.new(p,s,SHA1).digest()
|
||||||
|
|
||||||
|
for i in range(len(self._testData)):
|
||||||
|
v = self._testData[i]
|
||||||
|
res = PBKDF2(v[0], t2b(v[1]), v[2], v[3])
|
||||||
|
res2 = PBKDF2(v[0], t2b(v[1]), v[2], v[3], prf)
|
||||||
|
self.assertEqual(res, t2b(v[4]))
|
||||||
|
self.assertEqual(res, res2)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
tests += list_test_cases(PBKDF1_Tests)
|
||||||
|
tests += list_test_cases(PBKDF2_Tests)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4
|
74
Lib/site-packages/Crypto/SelfTest/Protocol/test_chaffing.py
Normal file
74
Lib/site-packages/Crypto/SelfTest/Protocol/test_chaffing.py
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#
|
||||||
|
# Test script for Crypto.Protocol.Chaffing
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# Written by Andrew Kuchling and others
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from Crypto.Protocol import Chaffing
|
||||||
|
|
||||||
|
text = """\
|
||||||
|
When in the Course of human events, it becomes necessary for one people to
|
||||||
|
dissolve the political bands which have connected them with another, and to
|
||||||
|
assume among the powers of the earth, the separate and equal station to which
|
||||||
|
the Laws of Nature and of Nature's God entitle them, a decent respect to the
|
||||||
|
opinions of mankind requires that they should declare the causes which impel
|
||||||
|
them to the separation.
|
||||||
|
|
||||||
|
We hold these truths to be self-evident, that all men are created equal, that
|
||||||
|
they are endowed by their Creator with certain unalienable Rights, that among
|
||||||
|
these are Life, Liberty, and the pursuit of Happiness. That to secure these
|
||||||
|
rights, Governments are instituted among Men, deriving their just powers from
|
||||||
|
the consent of the governed. That whenever any Form of Government becomes
|
||||||
|
destructive of these ends, it is the Right of the People to alter or to
|
||||||
|
abolish it, and to institute new Government, laying its foundation on such
|
||||||
|
principles and organizing its powers in such form, as to them shall seem most
|
||||||
|
likely to effect their Safety and Happiness.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class ChaffingTest (unittest.TestCase):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
"Simple tests of chaffing and winnowing"
|
||||||
|
# Test constructors
|
||||||
|
Chaffing.Chaff()
|
||||||
|
Chaffing.Chaff(0.5, 1)
|
||||||
|
self.assertRaises(ValueError, Chaffing.Chaff, factor=-1)
|
||||||
|
self.assertRaises(ValueError, Chaffing.Chaff, blocksper=-1)
|
||||||
|
|
||||||
|
data = [(1, 'data1', 'data1'), (2, 'data2', 'data2')]
|
||||||
|
c = Chaffing.Chaff(1.0, 1)
|
||||||
|
c.chaff(data)
|
||||||
|
chaff = c.chaff(data)
|
||||||
|
self.assertEqual(len(chaff), 4)
|
||||||
|
|
||||||
|
c = Chaffing.Chaff(0.0, 1)
|
||||||
|
chaff = c.chaff(data)
|
||||||
|
self.assertEqual(len(chaff), 2)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [ChaffingTest()]
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
62
Lib/site-packages/Crypto/SelfTest/Protocol/test_rfc1751.py
Normal file
62
Lib/site-packages/Crypto/SelfTest/Protocol/test_rfc1751.py
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#
|
||||||
|
# Test script for Crypto.Util.RFC1751.
|
||||||
|
#
|
||||||
|
# Part of the Python Cryptography Toolkit
|
||||||
|
#
|
||||||
|
# Written by Andrew Kuchling and others
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import binascii
|
||||||
|
import unittest
|
||||||
|
from Crypto.Util import RFC1751
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
test_data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'),
|
||||||
|
('CCAC2AED591056BE4F90FD441C534766',
|
||||||
|
'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'),
|
||||||
|
('EFF81F9BFBC65350920CDD7416DE8009',
|
||||||
|
'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL')
|
||||||
|
]
|
||||||
|
|
||||||
|
class RFC1751Test_k2e (unittest.TestCase):
|
||||||
|
|
||||||
|
def runTest (self):
|
||||||
|
"Check converting keys to English"
|
||||||
|
for key, words in test_data:
|
||||||
|
key=binascii.a2b_hex(b(key))
|
||||||
|
self.assertEqual(RFC1751.key_to_english(key), words)
|
||||||
|
|
||||||
|
class RFC1751Test_e2k (unittest.TestCase):
|
||||||
|
|
||||||
|
def runTest (self):
|
||||||
|
"Check converting English strings to keys"
|
||||||
|
for key, words in test_data:
|
||||||
|
key=binascii.a2b_hex(b(key))
|
||||||
|
self.assertEqual(RFC1751.english_to_key(words), key)
|
||||||
|
|
||||||
|
# class RFC1751Test
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [RFC1751Test_k2e(), RFC1751Test_e2k()]
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
44
Lib/site-packages/Crypto/SelfTest/PublicKey/__init__.py
Normal file
44
Lib/site-packages/Crypto/SelfTest/PublicKey/__init__.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/PublicKey/__init__.py: Self-test for public key crypto
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test for public-key crypto"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
from Crypto.SelfTest.PublicKey import test_DSA; tests += test_DSA.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.PublicKey import test_RSA; tests += test_RSA.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.PublicKey import test_importKey; tests += test_importKey.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.PublicKey import test_ElGamal; tests += test_ElGamal.get_tests(config=config)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
244
Lib/site-packages/Crypto/SelfTest/PublicKey/test_DSA.py
Normal file
244
Lib/site-packages/Crypto/SelfTest/PublicKey/test_DSA.py
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/PublicKey/test_DSA.py: Self-test for the DSA primitive
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.PublicKey.DSA"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
|
||||||
|
|
||||||
|
def _sws(s):
|
||||||
|
"""Remove whitespace from a text or byte string"""
|
||||||
|
if isinstance(s,str):
|
||||||
|
return "".join(s.split())
|
||||||
|
else:
|
||||||
|
return b("").join(s.split())
|
||||||
|
|
||||||
|
class DSATest(unittest.TestCase):
|
||||||
|
# Test vector from "Appendix 5. Example of the DSA" of
|
||||||
|
# "Digital Signature Standard (DSS)",
|
||||||
|
# U.S. Department of Commerce/National Institute of Standards and Technology
|
||||||
|
# FIPS 186-2 (+Change Notice), 2000 January 27.
|
||||||
|
# http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf
|
||||||
|
|
||||||
|
y = _sws("""19131871 d75b1612 a819f29d 78d1b0d7 346f7aa7 7bb62a85
|
||||||
|
9bfd6c56 75da9d21 2d3a36ef 1672ef66 0b8c7c25 5cc0ec74
|
||||||
|
858fba33 f44c0669 9630a76b 030ee333""")
|
||||||
|
|
||||||
|
g = _sws("""626d0278 39ea0a13 413163a5 5b4cb500 299d5522 956cefcb
|
||||||
|
3bff10f3 99ce2c2e 71cb9de5 fa24babf 58e5b795 21925c9c
|
||||||
|
c42e9f6f 464b088c c572af53 e6d78802""")
|
||||||
|
|
||||||
|
p = _sws("""8df2a494 492276aa 3d25759b b06869cb eac0d83a fb8d0cf7
|
||||||
|
cbb8324f 0d7882e5 d0762fc5 b7210eaf c2e9adac 32ab7aac
|
||||||
|
49693dfb f83724c2 ec0736ee 31c80291""")
|
||||||
|
|
||||||
|
q = _sws("""c773218c 737ec8ee 993b4f2d ed30f48e dace915f""")
|
||||||
|
|
||||||
|
x = _sws("""2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614""")
|
||||||
|
|
||||||
|
k = _sws("""358dad57 1462710f 50e254cf 1a376b2b deaadfbf""")
|
||||||
|
k_inverse = _sws("""0d516729 8202e49b 4116ac10 4fc3f415 ae52f917""")
|
||||||
|
m = b2a_hex(b("abc"))
|
||||||
|
m_hash = _sws("""a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d""")
|
||||||
|
r = _sws("""8bac1ab6 6410435c b7181f95 b16ab97c 92b341c0""")
|
||||||
|
s = _sws("""41e2345f 1f56df24 58f426d1 55b4ba2d b6dcd8c8""")
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
global DSA, Random, bytes_to_long, size
|
||||||
|
from Crypto.PublicKey import DSA
|
||||||
|
from Crypto import Random
|
||||||
|
from Crypto.Util.number import bytes_to_long, inverse, size
|
||||||
|
|
||||||
|
self.dsa = DSA
|
||||||
|
|
||||||
|
def test_generate_1arg(self):
|
||||||
|
"""DSA (default implementation) generated key (1 argument)"""
|
||||||
|
dsaObj = self.dsa.generate(1024)
|
||||||
|
self._check_private_key(dsaObj)
|
||||||
|
pub = dsaObj.publickey()
|
||||||
|
self._check_public_key(pub)
|
||||||
|
|
||||||
|
def test_generate_2arg(self):
|
||||||
|
"""DSA (default implementation) generated key (2 arguments)"""
|
||||||
|
dsaObj = self.dsa.generate(1024, Random.new().read)
|
||||||
|
self._check_private_key(dsaObj)
|
||||||
|
pub = dsaObj.publickey()
|
||||||
|
self._check_public_key(pub)
|
||||||
|
|
||||||
|
def test_construct_4tuple(self):
|
||||||
|
"""DSA (default implementation) constructed key (4-tuple)"""
|
||||||
|
(y, g, p, q) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q)]
|
||||||
|
dsaObj = self.dsa.construct((y, g, p, q))
|
||||||
|
self._test_verification(dsaObj)
|
||||||
|
|
||||||
|
def test_construct_5tuple(self):
|
||||||
|
"""DSA (default implementation) constructed key (5-tuple)"""
|
||||||
|
(y, g, p, q, x) = [bytes_to_long(a2b_hex(param)) for param in (self.y, self.g, self.p, self.q, self.x)]
|
||||||
|
dsaObj = self.dsa.construct((y, g, p, q, x))
|
||||||
|
self._test_signing(dsaObj)
|
||||||
|
self._test_verification(dsaObj)
|
||||||
|
|
||||||
|
def _check_private_key(self, dsaObj):
|
||||||
|
# Check capabilities
|
||||||
|
self.assertEqual(1, dsaObj.has_private())
|
||||||
|
self.assertEqual(1, dsaObj.can_sign())
|
||||||
|
self.assertEqual(0, dsaObj.can_encrypt())
|
||||||
|
self.assertEqual(0, dsaObj.can_blind())
|
||||||
|
|
||||||
|
# Check dsaObj.[ygpqx] -> dsaObj.key.[ygpqx] mapping
|
||||||
|
self.assertEqual(dsaObj.y, dsaObj.key.y)
|
||||||
|
self.assertEqual(dsaObj.g, dsaObj.key.g)
|
||||||
|
self.assertEqual(dsaObj.p, dsaObj.key.p)
|
||||||
|
self.assertEqual(dsaObj.q, dsaObj.key.q)
|
||||||
|
self.assertEqual(dsaObj.x, dsaObj.key.x)
|
||||||
|
|
||||||
|
# Sanity check key data
|
||||||
|
self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q
|
||||||
|
self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits
|
||||||
|
self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1
|
||||||
|
self.assertEqual(dsaObj.y, pow(dsaObj.g, dsaObj.x, dsaObj.p)) # y == g**x mod p
|
||||||
|
self.assertEqual(1, 0 < dsaObj.x < dsaObj.q) # 0 < x < q
|
||||||
|
|
||||||
|
def _check_public_key(self, dsaObj):
|
||||||
|
k = a2b_hex(self.k)
|
||||||
|
m_hash = a2b_hex(self.m_hash)
|
||||||
|
|
||||||
|
# Check capabilities
|
||||||
|
self.assertEqual(0, dsaObj.has_private())
|
||||||
|
self.assertEqual(1, dsaObj.can_sign())
|
||||||
|
self.assertEqual(0, dsaObj.can_encrypt())
|
||||||
|
self.assertEqual(0, dsaObj.can_blind())
|
||||||
|
|
||||||
|
# Check dsaObj.[ygpq] -> dsaObj.key.[ygpq] mapping
|
||||||
|
self.assertEqual(dsaObj.y, dsaObj.key.y)
|
||||||
|
self.assertEqual(dsaObj.g, dsaObj.key.g)
|
||||||
|
self.assertEqual(dsaObj.p, dsaObj.key.p)
|
||||||
|
self.assertEqual(dsaObj.q, dsaObj.key.q)
|
||||||
|
|
||||||
|
# Check that private parameters are all missing
|
||||||
|
self.assertEqual(0, hasattr(dsaObj, 'x'))
|
||||||
|
self.assertEqual(0, hasattr(dsaObj.key, 'x'))
|
||||||
|
|
||||||
|
# Sanity check key data
|
||||||
|
self.assertEqual(1, dsaObj.p > dsaObj.q) # p > q
|
||||||
|
self.assertEqual(160, size(dsaObj.q)) # size(q) == 160 bits
|
||||||
|
self.assertEqual(0, (dsaObj.p - 1) % dsaObj.q) # q is a divisor of p-1
|
||||||
|
|
||||||
|
# Public-only key objects should raise an error when .sign() is called
|
||||||
|
self.assertRaises(TypeError, dsaObj.sign, m_hash, k)
|
||||||
|
|
||||||
|
# Check __eq__ and __ne__
|
||||||
|
self.assertEqual(dsaObj.publickey() == dsaObj.publickey(),True) # assert_
|
||||||
|
self.assertEqual(dsaObj.publickey() != dsaObj.publickey(),False) # failIf
|
||||||
|
|
||||||
|
def _test_signing(self, dsaObj):
|
||||||
|
k = a2b_hex(self.k)
|
||||||
|
m_hash = a2b_hex(self.m_hash)
|
||||||
|
r = bytes_to_long(a2b_hex(self.r))
|
||||||
|
s = bytes_to_long(a2b_hex(self.s))
|
||||||
|
(r_out, s_out) = dsaObj.sign(m_hash, k)
|
||||||
|
self.assertEqual((r, s), (r_out, s_out))
|
||||||
|
|
||||||
|
def _test_verification(self, dsaObj):
|
||||||
|
m_hash = a2b_hex(self.m_hash)
|
||||||
|
r = bytes_to_long(a2b_hex(self.r))
|
||||||
|
s = bytes_to_long(a2b_hex(self.s))
|
||||||
|
self.assertEqual(1, dsaObj.verify(m_hash, (r, s)))
|
||||||
|
self.assertEqual(0, dsaObj.verify(m_hash + b("\0"), (r, s)))
|
||||||
|
|
||||||
|
class DSAFastMathTest(DSATest):
|
||||||
|
def setUp(self):
|
||||||
|
DSATest.setUp(self)
|
||||||
|
self.dsa = DSA.DSAImplementation(use_fast_math=True)
|
||||||
|
|
||||||
|
def test_generate_1arg(self):
|
||||||
|
"""DSA (_fastmath implementation) generated key (1 argument)"""
|
||||||
|
DSATest.test_generate_1arg(self)
|
||||||
|
|
||||||
|
def test_generate_2arg(self):
|
||||||
|
"""DSA (_fastmath implementation) generated key (2 arguments)"""
|
||||||
|
DSATest.test_generate_2arg(self)
|
||||||
|
|
||||||
|
def test_construct_4tuple(self):
|
||||||
|
"""DSA (_fastmath implementation) constructed key (4-tuple)"""
|
||||||
|
DSATest.test_construct_4tuple(self)
|
||||||
|
|
||||||
|
def test_construct_5tuple(self):
|
||||||
|
"""DSA (_fastmath implementation) constructed key (5-tuple)"""
|
||||||
|
DSATest.test_construct_5tuple(self)
|
||||||
|
|
||||||
|
class DSASlowMathTest(DSATest):
|
||||||
|
def setUp(self):
|
||||||
|
DSATest.setUp(self)
|
||||||
|
self.dsa = DSA.DSAImplementation(use_fast_math=False)
|
||||||
|
|
||||||
|
def test_generate_1arg(self):
|
||||||
|
"""DSA (_slowmath implementation) generated key (1 argument)"""
|
||||||
|
DSATest.test_generate_1arg(self)
|
||||||
|
|
||||||
|
def test_generate_2arg(self):
|
||||||
|
"""DSA (_slowmath implementation) generated key (2 arguments)"""
|
||||||
|
DSATest.test_generate_2arg(self)
|
||||||
|
|
||||||
|
def test_construct_4tuple(self):
|
||||||
|
"""DSA (_slowmath implementation) constructed key (4-tuple)"""
|
||||||
|
DSATest.test_construct_4tuple(self)
|
||||||
|
|
||||||
|
def test_construct_5tuple(self):
|
||||||
|
"""DSA (_slowmath implementation) constructed key (5-tuple)"""
|
||||||
|
DSATest.test_construct_5tuple(self)
|
||||||
|
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
tests += list_test_cases(DSATest)
|
||||||
|
try:
|
||||||
|
from Crypto.PublicKey import _fastmath
|
||||||
|
tests += list_test_cases(DSAFastMathTest)
|
||||||
|
except ImportError:
|
||||||
|
from distutils.sysconfig import get_config_var
|
||||||
|
import inspect
|
||||||
|
_fm_path = os.path.normpath(os.path.dirname(os.path.abspath(
|
||||||
|
inspect.getfile(inspect.currentframe())))
|
||||||
|
+"/../../PublicKey/_fastmath"+get_config_var("SO"))
|
||||||
|
if os.path.exists(_fm_path):
|
||||||
|
raise ImportError("While the _fastmath module exists, importing "+
|
||||||
|
"it failed. This may point to the gmp or mpir shared library "+
|
||||||
|
"not being in the path. _fastmath was found at "+_fm_path)
|
||||||
|
tests += list_test_cases(DSASlowMathTest)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
210
Lib/site-packages/Crypto/SelfTest/PublicKey/test_ElGamal.py
Normal file
210
Lib/site-packages/Crypto/SelfTest/PublicKey/test_ElGamal.py
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/PublicKey/test_ElGamal.py: Self-test for the ElGamal primitive
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.PublicKey.ElGamal"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
|
||||||
|
from Crypto import Random
|
||||||
|
from Crypto.PublicKey import ElGamal
|
||||||
|
from Crypto.Util.number import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
class ElGamalTest(unittest.TestCase):
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test vectors
|
||||||
|
#
|
||||||
|
# There seem to be no real ElGamal test vectors available in the
|
||||||
|
# public domain. The following test vectors have been generated
|
||||||
|
# with libgcrypt 1.5.0.
|
||||||
|
#
|
||||||
|
# Encryption
|
||||||
|
tve=[
|
||||||
|
{
|
||||||
|
# 256 bits
|
||||||
|
'p' :'BA4CAEAAED8CBE952AFD2126C63EB3B345D65C2A0A73D2A3AD4138B6D09BD933',
|
||||||
|
'g' :'05',
|
||||||
|
'y' :'60D063600ECED7C7C55146020E7A31C4476E9793BEAED420FEC9E77604CAE4EF',
|
||||||
|
'x' :'1D391BA2EE3C37FE1BA175A69B2C73A11238AD77675932',
|
||||||
|
'k' :'F5893C5BAB4131264066F57AB3D8AD89E391A0B68A68A1',
|
||||||
|
'pt' :'48656C6C6F207468657265',
|
||||||
|
'ct1':'32BFD5F487966CEA9E9356715788C491EC515E4ED48B58F0F00971E93AAA5EC7',
|
||||||
|
'ct2':'7BE8FBFF317C93E82FCEF9BD515284BA506603FEA25D01C0CB874A31F315EE68'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
# 512 bits
|
||||||
|
'p' :'F1B18AE9F7B4E08FDA9A04832F4E919D89462FD31BF12F92791A93519F75076D6CE3942689CDFF2F344CAFF0F82D01864F69F3AECF566C774CBACF728B81A227',
|
||||||
|
'g' :'07',
|
||||||
|
'y' :'688628C676E4F05D630E1BE39D0066178CA7AA83836B645DE5ADD359B4825A12B02EF4252E4E6FA9BEC1DB0BE90F6D7C8629CABB6E531F472B2664868156E20C',
|
||||||
|
'x' :'14E60B1BDFD33436C0DA8A22FDC14A2CCDBBED0627CE68',
|
||||||
|
'k' :'38DBF14E1F319BDA9BAB33EEEADCAF6B2EA5250577ACE7',
|
||||||
|
'pt' :'48656C6C6F207468657265',
|
||||||
|
'ct1':'290F8530C2CC312EC46178724F196F308AD4C523CEABB001FACB0506BFED676083FE0F27AC688B5C749AB3CB8A80CD6F7094DBA421FB19442F5A413E06A9772B',
|
||||||
|
'ct2':'1D69AAAD1DC50493FB1B8E8721D621D683F3BF1321BE21BC4A43E11B40C9D4D9C80DE3AAC2AB60D31782B16B61112E68220889D53C4C3136EE6F6CE61F8A23A0'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
# Signature
|
||||||
|
tvs=[
|
||||||
|
{
|
||||||
|
# 256 bits
|
||||||
|
'p' :'D2F3C41EA66530838A704A48FFAC9334F4701ECE3A97CEE4C69DD01AE7129DD7',
|
||||||
|
'g' :'05',
|
||||||
|
'y' :'C3F9417DC0DAFEA6A05C1D2333B7A95E63B3F4F28CC962254B3256984D1012E7',
|
||||||
|
'x' :'165E4A39BE44D5A2D8B1332D416BC559616F536BC735BB',
|
||||||
|
'k' :'C7F0C794A7EAD726E25A47FF8928013680E73C51DD3D7D99BFDA8F492585928F',
|
||||||
|
'h' :'48656C6C6F207468657265',
|
||||||
|
'sig1':'35CA98133779E2073EF31165AFCDEB764DD54E96ADE851715495F9C635E1E7C2',
|
||||||
|
'sig2':'0135B88B1151279FE5D8078D4FC685EE81177EE9802AB123A73925FC1CB059A7',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
# 512 bits
|
||||||
|
'p' :'E24CF3A4B8A6AF749DCA6D714282FE4AABEEE44A53BB6ED15FBE32B5D3C3EF9CC4124A2ECA331F3C1C1B667ACA3766825217E7B5F9856648D95F05330C6A19CF',
|
||||||
|
'g' :'0B',
|
||||||
|
'y' :'2AD3A1049CA5D4ED207B2431C79A8719BB4073D4A94E450EA6CEE8A760EB07ADB67C0D52C275EE85D7B52789061EE45F2F37D9B2AE522A51C28329766BFE68AC',
|
||||||
|
'x' :'16CBB4F46D9ECCF24FF9F7E63CAA3BD8936341555062AB',
|
||||||
|
'k' :'8A3D89A4E429FD2476D7D717251FB79BF900FFE77444E6BB8299DC3F84D0DD57ABAB50732AE158EA52F5B9E7D8813E81FD9F79470AE22F8F1CF9AEC820A78C69',
|
||||||
|
'h' :'48656C6C6F207468657265',
|
||||||
|
'sig1':'BE001AABAFFF976EC9016198FBFEA14CBEF96B000CCC0063D3324016F9E91FE80D8F9325812ED24DDB2B4D4CF4430B169880B3CE88313B53255BD4EC0378586F',
|
||||||
|
'sig2':'5E266F3F837BA204E3BBB6DBECC0611429D96F8C7CE8F4EFDF9D4CB681C2A954468A357BF4242CEC7418B51DFC081BCD21299EF5B5A0DDEF3A139A1817503DDE',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_generate_128(self):
|
||||||
|
self._test_random_key(128)
|
||||||
|
|
||||||
|
def test_generate_512(self):
|
||||||
|
self._test_random_key(512)
|
||||||
|
|
||||||
|
def test_encryption(self):
|
||||||
|
for tv in self.tve:
|
||||||
|
for as_longs in (0,1):
|
||||||
|
d = self.convert_tv(tv, as_longs)
|
||||||
|
key = ElGamal.construct(d['key'])
|
||||||
|
ct = key.encrypt(d['pt'], d['k'])
|
||||||
|
self.assertEqual(ct[0], d['ct1'])
|
||||||
|
self.assertEqual(ct[1], d['ct2'])
|
||||||
|
|
||||||
|
def test_decryption(self):
|
||||||
|
for tv in self.tve:
|
||||||
|
for as_longs in (0,1):
|
||||||
|
d = self.convert_tv(tv, as_longs)
|
||||||
|
key = ElGamal.construct(d['key'])
|
||||||
|
pt = key.decrypt((d['ct1'], d['ct2']))
|
||||||
|
self.assertEqual(pt, d['pt'])
|
||||||
|
|
||||||
|
def test_signing(self):
|
||||||
|
for tv in self.tvs:
|
||||||
|
for as_longs in (0,1):
|
||||||
|
d = self.convert_tv(tv, as_longs)
|
||||||
|
key = ElGamal.construct(d['key'])
|
||||||
|
sig1, sig2 = key.sign(d['h'], d['k'])
|
||||||
|
self.assertEqual(sig1, d['sig1'])
|
||||||
|
self.assertEqual(sig2, d['sig2'])
|
||||||
|
|
||||||
|
def test_verification(self):
|
||||||
|
for tv in self.tvs:
|
||||||
|
for as_longs in (0,1):
|
||||||
|
d = self.convert_tv(tv, as_longs)
|
||||||
|
key = ElGamal.construct(d['key'])
|
||||||
|
# Positive test
|
||||||
|
res = key.verify( d['h'], (d['sig1'],d['sig2']) )
|
||||||
|
self.assertTrue(res)
|
||||||
|
# Negative test
|
||||||
|
res = key.verify( d['h'], (d['sig1']+1,d['sig2']) )
|
||||||
|
self.assertFalse(res)
|
||||||
|
|
||||||
|
def convert_tv(self, tv, as_longs=0):
|
||||||
|
"""Convert a test vector from textual form (hexadecimal ascii
|
||||||
|
to either integers or byte strings."""
|
||||||
|
key_comps = 'p','g','y','x'
|
||||||
|
tv2 = {}
|
||||||
|
for c in list(tv.keys()):
|
||||||
|
tv2[c] = a2b_hex(tv[c])
|
||||||
|
if as_longs or c in key_comps or c in ('sig1','sig2'):
|
||||||
|
tv2[c] = bytes_to_long(tv2[c])
|
||||||
|
tv2['key']=[]
|
||||||
|
for c in key_comps:
|
||||||
|
tv2['key'] += [tv2[c]]
|
||||||
|
del tv2[c]
|
||||||
|
return tv2
|
||||||
|
|
||||||
|
def _test_random_key(self, bits):
|
||||||
|
elgObj = ElGamal.generate(bits, Random.new().read)
|
||||||
|
self._check_private_key(elgObj)
|
||||||
|
self._exercise_primitive(elgObj)
|
||||||
|
pub = elgObj.publickey()
|
||||||
|
self._check_public_key(pub)
|
||||||
|
self._exercise_public_primitive(elgObj)
|
||||||
|
|
||||||
|
def _check_private_key(self, elgObj):
|
||||||
|
|
||||||
|
# Check capabilities
|
||||||
|
self.assertTrue(elgObj.has_private())
|
||||||
|
self.assertTrue(elgObj.can_sign())
|
||||||
|
self.assertTrue(elgObj.can_encrypt())
|
||||||
|
|
||||||
|
# Sanity check key data
|
||||||
|
self.assertTrue(1<elgObj.g<(elgObj.p-1))
|
||||||
|
self.assertEqual(pow(elgObj.g, elgObj.p-1, elgObj.p), 1)
|
||||||
|
self.assertTrue(1<elgObj.x<(elgObj.p-1))
|
||||||
|
self.assertEqual(pow(elgObj.g, elgObj.x, elgObj.p), elgObj.y)
|
||||||
|
|
||||||
|
def _check_public_key(self, elgObj):
|
||||||
|
|
||||||
|
# Check capabilities
|
||||||
|
self.assertFalse(elgObj.has_private())
|
||||||
|
self.assertTrue(elgObj.can_sign())
|
||||||
|
self.assertTrue(elgObj.can_encrypt())
|
||||||
|
|
||||||
|
# Sanity check key data
|
||||||
|
self.assertTrue(1<elgObj.g<(elgObj.p-1))
|
||||||
|
self.assertEqual(pow(elgObj.g, elgObj.p-1, elgObj.p), 1)
|
||||||
|
|
||||||
|
def _exercise_primitive(self, elgObj):
|
||||||
|
# Test encryption/decryption
|
||||||
|
plaintext = b("Test")
|
||||||
|
ciphertext = elgObj.encrypt(plaintext, 123456789)
|
||||||
|
plaintextP = elgObj.decrypt(ciphertext)
|
||||||
|
self.assertEqual(plaintext, plaintextP)
|
||||||
|
|
||||||
|
# Test signature/verification
|
||||||
|
signature = elgObj.sign(plaintext, 987654321)
|
||||||
|
elgObj.verify(plaintext, signature)
|
||||||
|
|
||||||
|
def _exercise_public_primitive(self, elgObj):
|
||||||
|
plaintext = b("Test")
|
||||||
|
ciphertext = elgObj.encrypt(plaintext, 123456789)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
tests += list_test_cases(ElGamalTest)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
415
Lib/site-packages/Crypto/SelfTest/PublicKey/test_RSA.py
Normal file
415
Lib/site-packages/Crypto/SelfTest/PublicKey/test_RSA.py
Normal file
|
@ -0,0 +1,415 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/PublicKey/test_RSA.py: Self-test for the RSA primitive
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.PublicKey.RSA"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
|
||||||
|
|
||||||
|
class RSATest(unittest.TestCase):
|
||||||
|
# Test vectors from "RSA-OAEP and RSA-PSS test vectors (.zip file)"
|
||||||
|
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
|
||||||
|
# See RSADSI's PKCS#1 page at
|
||||||
|
# http://www.rsa.com/rsalabs/node.asp?id=2125
|
||||||
|
|
||||||
|
# from oaep-int.txt
|
||||||
|
|
||||||
|
# TODO: PyCrypto treats the message as starting *after* the leading "00"
|
||||||
|
# TODO: That behaviour should probably be changed in the future.
|
||||||
|
plaintext = """
|
||||||
|
eb 7a 19 ac e9 e3 00 63 50 e3 29 50 4b 45 e2
|
||||||
|
ca 82 31 0b 26 dc d8 7d 5c 68 f1 ee a8 f5 52 67
|
||||||
|
c3 1b 2e 8b b4 25 1f 84 d7 e0 b2 c0 46 26 f5 af
|
||||||
|
f9 3e dc fb 25 c9 c2 b3 ff 8a e1 0e 83 9a 2d db
|
||||||
|
4c dc fe 4f f4 77 28 b4 a1 b7 c1 36 2b aa d2 9a
|
||||||
|
b4 8d 28 69 d5 02 41 21 43 58 11 59 1b e3 92 f9
|
||||||
|
82 fb 3e 87 d0 95 ae b4 04 48 db 97 2f 3a c1 4f
|
||||||
|
7b c2 75 19 52 81 ce 32 d2 f1 b7 6d 4d 35 3e 2d
|
||||||
|
"""
|
||||||
|
|
||||||
|
ciphertext = """
|
||||||
|
12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0
|
||||||
|
39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7
|
||||||
|
63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6
|
||||||
|
53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb
|
||||||
|
6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0
|
||||||
|
24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48
|
||||||
|
da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d
|
||||||
|
51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55
|
||||||
|
"""
|
||||||
|
|
||||||
|
modulus = """
|
||||||
|
bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7
|
||||||
|
36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f
|
||||||
|
b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48
|
||||||
|
76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f
|
||||||
|
af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84
|
||||||
|
ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e
|
||||||
|
e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f
|
||||||
|
e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb
|
||||||
|
"""
|
||||||
|
|
||||||
|
e = 0x11 # public exponent
|
||||||
|
|
||||||
|
prime_factor = """
|
||||||
|
c9 7f b1 f0 27 f4 53 f6 34 12 33 ea aa d1 d9 35
|
||||||
|
3f 6c 42 d0 88 66 b1 d0 5a 0f 20 35 02 8b 9d 86
|
||||||
|
98 40 b4 16 66 b4 2e 92 ea 0d a3 b4 32 04 b5 cf
|
||||||
|
ce 33 52 52 4d 04 16 a5 a4 41 e7 00 af 46 15 03
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
global RSA, Random, bytes_to_long
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
from Crypto import Random
|
||||||
|
from Crypto.Util.number import bytes_to_long, inverse
|
||||||
|
self.n = bytes_to_long(a2b_hex(self.modulus))
|
||||||
|
self.p = bytes_to_long(a2b_hex(self.prime_factor))
|
||||||
|
|
||||||
|
# Compute q, d, and u from n, e, and p
|
||||||
|
self.q = divmod(self.n, self.p)[0]
|
||||||
|
self.d = inverse(self.e, (self.p-1)*(self.q-1))
|
||||||
|
self.u = inverse(self.p, self.q) # u = e**-1 (mod q)
|
||||||
|
|
||||||
|
self.rsa = RSA
|
||||||
|
|
||||||
|
def test_generate_1arg(self):
|
||||||
|
"""RSA (default implementation) generated key (1 argument)"""
|
||||||
|
rsaObj = self.rsa.generate(1024)
|
||||||
|
self._check_private_key(rsaObj)
|
||||||
|
self._exercise_primitive(rsaObj)
|
||||||
|
pub = rsaObj.publickey()
|
||||||
|
self._check_public_key(pub)
|
||||||
|
self._exercise_public_primitive(rsaObj)
|
||||||
|
|
||||||
|
def test_generate_2arg(self):
|
||||||
|
"""RSA (default implementation) generated key (2 arguments)"""
|
||||||
|
rsaObj = self.rsa.generate(1024, Random.new().read)
|
||||||
|
self._check_private_key(rsaObj)
|
||||||
|
self._exercise_primitive(rsaObj)
|
||||||
|
pub = rsaObj.publickey()
|
||||||
|
self._check_public_key(pub)
|
||||||
|
self._exercise_public_primitive(rsaObj)
|
||||||
|
|
||||||
|
def test_generate_3args(self):
|
||||||
|
rsaObj = self.rsa.generate(1024, Random.new().read,e=65537)
|
||||||
|
self._check_private_key(rsaObj)
|
||||||
|
self._exercise_primitive(rsaObj)
|
||||||
|
pub = rsaObj.publickey()
|
||||||
|
self._check_public_key(pub)
|
||||||
|
self._exercise_public_primitive(rsaObj)
|
||||||
|
self.assertEqual(65537,rsaObj.e)
|
||||||
|
|
||||||
|
def test_construct_2tuple(self):
|
||||||
|
"""RSA (default implementation) constructed key (2-tuple)"""
|
||||||
|
pub = self.rsa.construct((self.n, self.e))
|
||||||
|
self._check_public_key(pub)
|
||||||
|
self._check_encryption(pub)
|
||||||
|
self._check_verification(pub)
|
||||||
|
|
||||||
|
def test_construct_3tuple(self):
|
||||||
|
"""RSA (default implementation) constructed key (3-tuple)"""
|
||||||
|
rsaObj = self.rsa.construct((self.n, self.e, self.d))
|
||||||
|
self._check_encryption(rsaObj)
|
||||||
|
self._check_decryption(rsaObj)
|
||||||
|
self._check_signing(rsaObj)
|
||||||
|
self._check_verification(rsaObj)
|
||||||
|
|
||||||
|
def test_construct_4tuple(self):
|
||||||
|
"""RSA (default implementation) constructed key (4-tuple)"""
|
||||||
|
rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p))
|
||||||
|
self._check_encryption(rsaObj)
|
||||||
|
self._check_decryption(rsaObj)
|
||||||
|
self._check_signing(rsaObj)
|
||||||
|
self._check_verification(rsaObj)
|
||||||
|
|
||||||
|
def test_construct_5tuple(self):
|
||||||
|
"""RSA (default implementation) constructed key (5-tuple)"""
|
||||||
|
rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q))
|
||||||
|
self._check_private_key(rsaObj)
|
||||||
|
self._check_encryption(rsaObj)
|
||||||
|
self._check_decryption(rsaObj)
|
||||||
|
self._check_signing(rsaObj)
|
||||||
|
self._check_verification(rsaObj)
|
||||||
|
|
||||||
|
def test_construct_6tuple(self):
|
||||||
|
"""RSA (default implementation) constructed key (6-tuple)"""
|
||||||
|
rsaObj = self.rsa.construct((self.n, self.e, self.d, self.p, self.q, self.u))
|
||||||
|
self._check_private_key(rsaObj)
|
||||||
|
self._check_encryption(rsaObj)
|
||||||
|
self._check_decryption(rsaObj)
|
||||||
|
self._check_signing(rsaObj)
|
||||||
|
self._check_verification(rsaObj)
|
||||||
|
|
||||||
|
def test_factoring(self):
|
||||||
|
rsaObj = self.rsa.construct([self.n, self.e, self.d])
|
||||||
|
self.assertTrue(rsaObj.p==self.p or rsaObj.p==self.q)
|
||||||
|
self.assertTrue(rsaObj.q==self.p or rsaObj.q==self.q)
|
||||||
|
self.assertTrue(rsaObj.q*rsaObj.p == self.n)
|
||||||
|
|
||||||
|
self.assertRaises(ValueError, self.rsa.construct, [self.n, self.e, self.n-1])
|
||||||
|
|
||||||
|
def _check_private_key(self, rsaObj):
|
||||||
|
# Check capabilities
|
||||||
|
self.assertEqual(1, rsaObj.has_private())
|
||||||
|
self.assertEqual(1, rsaObj.can_sign())
|
||||||
|
self.assertEqual(1, rsaObj.can_encrypt())
|
||||||
|
self.assertEqual(1, rsaObj.can_blind())
|
||||||
|
|
||||||
|
# Check rsaObj.[nedpqu] -> rsaObj.key.[nedpqu] mapping
|
||||||
|
self.assertEqual(rsaObj.n, rsaObj.key.n)
|
||||||
|
self.assertEqual(rsaObj.e, rsaObj.key.e)
|
||||||
|
self.assertEqual(rsaObj.d, rsaObj.key.d)
|
||||||
|
self.assertEqual(rsaObj.p, rsaObj.key.p)
|
||||||
|
self.assertEqual(rsaObj.q, rsaObj.key.q)
|
||||||
|
self.assertEqual(rsaObj.u, rsaObj.key.u)
|
||||||
|
|
||||||
|
# Sanity check key data
|
||||||
|
self.assertEqual(rsaObj.n, rsaObj.p * rsaObj.q) # n = pq
|
||||||
|
self.assertEqual(1, rsaObj.d * rsaObj.e % ((rsaObj.p-1) * (rsaObj.q-1))) # ed = 1 (mod (p-1)(q-1))
|
||||||
|
self.assertEqual(1, rsaObj.p * rsaObj.u % rsaObj.q) # pu = 1 (mod q)
|
||||||
|
self.assertEqual(1, rsaObj.p > 1) # p > 1
|
||||||
|
self.assertEqual(1, rsaObj.q > 1) # q > 1
|
||||||
|
self.assertEqual(1, rsaObj.e > 1) # e > 1
|
||||||
|
self.assertEqual(1, rsaObj.d > 1) # d > 1
|
||||||
|
|
||||||
|
def _check_public_key(self, rsaObj):
|
||||||
|
ciphertext = a2b_hex(self.ciphertext)
|
||||||
|
|
||||||
|
# Check capabilities
|
||||||
|
self.assertEqual(0, rsaObj.has_private())
|
||||||
|
self.assertEqual(1, rsaObj.can_sign())
|
||||||
|
self.assertEqual(1, rsaObj.can_encrypt())
|
||||||
|
self.assertEqual(1, rsaObj.can_blind())
|
||||||
|
|
||||||
|
# Check rsaObj.[ne] -> rsaObj.key.[ne] mapping
|
||||||
|
self.assertEqual(rsaObj.n, rsaObj.key.n)
|
||||||
|
self.assertEqual(rsaObj.e, rsaObj.key.e)
|
||||||
|
|
||||||
|
# Check that private parameters are all missing
|
||||||
|
self.assertEqual(0, hasattr(rsaObj, 'd'))
|
||||||
|
self.assertEqual(0, hasattr(rsaObj, 'p'))
|
||||||
|
self.assertEqual(0, hasattr(rsaObj, 'q'))
|
||||||
|
self.assertEqual(0, hasattr(rsaObj, 'u'))
|
||||||
|
self.assertEqual(0, hasattr(rsaObj.key, 'd'))
|
||||||
|
self.assertEqual(0, hasattr(rsaObj.key, 'p'))
|
||||||
|
self.assertEqual(0, hasattr(rsaObj.key, 'q'))
|
||||||
|
self.assertEqual(0, hasattr(rsaObj.key, 'u'))
|
||||||
|
|
||||||
|
# Sanity check key data
|
||||||
|
self.assertEqual(1, rsaObj.e > 1) # e > 1
|
||||||
|
|
||||||
|
# Public keys should not be able to sign or decrypt
|
||||||
|
self.assertRaises(TypeError, rsaObj.sign, ciphertext, b(""))
|
||||||
|
self.assertRaises(TypeError, rsaObj.decrypt, ciphertext)
|
||||||
|
|
||||||
|
# Check __eq__ and __ne__
|
||||||
|
self.assertEqual(rsaObj.publickey() == rsaObj.publickey(),True) # assert_
|
||||||
|
self.assertEqual(rsaObj.publickey() != rsaObj.publickey(),False) # failIf
|
||||||
|
|
||||||
|
def _exercise_primitive(self, rsaObj):
|
||||||
|
# Since we're using a randomly-generated key, we can't check the test
|
||||||
|
# vector, but we can make sure encryption and decryption are inverse
|
||||||
|
# operations.
|
||||||
|
ciphertext = a2b_hex(self.ciphertext)
|
||||||
|
|
||||||
|
# Test decryption
|
||||||
|
plaintext = rsaObj.decrypt((ciphertext,))
|
||||||
|
|
||||||
|
# Test encryption (2 arguments)
|
||||||
|
(new_ciphertext2,) = rsaObj.encrypt(plaintext, b(""))
|
||||||
|
self.assertEqual(b2a_hex(ciphertext), b2a_hex(new_ciphertext2))
|
||||||
|
|
||||||
|
# Test blinded decryption
|
||||||
|
blinding_factor = Random.new().read(len(ciphertext)-1)
|
||||||
|
blinded_ctext = rsaObj.blind(ciphertext, blinding_factor)
|
||||||
|
blinded_ptext = rsaObj.decrypt((blinded_ctext,))
|
||||||
|
unblinded_plaintext = rsaObj.unblind(blinded_ptext, blinding_factor)
|
||||||
|
self.assertEqual(b2a_hex(plaintext), b2a_hex(unblinded_plaintext))
|
||||||
|
|
||||||
|
# Test signing (2 arguments)
|
||||||
|
signature2 = rsaObj.sign(ciphertext, b(""))
|
||||||
|
self.assertEqual((bytes_to_long(plaintext),), signature2)
|
||||||
|
|
||||||
|
# Test verification
|
||||||
|
self.assertEqual(1, rsaObj.verify(ciphertext, (bytes_to_long(plaintext),)))
|
||||||
|
|
||||||
|
def _exercise_public_primitive(self, rsaObj):
|
||||||
|
plaintext = a2b_hex(self.plaintext)
|
||||||
|
|
||||||
|
# Test encryption (2 arguments)
|
||||||
|
(new_ciphertext2,) = rsaObj.encrypt(plaintext, b(""))
|
||||||
|
|
||||||
|
# Exercise verification
|
||||||
|
rsaObj.verify(new_ciphertext2, (bytes_to_long(plaintext),))
|
||||||
|
|
||||||
|
def _check_encryption(self, rsaObj):
|
||||||
|
plaintext = a2b_hex(self.plaintext)
|
||||||
|
ciphertext = a2b_hex(self.ciphertext)
|
||||||
|
|
||||||
|
# Test encryption (2 arguments)
|
||||||
|
(new_ciphertext2,) = rsaObj.encrypt(plaintext, b(""))
|
||||||
|
self.assertEqual(b2a_hex(ciphertext), b2a_hex(new_ciphertext2))
|
||||||
|
|
||||||
|
def _check_decryption(self, rsaObj):
|
||||||
|
plaintext = a2b_hex(self.plaintext)
|
||||||
|
ciphertext = a2b_hex(self.ciphertext)
|
||||||
|
|
||||||
|
# Test plain decryption
|
||||||
|
new_plaintext = rsaObj.decrypt((ciphertext,))
|
||||||
|
self.assertEqual(b2a_hex(plaintext), b2a_hex(new_plaintext))
|
||||||
|
|
||||||
|
# Test blinded decryption
|
||||||
|
blinding_factor = Random.new().read(len(ciphertext)-1)
|
||||||
|
blinded_ctext = rsaObj.blind(ciphertext, blinding_factor)
|
||||||
|
blinded_ptext = rsaObj.decrypt((blinded_ctext,))
|
||||||
|
unblinded_plaintext = rsaObj.unblind(blinded_ptext, blinding_factor)
|
||||||
|
self.assertEqual(b2a_hex(plaintext), b2a_hex(unblinded_plaintext))
|
||||||
|
|
||||||
|
def _check_verification(self, rsaObj):
|
||||||
|
signature = bytes_to_long(a2b_hex(self.plaintext))
|
||||||
|
message = a2b_hex(self.ciphertext)
|
||||||
|
|
||||||
|
# Test verification
|
||||||
|
t = (signature,) # rsaObj.verify expects a tuple
|
||||||
|
self.assertEqual(1, rsaObj.verify(message, t))
|
||||||
|
|
||||||
|
# Test verification with overlong tuple (this is a
|
||||||
|
# backward-compatibility hack to support some harmless misuse of the
|
||||||
|
# API)
|
||||||
|
t2 = (signature, '')
|
||||||
|
self.assertEqual(1, rsaObj.verify(message, t2)) # extra garbage at end of tuple
|
||||||
|
|
||||||
|
def _check_signing(self, rsaObj):
|
||||||
|
signature = bytes_to_long(a2b_hex(self.plaintext))
|
||||||
|
message = a2b_hex(self.ciphertext)
|
||||||
|
|
||||||
|
# Test signing (2 argument)
|
||||||
|
self.assertEqual((signature,), rsaObj.sign(message, b("")))
|
||||||
|
|
||||||
|
class RSAFastMathTest(RSATest):
|
||||||
|
def setUp(self):
|
||||||
|
RSATest.setUp(self)
|
||||||
|
self.rsa = RSA.RSAImplementation(use_fast_math=True)
|
||||||
|
|
||||||
|
def test_generate_1arg(self):
|
||||||
|
"""RSA (_fastmath implementation) generated key (1 argument)"""
|
||||||
|
RSATest.test_generate_1arg(self)
|
||||||
|
|
||||||
|
def test_generate_2arg(self):
|
||||||
|
"""RSA (_fastmath implementation) generated key (2 arguments)"""
|
||||||
|
RSATest.test_generate_2arg(self)
|
||||||
|
|
||||||
|
def test_construct_2tuple(self):
|
||||||
|
"""RSA (_fastmath implementation) constructed key (2-tuple)"""
|
||||||
|
RSATest.test_construct_2tuple(self)
|
||||||
|
|
||||||
|
def test_construct_3tuple(self):
|
||||||
|
"""RSA (_fastmath implementation) constructed key (3-tuple)"""
|
||||||
|
RSATest.test_construct_3tuple(self)
|
||||||
|
|
||||||
|
def test_construct_4tuple(self):
|
||||||
|
"""RSA (_fastmath implementation) constructed key (4-tuple)"""
|
||||||
|
RSATest.test_construct_4tuple(self)
|
||||||
|
|
||||||
|
def test_construct_5tuple(self):
|
||||||
|
"""RSA (_fastmath implementation) constructed key (5-tuple)"""
|
||||||
|
RSATest.test_construct_5tuple(self)
|
||||||
|
|
||||||
|
def test_construct_6tuple(self):
|
||||||
|
"""RSA (_fastmath implementation) constructed key (6-tuple)"""
|
||||||
|
RSATest.test_construct_6tuple(self)
|
||||||
|
|
||||||
|
def test_factoring(self):
|
||||||
|
RSATest.test_factoring(self)
|
||||||
|
|
||||||
|
class RSASlowMathTest(RSATest):
|
||||||
|
def setUp(self):
|
||||||
|
RSATest.setUp(self)
|
||||||
|
self.rsa = RSA.RSAImplementation(use_fast_math=False)
|
||||||
|
|
||||||
|
def test_generate_1arg(self):
|
||||||
|
"""RSA (_slowmath implementation) generated key (1 argument)"""
|
||||||
|
RSATest.test_generate_1arg(self)
|
||||||
|
|
||||||
|
def test_generate_2arg(self):
|
||||||
|
"""RSA (_slowmath implementation) generated key (2 arguments)"""
|
||||||
|
RSATest.test_generate_2arg(self)
|
||||||
|
|
||||||
|
def test_construct_2tuple(self):
|
||||||
|
"""RSA (_slowmath implementation) constructed key (2-tuple)"""
|
||||||
|
RSATest.test_construct_2tuple(self)
|
||||||
|
|
||||||
|
def test_construct_3tuple(self):
|
||||||
|
"""RSA (_slowmath implementation) constructed key (3-tuple)"""
|
||||||
|
RSATest.test_construct_3tuple(self)
|
||||||
|
|
||||||
|
def test_construct_4tuple(self):
|
||||||
|
"""RSA (_slowmath implementation) constructed key (4-tuple)"""
|
||||||
|
RSATest.test_construct_4tuple(self)
|
||||||
|
|
||||||
|
def test_construct_5tuple(self):
|
||||||
|
"""RSA (_slowmath implementation) constructed key (5-tuple)"""
|
||||||
|
RSATest.test_construct_5tuple(self)
|
||||||
|
|
||||||
|
def test_construct_6tuple(self):
|
||||||
|
"""RSA (_slowmath implementation) constructed key (6-tuple)"""
|
||||||
|
RSATest.test_construct_6tuple(self)
|
||||||
|
|
||||||
|
def test_factoring(self):
|
||||||
|
RSATest.test_factoring(self)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
tests += list_test_cases(RSATest)
|
||||||
|
try:
|
||||||
|
from Crypto.PublicKey import _fastmath
|
||||||
|
tests += list_test_cases(RSAFastMathTest)
|
||||||
|
except ImportError:
|
||||||
|
from distutils.sysconfig import get_config_var
|
||||||
|
import inspect
|
||||||
|
_fm_path = os.path.normpath(os.path.dirname(os.path.abspath(
|
||||||
|
inspect.getfile(inspect.currentframe())))
|
||||||
|
+"/../../PublicKey/_fastmath"+get_config_var("SO"))
|
||||||
|
if os.path.exists(_fm_path):
|
||||||
|
raise ImportError("While the _fastmath module exists, importing "+
|
||||||
|
"it failed. This may point to the gmp or mpir shared library "+
|
||||||
|
"not being in the path. _fastmath was found at "+_fm_path)
|
||||||
|
if config.get('slow_tests',1):
|
||||||
|
tests += list_test_cases(RSASlowMathTest)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
345
Lib/site-packages/Crypto/SelfTest/PublicKey/test_importKey.py
Normal file
345
Lib/site-packages/Crypto/SelfTest/PublicKey/test_importKey.py
Normal file
|
@ -0,0 +1,345 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/PublicKey/test_importKey.py: Self-test for importing RSA keys
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
from Crypto.SelfTest.st_common import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
from Crypto.Util.number import inverse
|
||||||
|
from Crypto.Util import asn1
|
||||||
|
|
||||||
|
def der2pem(der, text='PUBLIC'):
|
||||||
|
import binascii
|
||||||
|
chunks = [ binascii.b2a_base64(der[i:i+48]) for i in range(0, len(der), 48) ]
|
||||||
|
pem = b('-----BEGIN %s KEY-----\n' % text)
|
||||||
|
pem += b('').join(chunks)
|
||||||
|
pem += b('-----END %s KEY-----' % text)
|
||||||
|
return pem
|
||||||
|
|
||||||
|
class ImportKeyTests(unittest.TestCase):
|
||||||
|
# 512-bit RSA key generated with openssl
|
||||||
|
rsaKeyPEM = '''-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII
|
||||||
|
q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8
|
||||||
|
Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI
|
||||||
|
OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr
|
||||||
|
+rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK
|
||||||
|
JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9
|
||||||
|
n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ==
|
||||||
|
-----END RSA PRIVATE KEY-----'''
|
||||||
|
|
||||||
|
# As above, but this is actually an unencrypted PKCS#8 key
|
||||||
|
rsaKeyPEM8 = '''-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvx4nkAqgiyNRGlwS
|
||||||
|
ga5tkzEsPv6RP5MuvtSS8S0WtGEMMoy24girX0WsvilQgzKY8xIsGfeEkt7fQPDj
|
||||||
|
wZAzhQIDAQABAkAJRIMSnxFN7fZ+2rwjAbxaiOXmYB3XAWIg6tn9S/xv3rdYk4mK
|
||||||
|
5BxU3b2/FTn4zL0Y9ntEDeGsMEQCgdQM+sg5AiEA8g8vPh2mGIP2KYCSK9jfVFzk
|
||||||
|
B8cmJBEDteLFNyMSSiMCIQDKH+kkeSz8yWv6t080Smi0GN9XgzgGSAYAD+KlyZoC
|
||||||
|
NwIhAIe+HDApUEvPNOxxPYd5R0R4EyiJdcokAICvewlAkbEhAiBqtGn6bVZIpXUx
|
||||||
|
yLAxpM6dtTvDEWz0M/Wm9rvqVgHOBQIhAL2fQKdkInohlipK3Qfk3v5D7ZGjrie7
|
||||||
|
BX85JB8zqwHB
|
||||||
|
-----END PRIVATE KEY-----'''
|
||||||
|
|
||||||
|
# The same RSA private key as in rsaKeyPEM, but now encrypted
|
||||||
|
rsaKeyEncryptedPEM=(
|
||||||
|
|
||||||
|
# With DES and passphrase 'test'
|
||||||
|
('test', '''-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
Proc-Type: 4,ENCRYPTED
|
||||||
|
DEK-Info: DES-CBC,AF8F9A40BD2FA2FC
|
||||||
|
|
||||||
|
Ckl9ex1kaVEWhYC2QBmfaF+YPiR4NFkRXA7nj3dcnuFEzBnY5XULupqQpQI3qbfA
|
||||||
|
u8GYS7+b3toWWiHZivHbAAUBPDIZG9hKDyB9Sq2VMARGsX1yW1zhNvZLIiVJzUHs
|
||||||
|
C6NxQ1IJWOXzTew/xM2I26kPwHIvadq+/VaT8gLQdjdH0jOiVNaevjWnLgrn1mLP
|
||||||
|
BCNRMdcexozWtAFNNqSzfW58MJL2OdMi21ED184EFytIc1BlB+FZiGZduwKGuaKy
|
||||||
|
9bMbdb/1PSvsSzPsqW7KSSrTw6MgJAFJg6lzIYvR5F4poTVBxwBX3+EyEmShiaNY
|
||||||
|
IRX3TgQI0IjrVuLmvlZKbGWP18FXj7I7k9tSsNOOzllTTdq3ny5vgM3A+ynfAaxp
|
||||||
|
dysKznQ6P+IoqML1WxAID4aGRMWka+uArOJ148Rbj9s=
|
||||||
|
-----END RSA PRIVATE KEY-----''',
|
||||||
|
"\xAF\x8F\x9A\x40\xBD\x2F\xA2\xFC"),
|
||||||
|
|
||||||
|
# With Triple-DES and passphrase 'rocking'
|
||||||
|
('rocking', '''-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
Proc-Type: 4,ENCRYPTED
|
||||||
|
DEK-Info: DES-EDE3-CBC,C05D6C07F7FC02F6
|
||||||
|
|
||||||
|
w4lwQrXaVoTTJ0GgwY566htTA2/t1YlimhxkxYt9AEeCcidS5M0Wq9ClPiPz9O7F
|
||||||
|
m6K5QpM1rxo1RUE/ZyI85gglRNPdNwkeTOqit+kum7nN73AToX17+irVmOA4Z9E+
|
||||||
|
4O07t91GxGMcjUSIFk0ucwEU4jgxRvYscbvOMvNbuZszGdVNzBTVddnShKCsy9i7
|
||||||
|
nJbPlXeEKYi/OkRgO4PtfqqWQu5GIEFVUf9ev1QV7AvC+kyWTR1wWYnHX265jU5c
|
||||||
|
sopxQQtP8XEHIJEdd5/p1oieRcWTCNyY8EkslxDSsrf0OtZp6mZH9N+KU47cgQtt
|
||||||
|
9qGORmlWnsIoFFKcDohbtOaWBTKhkj5h6OkLjFjfU/sBeV1c+7wDT3dAy5tawXjG
|
||||||
|
YSxC7qDQIT/RECvV3+oQKEcmpEujn45wAnkTi12BH30=
|
||||||
|
-----END RSA PRIVATE KEY-----''',
|
||||||
|
"\xC0\x5D\x6C\x07\xF7\xFC\x02\xF6"),
|
||||||
|
)
|
||||||
|
|
||||||
|
rsaPublicKeyPEM = '''-----BEGIN PUBLIC KEY-----
|
||||||
|
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+T
|
||||||
|
Lr7UkvEtFrRhDDKMtuIIq19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQ==
|
||||||
|
-----END PUBLIC KEY-----'''
|
||||||
|
|
||||||
|
# Obtained using 'ssh-keygen -i -m PKCS8 -f rsaPublicKeyPEM'
|
||||||
|
rsaPublicKeyOpenSSH = '''ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQC/HieQCqCLI1EaXBKBrm2TMSw+/pE/ky6+1JLxLRa0YQwyjLbiCKtfRay+KVCDMpjzEiwZ94SS3t9A8OPBkDOF comment\n'''
|
||||||
|
|
||||||
|
# The private key, in PKCS#1 format encoded with DER
|
||||||
|
rsaKeyDER = a2b_hex(
|
||||||
|
'''3082013b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe
|
||||||
|
913f932ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f312
|
||||||
|
2c19f78492dedf40f0e3c190338502030100010240094483129f114dedf6
|
||||||
|
7edabc2301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c
|
||||||
|
54ddbdbf1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f
|
||||||
|
2f3e1da61883f62980922bd8df545ce407c726241103b5e2c53723124a23
|
||||||
|
022100ca1fe924792cfcc96bfab74f344a68b418df578338064806000fe2
|
||||||
|
a5c99a023702210087be1c3029504bcf34ec713d877947447813288975ca
|
||||||
|
240080af7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53b
|
||||||
|
c3116cf433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07
|
||||||
|
e4defe43ed91a3ae27bb057f39241f33ab01c1
|
||||||
|
'''.replace(" ",""))
|
||||||
|
|
||||||
|
# The private key, in unencrypted PKCS#8 format encoded with DER
|
||||||
|
rsaKeyDER8 = a2b_hex(
|
||||||
|
'''30820155020100300d06092a864886f70d01010105000482013f3082013
|
||||||
|
b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe913f932
|
||||||
|
ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f3122c19f78
|
||||||
|
492dedf40f0e3c190338502030100010240094483129f114dedf67edabc2
|
||||||
|
301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c54ddbdb
|
||||||
|
f1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f2f3e1da
|
||||||
|
61883f62980922bd8df545ce407c726241103b5e2c53723124a23022100c
|
||||||
|
a1fe924792cfcc96bfab74f344a68b418df578338064806000fe2a5c99a0
|
||||||
|
23702210087be1c3029504bcf34ec713d877947447813288975ca240080a
|
||||||
|
f7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53bc3116cf
|
||||||
|
433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07e4defe4
|
||||||
|
3ed91a3ae27bb057f39241f33ab01c1
|
||||||
|
'''.replace(" ",""))
|
||||||
|
|
||||||
|
rsaPublicKeyDER = a2b_hex(
|
||||||
|
'''305c300d06092a864886f70d0101010500034b003048024100bf1e27900a
|
||||||
|
a08b23511a5c1281ae6d93312c3efe913f932ebed492f12d16b4610c328c
|
||||||
|
b6e208ab5f45acbe2950833298f3122c19f78492dedf40f0e3c190338502
|
||||||
|
03010001
|
||||||
|
'''.replace(" ",""))
|
||||||
|
|
||||||
|
n = int('BF 1E 27 90 0A A0 8B 23 51 1A 5C 12 81 AE 6D 93 31 2C 3E FE 91 3F 93 2E BE D4 92 F1 2D 16 B4 61 0C 32 8C B6 E2 08 AB 5F 45 AC BE 29 50 83 32 98 F3 12 2C 19 F7 84 92 DE DF 40 F0 E3 C1 90 33 85'.replace(" ",""),16)
|
||||||
|
e = 65537
|
||||||
|
d = int('09 44 83 12 9F 11 4D ED F6 7E DA BC 23 01 BC 5A 88 E5 E6 60 1D D7 01 62 20 EA D9 FD 4B FC 6F DE B7 58 93 89 8A E4 1C 54 DD BD BF 15 39 F8 CC BD 18 F6 7B 44 0D E1 AC 30 44 02 81 D4 0C FA C8 39'.replace(" ",""),16)
|
||||||
|
p = int('00 F2 0F 2F 3E 1D A6 18 83 F6 29 80 92 2B D8 DF 54 5C E4 07 C7 26 24 11 03 B5 E2 C5 37 23 12 4A 23'.replace(" ",""),16)
|
||||||
|
q = int('00 CA 1F E9 24 79 2C FC C9 6B FA B7 4F 34 4A 68 B4 18 DF 57 83 38 06 48 06 00 0F E2 A5 C9 9A 02 37'.replace(" ",""),16)
|
||||||
|
|
||||||
|
# This is q^{-1} mod p). fastmath and slowmath use pInv (p^{-1}
|
||||||
|
# mod q) instead!
|
||||||
|
qInv = int('00 BD 9F 40 A7 64 22 7A 21 96 2A 4A DD 07 E4 DE FE 43 ED 91 A3 AE 27 BB 05 7F 39 24 1F 33 AB 01 C1'.replace(" ",""),16)
|
||||||
|
pInv = inverse(p,q)
|
||||||
|
|
||||||
|
def testImportKey1(self):
|
||||||
|
"""Verify import of RSAPrivateKey DER SEQUENCE"""
|
||||||
|
key = self.rsa.importKey(self.rsaKeyDER)
|
||||||
|
self.assertTrue(key.has_private())
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
self.assertEqual(key.d, self.d)
|
||||||
|
self.assertEqual(key.p, self.p)
|
||||||
|
self.assertEqual(key.q, self.q)
|
||||||
|
|
||||||
|
def testImportKey2(self):
|
||||||
|
"""Verify import of SubjectPublicKeyInfo DER SEQUENCE"""
|
||||||
|
key = self.rsa.importKey(self.rsaPublicKeyDER)
|
||||||
|
self.assertFalse(key.has_private())
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
|
||||||
|
def testImportKey3unicode(self):
|
||||||
|
"""Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode"""
|
||||||
|
key = RSA.importKey(self.rsaKeyPEM)
|
||||||
|
self.assertEqual(key.has_private(),True) # assert_
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
self.assertEqual(key.d, self.d)
|
||||||
|
self.assertEqual(key.p, self.p)
|
||||||
|
self.assertEqual(key.q, self.q)
|
||||||
|
|
||||||
|
def testImportKey3bytes(self):
|
||||||
|
"""Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as byte string"""
|
||||||
|
key = RSA.importKey(b(self.rsaKeyPEM))
|
||||||
|
self.assertEqual(key.has_private(),True) # assert_
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
self.assertEqual(key.d, self.d)
|
||||||
|
self.assertEqual(key.p, self.p)
|
||||||
|
self.assertEqual(key.q, self.q)
|
||||||
|
|
||||||
|
def testImportKey4unicode(self):
|
||||||
|
"""Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode"""
|
||||||
|
key = RSA.importKey(self.rsaPublicKeyPEM)
|
||||||
|
self.assertEqual(key.has_private(),False) # failIf
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
|
||||||
|
def testImportKey4bytes(self):
|
||||||
|
"""Verify import of SubjectPublicKeyInfo DER SEQUENCE, encoded with PEM as byte string"""
|
||||||
|
key = RSA.importKey(b(self.rsaPublicKeyPEM))
|
||||||
|
self.assertEqual(key.has_private(),False) # failIf
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
|
||||||
|
def testImportKey5(self):
|
||||||
|
"""Verifies that the imported key is still a valid RSA pair"""
|
||||||
|
key = RSA.importKey(self.rsaKeyPEM)
|
||||||
|
idem = key.encrypt(key.decrypt(b("Test")),0)
|
||||||
|
self.assertEqual(idem[0],b("Test"))
|
||||||
|
|
||||||
|
def testImportKey6(self):
|
||||||
|
"""Verifies that the imported key is still a valid RSA pair"""
|
||||||
|
key = RSA.importKey(self.rsaKeyDER)
|
||||||
|
idem = key.encrypt(key.decrypt(b("Test")),0)
|
||||||
|
self.assertEqual(idem[0],b("Test"))
|
||||||
|
|
||||||
|
def testImportKey7(self):
|
||||||
|
"""Verify import of OpenSSH public key"""
|
||||||
|
key = self.rsa.importKey(self.rsaPublicKeyOpenSSH)
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
|
||||||
|
def testImportKey8(self):
|
||||||
|
"""Verify import of encrypted PrivateKeyInfo DER SEQUENCE"""
|
||||||
|
for t in self.rsaKeyEncryptedPEM:
|
||||||
|
key = self.rsa.importKey(t[1], t[0])
|
||||||
|
self.assertTrue(key.has_private())
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
self.assertEqual(key.d, self.d)
|
||||||
|
self.assertEqual(key.p, self.p)
|
||||||
|
self.assertEqual(key.q, self.q)
|
||||||
|
|
||||||
|
def testImportKey9(self):
|
||||||
|
"""Verify import of unencrypted PrivateKeyInfo DER SEQUENCE"""
|
||||||
|
key = self.rsa.importKey(self.rsaKeyDER8)
|
||||||
|
self.assertTrue(key.has_private())
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
self.assertEqual(key.d, self.d)
|
||||||
|
self.assertEqual(key.p, self.p)
|
||||||
|
self.assertEqual(key.q, self.q)
|
||||||
|
|
||||||
|
def testImportKey10(self):
|
||||||
|
"""Verify import of unencrypted PrivateKeyInfo DER SEQUENCE, encoded with PEM"""
|
||||||
|
key = self.rsa.importKey(self.rsaKeyPEM8)
|
||||||
|
self.assertTrue(key.has_private())
|
||||||
|
self.assertEqual(key.n, self.n)
|
||||||
|
self.assertEqual(key.e, self.e)
|
||||||
|
self.assertEqual(key.d, self.d)
|
||||||
|
self.assertEqual(key.p, self.p)
|
||||||
|
self.assertEqual(key.q, self.q)
|
||||||
|
|
||||||
|
def testImportKey11(self):
|
||||||
|
"""Verify import of RSAPublicKey DER SEQUENCE"""
|
||||||
|
der = asn1.DerSequence([17, 3]).encode()
|
||||||
|
key = self.rsa.importKey(der)
|
||||||
|
self.assertEqual(key.n, 17)
|
||||||
|
self.assertEqual(key.e, 3)
|
||||||
|
|
||||||
|
def testImportKey12(self):
|
||||||
|
"""Verify import of RSAPublicKey DER SEQUENCE, encoded with PEM"""
|
||||||
|
der = asn1.DerSequence([17, 3]).encode()
|
||||||
|
pem = der2pem(der)
|
||||||
|
key = self.rsa.importKey(pem)
|
||||||
|
self.assertEqual(key.n, 17)
|
||||||
|
self.assertEqual(key.e, 3)
|
||||||
|
|
||||||
|
###
|
||||||
|
def testExportKey1(self):
|
||||||
|
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||||
|
derKey = key.exportKey("DER")
|
||||||
|
self.assertEqual(derKey, self.rsaKeyDER)
|
||||||
|
|
||||||
|
def testExportKey2(self):
|
||||||
|
key = self.rsa.construct([self.n, self.e])
|
||||||
|
derKey = key.exportKey("DER")
|
||||||
|
self.assertEqual(derKey, self.rsaPublicKeyDER)
|
||||||
|
|
||||||
|
def testExportKey3(self):
|
||||||
|
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||||
|
pemKey = key.exportKey("PEM")
|
||||||
|
self.assertEqual(pemKey, b(self.rsaKeyPEM))
|
||||||
|
|
||||||
|
def testExportKey4(self):
|
||||||
|
key = self.rsa.construct([self.n, self.e])
|
||||||
|
pemKey = key.exportKey("PEM")
|
||||||
|
self.assertEqual(pemKey, b(self.rsaPublicKeyPEM))
|
||||||
|
|
||||||
|
def testExportKey5(self):
|
||||||
|
key = self.rsa.construct([self.n, self.e])
|
||||||
|
openssh_1 = key.exportKey("OpenSSH").split()
|
||||||
|
openssh_2 = self.rsaPublicKeyOpenSSH.split()
|
||||||
|
self.assertEqual(openssh_1[0], openssh_2[0])
|
||||||
|
self.assertEqual(openssh_1[1], openssh_2[1])
|
||||||
|
|
||||||
|
def testExportKey4(self):
|
||||||
|
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||||
|
# Tuple with index #1 is encrypted with 3DES
|
||||||
|
t = list(map(b,self.rsaKeyEncryptedPEM[1]))
|
||||||
|
# Force the salt being used when exporting
|
||||||
|
key._randfunc = lambda N: (t[2]*divmod(N+len(t[2]),len(t[2]))[0])[:N]
|
||||||
|
pemKey = key.exportKey("PEM", t[0])
|
||||||
|
self.assertEqual(pemKey, t[1])
|
||||||
|
|
||||||
|
def testExportKey5(self):
|
||||||
|
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||||
|
derKey = key.exportKey("DER", pkcs=8)
|
||||||
|
self.assertEqual(derKey, self.rsaKeyDER8)
|
||||||
|
|
||||||
|
def testExportKey6(self):
|
||||||
|
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||||
|
pemKey = key.exportKey("PEM", pkcs=8)
|
||||||
|
self.assertEqual(pemKey, b(self.rsaKeyPEM8))
|
||||||
|
|
||||||
|
class ImportKeyTestsSlow(ImportKeyTests):
|
||||||
|
def setUp(self):
|
||||||
|
self.rsa = RSA.RSAImplementation(use_fast_math=0)
|
||||||
|
|
||||||
|
class ImportKeyTestsFast(ImportKeyTests):
|
||||||
|
def setUp(self):
|
||||||
|
self.rsa = RSA.RSAImplementation(use_fast_math=1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
try:
|
||||||
|
from Crypto.PublicKey import _fastmath
|
||||||
|
tests += list_test_cases(ImportKeyTestsFast)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
tests += list_test_cases(ImportKeyTestsSlow)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
44
Lib/site-packages/Crypto/SelfTest/Random/Fortuna/__init__.py
Normal file
44
Lib/site-packages/Crypto/SelfTest/Random/Fortuna/__init__.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Random/Fortuna/__init__.py: Self-test for Fortuna modules
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test for the Crypto.Random.Fortuna package"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
from Crypto.SelfTest.Random.Fortuna import test_FortunaAccumulator; tests += test_FortunaAccumulator.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Random.Fortuna import test_FortunaGenerator; tests += test_FortunaGenerator.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Random.Fortuna import test_SHAd256; tests += test_SHAd256.get_tests(config=config)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
|
@ -0,0 +1,189 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Random/Fortuna/test_FortunaAccumulator.py: Self-test for the FortunaAccumulator module
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-tests for Crypto.Random.Fortuna.FortunaAccumulator"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from binascii import b2a_hex
|
||||||
|
|
||||||
|
class FortunaAccumulatorTests(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
global FortunaAccumulator
|
||||||
|
from Crypto.Random.Fortuna import FortunaAccumulator
|
||||||
|
|
||||||
|
def test_FortunaPool(self):
|
||||||
|
"""FortunaAccumulator.FortunaPool"""
|
||||||
|
pool = FortunaAccumulator.FortunaPool()
|
||||||
|
self.assertEqual(0, pool.length)
|
||||||
|
self.assertEqual("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456", pool.hexdigest())
|
||||||
|
|
||||||
|
pool.append(b('abc'))
|
||||||
|
|
||||||
|
self.assertEqual(3, pool.length)
|
||||||
|
self.assertEqual("4f8b42c22dd3729b519ba6f68d2da7cc5b2d606d05daed5ad5128cc03e6c6358", pool.hexdigest())
|
||||||
|
|
||||||
|
pool.append(b("dbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))
|
||||||
|
|
||||||
|
self.assertEqual(56, pool.length)
|
||||||
|
self.assertEqual(b('0cffe17f68954dac3a84fb1458bd5ec99209449749b2b308b7cb55812f9563af'), b2a_hex(pool.digest()))
|
||||||
|
|
||||||
|
pool.reset()
|
||||||
|
|
||||||
|
self.assertEqual(0, pool.length)
|
||||||
|
|
||||||
|
pool.append(b('a') * 10**6)
|
||||||
|
|
||||||
|
self.assertEqual(10**6, pool.length)
|
||||||
|
self.assertEqual(b('80d1189477563e1b5206b2749f1afe4807e5705e8bd77887a60187a712156688'), b2a_hex(pool.digest()))
|
||||||
|
|
||||||
|
def test_which_pools(self):
|
||||||
|
"""FortunaAccumulator.which_pools"""
|
||||||
|
|
||||||
|
# which_pools(0) should fail
|
||||||
|
self.assertRaises(AssertionError, FortunaAccumulator.which_pools, 0)
|
||||||
|
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(1), [0])
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2), [0, 1])
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(3), [0])
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(4), [0, 1, 2])
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(5), [0])
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(6), [0, 1])
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(7), [0])
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(8), [0, 1, 2, 3])
|
||||||
|
for i in range(1, 32):
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**i-1), [0])
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**i), list(range(i+1)))
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**i+1), [0])
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**31), list(range(32)))
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**32), list(range(32)))
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**33), list(range(32)))
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**34), list(range(32)))
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**35), list(range(32)))
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**36), list(range(32)))
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**64), list(range(32)))
|
||||||
|
self.assertEqual(FortunaAccumulator.which_pools(2**128), list(range(32)))
|
||||||
|
|
||||||
|
def test_accumulator(self):
|
||||||
|
"""FortunaAccumulator.FortunaAccumulator"""
|
||||||
|
fa = FortunaAccumulator.FortunaAccumulator()
|
||||||
|
|
||||||
|
# This should fail, because we haven't seeded the PRNG yet
|
||||||
|
self.assertRaises(AssertionError, fa.random_data, 1)
|
||||||
|
|
||||||
|
# Spread some test data across the pools (source number 42)
|
||||||
|
# This would be horribly insecure in a real system.
|
||||||
|
for p in range(32):
|
||||||
|
fa.add_random_event(42, p, b("X") * 32)
|
||||||
|
self.assertEqual(32+2, fa.pools[p].length)
|
||||||
|
|
||||||
|
# This should still fail, because we haven't seeded the PRNG with 64 bytes yet
|
||||||
|
self.assertRaises(AssertionError, fa.random_data, 1)
|
||||||
|
|
||||||
|
# Add more data
|
||||||
|
for p in range(32):
|
||||||
|
fa.add_random_event(42, p, b("X") * 32)
|
||||||
|
self.assertEqual((32+2)*2, fa.pools[p].length)
|
||||||
|
|
||||||
|
# The underlying RandomGenerator should get seeded with Pool 0
|
||||||
|
# s = SHAd256(chr(42) + chr(32) + "X"*32 + chr(42) + chr(32) + "X"*32)
|
||||||
|
# = SHA256(h'edd546f057b389155a31c32e3975e736c1dec030ddebb137014ecbfb32ed8c6f')
|
||||||
|
# = h'aef42a5dcbddab67e8efa118e1b47fde5d697f89beb971b99e6e8e5e89fbf064'
|
||||||
|
# The counter and the key before reseeding is:
|
||||||
|
# C_0 = 0
|
||||||
|
# K_0 = "\x00" * 32
|
||||||
|
# The counter after reseeding is 1, and the new key after reseeding is
|
||||||
|
# C_1 = 1
|
||||||
|
# K_1 = SHAd256(K_0 || s)
|
||||||
|
# = SHA256(h'0eae3e401389fab86640327ac919ecfcb067359d95469e18995ca889abc119a6')
|
||||||
|
# = h'aafe9d0409fbaaafeb0a1f2ef2014a20953349d3c1c6e6e3b962953bea6184dd'
|
||||||
|
# The first block of random data, therefore, is
|
||||||
|
# r_1 = AES-256(K_1, 1)
|
||||||
|
# = AES-256(K_1, h'01000000000000000000000000000000')
|
||||||
|
# = h'b7b86bd9a27d96d7bb4add1b6b10d157'
|
||||||
|
# The second block of random data is
|
||||||
|
# r_2 = AES-256(K_1, 2)
|
||||||
|
# = AES-256(K_1, h'02000000000000000000000000000000')
|
||||||
|
# = h'2350b1c61253db2f8da233be726dc15f'
|
||||||
|
# The third and fourth blocks of random data (which become the new key) are
|
||||||
|
# r_3 = AES-256(K_1, 3)
|
||||||
|
# = AES-256(K_1, h'03000000000000000000000000000000')
|
||||||
|
# = h'f23ad749f33066ff53d307914fbf5b21'
|
||||||
|
# r_4 = AES-256(K_1, 4)
|
||||||
|
# = AES-256(K_1, h'04000000000000000000000000000000')
|
||||||
|
# = h'da9667c7e86ba247655c9490e9d94a7c'
|
||||||
|
# K_2 = r_3 || r_4
|
||||||
|
# = h'f23ad749f33066ff53d307914fbf5b21da9667c7e86ba247655c9490e9d94a7c'
|
||||||
|
# The final counter value is 5.
|
||||||
|
self.assertEqual("aef42a5dcbddab67e8efa118e1b47fde5d697f89beb971b99e6e8e5e89fbf064",
|
||||||
|
fa.pools[0].hexdigest())
|
||||||
|
self.assertEqual(None, fa.generator.key)
|
||||||
|
self.assertEqual(0, fa.generator.counter.next_value())
|
||||||
|
|
||||||
|
result = fa.random_data(32)
|
||||||
|
|
||||||
|
self.assertEqual(b("b7b86bd9a27d96d7bb4add1b6b10d157" "2350b1c61253db2f8da233be726dc15f"), b2a_hex(result))
|
||||||
|
self.assertEqual(b("f23ad749f33066ff53d307914fbf5b21da9667c7e86ba247655c9490e9d94a7c"), b2a_hex(fa.generator.key))
|
||||||
|
self.assertEqual(5, fa.generator.counter.next_value())
|
||||||
|
|
||||||
|
def test_accumulator_pool_length(self):
|
||||||
|
"""FortunaAccumulator.FortunaAccumulator minimum pool length"""
|
||||||
|
fa = FortunaAccumulator.FortunaAccumulator()
|
||||||
|
|
||||||
|
# This test case is hard-coded to assume that FortunaAccumulator.min_pool_size is 64.
|
||||||
|
self.assertEqual(fa.min_pool_size, 64)
|
||||||
|
|
||||||
|
# The PRNG should not allow us to get random data from it yet
|
||||||
|
self.assertRaises(AssertionError, fa.random_data, 1)
|
||||||
|
|
||||||
|
# Add 60 bytes, 4 at a time (2 header + 2 payload) to each of the 32 pools
|
||||||
|
for i in range(15):
|
||||||
|
for p in range(32):
|
||||||
|
# Add the bytes to the pool
|
||||||
|
fa.add_random_event(2, p, b("XX"))
|
||||||
|
|
||||||
|
# The PRNG should not allow us to get random data from it yet
|
||||||
|
self.assertRaises(AssertionError, fa.random_data, 1)
|
||||||
|
|
||||||
|
# Add 4 more bytes to pool 0
|
||||||
|
fa.add_random_event(2, 0, b("XX"))
|
||||||
|
|
||||||
|
# We should now be able to get data from the accumulator
|
||||||
|
fa.random_data(1)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.SelfTest.st_common import list_test_cases
|
||||||
|
return list_test_cases(FortunaAccumulatorTests)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
|
@ -0,0 +1,83 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Random/Fortuna/test_FortunaGenerator.py: Self-test for the FortunaGenerator module
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-tests for Crypto.Random.Fortuna.FortunaGenerator"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from binascii import b2a_hex
|
||||||
|
|
||||||
|
class FortunaGeneratorTests(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
global FortunaGenerator
|
||||||
|
from Crypto.Random.Fortuna import FortunaGenerator
|
||||||
|
|
||||||
|
def test_generator(self):
|
||||||
|
"""FortunaGenerator.AESGenerator"""
|
||||||
|
fg = FortunaGenerator.AESGenerator()
|
||||||
|
|
||||||
|
# We shouldn't be able to read data until we've seeded the generator
|
||||||
|
self.assertRaises(Exception, fg.pseudo_random_data, 1)
|
||||||
|
self.assertEqual(0, fg.counter.next_value())
|
||||||
|
|
||||||
|
# Seed the generator, which should set the key and increment the counter.
|
||||||
|
fg.reseed(b("Hello"))
|
||||||
|
self.assertEqual(b("0ea6919d4361551364242a4ba890f8f073676e82cf1a52bb880f7e496648b565"), b2a_hex(fg.key))
|
||||||
|
self.assertEqual(1, fg.counter.next_value())
|
||||||
|
|
||||||
|
# Read 2 full blocks from the generator
|
||||||
|
self.assertEqual(b("7cbe2c17684ac223d08969ee8b565616") + # counter=1
|
||||||
|
b("717661c0d2f4758bd6ba140bf3791abd"), # counter=2
|
||||||
|
b2a_hex(fg.pseudo_random_data(32)))
|
||||||
|
|
||||||
|
# Meanwhile, the generator will have re-keyed itself and incremented its counter
|
||||||
|
self.assertEqual(b("33a1bb21987859caf2bbfc5615bef56d") + # counter=3
|
||||||
|
b("e6b71ff9f37112d0c193a135160862b7"), # counter=4
|
||||||
|
b2a_hex(fg.key))
|
||||||
|
self.assertEqual(5, fg.counter.next_value())
|
||||||
|
|
||||||
|
# Read another 2 blocks from the generator
|
||||||
|
self.assertEqual(b("fd6648ba3086e919cee34904ef09a7ff") + # counter=5
|
||||||
|
b("021f77580558b8c3e9248275f23042bf"), # counter=6
|
||||||
|
b2a_hex(fg.pseudo_random_data(32)))
|
||||||
|
|
||||||
|
|
||||||
|
# Try to read more than 2**20 bytes using the internal function. This should fail.
|
||||||
|
self.assertRaises(AssertionError, fg._pseudo_random_data, 2**20+1)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.SelfTest.st_common import list_test_cases
|
||||||
|
return list_test_cases(FortunaGeneratorTests)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
|
@ -0,0 +1,55 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Random/Fortuna/test_SHAd256.py: Self-test for the SHAd256 hash function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Random.Fortuna.SHAd256"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
# This is a list of (expected_result, input[, description]) tuples.
|
||||||
|
test_data = [
|
||||||
|
# I could not find any test vectors for SHAd256, so I made these vectors by
|
||||||
|
# feeding some sample data into several plain SHA256 implementations
|
||||||
|
# (including OpenSSL, the "sha256sum" tool, and this implementation).
|
||||||
|
# This is a subset of the resulting test vectors. The complete list can be
|
||||||
|
# found at: http://www.dlitz.net/crypto/shad256-test-vectors/
|
||||||
|
('5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456',
|
||||||
|
'', "'' (empty string)"),
|
||||||
|
('4f8b42c22dd3729b519ba6f68d2da7cc5b2d606d05daed5ad5128cc03e6c6358',
|
||||||
|
'abc'),
|
||||||
|
('0cffe17f68954dac3a84fb1458bd5ec99209449749b2b308b7cb55812f9563af',
|
||||||
|
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
from Crypto.Random.Fortuna import SHAd256
|
||||||
|
from Crypto.SelfTest.Hash.common import make_hash_tests
|
||||||
|
return make_hash_tests(SHAd256, "SHAd256", test_data, 32)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
49
Lib/site-packages/Crypto/SelfTest/Random/OSRNG/__init__.py
Normal file
49
Lib/site-packages/Crypto/SelfTest/Random/OSRNG/__init__.py
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Random/OSRNG/__init__.py: Self-test for OSRNG modules
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test for Crypto.Random.OSRNG package"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
if os.name == 'nt':
|
||||||
|
from Crypto.SelfTest.Random.OSRNG import test_nt; tests += test_nt.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Random.OSRNG import test_winrandom; tests += test_winrandom.get_tests(config=config)
|
||||||
|
elif os.name == 'posix':
|
||||||
|
from Crypto.SelfTest.Random.OSRNG import test_posix; tests += test_posix.get_tests(config=config)
|
||||||
|
if hasattr(os, 'urandom'):
|
||||||
|
from Crypto.SelfTest.Random.OSRNG import test_fallback; tests += test_fallback.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Random.OSRNG import test_generic; tests += test_generic.get_tests(config=config)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
|
@ -0,0 +1,48 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Util/test_fallback.py: Self-test for the OSRNG.fallback.new() function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Random.OSRNG.fallback"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class SimpleTest(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
"""Crypto.Random.OSRNG.fallback.new()"""
|
||||||
|
# Import the OSRNG.nt module and try to use it
|
||||||
|
import Crypto.Random.OSRNG.fallback
|
||||||
|
randobj = Crypto.Random.OSRNG.fallback.new()
|
||||||
|
x = randobj.read(16)
|
||||||
|
y = randobj.read(16)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [SimpleTest()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
|
@ -0,0 +1,48 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Util/test_generic.py: Self-test for the OSRNG.new() function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Random.OSRNG"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class SimpleTest(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
"""Crypto.Random.OSRNG.new()"""
|
||||||
|
# Import the OSRNG module and try to use it
|
||||||
|
import Crypto.Random.OSRNG
|
||||||
|
randobj = Crypto.Random.OSRNG.new()
|
||||||
|
x = randobj.read(16)
|
||||||
|
y = randobj.read(16)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [SimpleTest()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
48
Lib/site-packages/Crypto/SelfTest/Random/OSRNG/test_nt.py
Normal file
48
Lib/site-packages/Crypto/SelfTest/Random/OSRNG/test_nt.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Util/test_generic.py: Self-test for the OSRNG.nt.new() function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Random.OSRNG.nt"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class SimpleTest(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
"""Crypto.Random.OSRNG.nt.new()"""
|
||||||
|
# Import the OSRNG.nt module and try to use it
|
||||||
|
import Crypto.Random.OSRNG.nt
|
||||||
|
randobj = Crypto.Random.OSRNG.nt.new()
|
||||||
|
x = randobj.read(16)
|
||||||
|
y = randobj.read(16)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [SimpleTest()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
48
Lib/site-packages/Crypto/SelfTest/Random/OSRNG/test_posix.py
Normal file
48
Lib/site-packages/Crypto/SelfTest/Random/OSRNG/test_posix.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Util/test_posix.py: Self-test for the OSRNG.posix.new() function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Random.OSRNG.posix"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class SimpleTest(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
"""Crypto.Random.OSRNG.posix.new()"""
|
||||||
|
# Import the OSRNG.nt module and try to use it
|
||||||
|
import Crypto.Random.OSRNG.posix
|
||||||
|
randobj = Crypto.Random.OSRNG.posix.new()
|
||||||
|
x = randobj.read(16)
|
||||||
|
y = randobj.read(16)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [SimpleTest()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
|
@ -0,0 +1,48 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Util/test_winrandom.py: Self-test for the winrandom module
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Random.OSRNG.winrandom"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class SimpleTest(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
"""Crypto.Random.OSRNG.winrandom"""
|
||||||
|
# Import the winrandom module and try to use it
|
||||||
|
from Crypto.Random.OSRNG import winrandom
|
||||||
|
randobj = winrandom.new()
|
||||||
|
x = randobj.get_bytes(16)
|
||||||
|
y = randobj.get_bytes(16)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [SimpleTest()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
43
Lib/site-packages/Crypto/SelfTest/Random/__init__.py
Normal file
43
Lib/site-packages/Crypto/SelfTest/Random/__init__.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Random/__init__.py: Self-test for random number generation modules
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test for random number generators"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
from Crypto.SelfTest.Random import Fortuna; tests += Fortuna.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Random import OSRNG; tests += OSRNG.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Random import test_random; tests += test_random.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Random import test_rpoolcompat; tests += test_rpoolcompat.get_tests(config=config)
|
||||||
|
from Crypto.SelfTest.Random import test__UserFriendlyRNG; tests += test__UserFriendlyRNG.get_tests(config=config)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
|
@ -0,0 +1,171 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Self-tests for the user-friendly Crypto.Random interface
|
||||||
|
#
|
||||||
|
# Written in 2013 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for generic Crypto.Random stuff """
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import binascii
|
||||||
|
import pprint
|
||||||
|
import unittest
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
import multiprocessing
|
||||||
|
except ImportError:
|
||||||
|
multiprocessing = None
|
||||||
|
|
||||||
|
import Crypto.Random._UserFriendlyRNG
|
||||||
|
import Crypto.Random.random
|
||||||
|
|
||||||
|
class RNGForkTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def _get_reseed_count(self):
|
||||||
|
"""
|
||||||
|
Get `FortunaAccumulator.reseed_count`, the global count of the
|
||||||
|
number of times that the PRNG has been reseeded.
|
||||||
|
"""
|
||||||
|
rng_singleton = Crypto.Random._UserFriendlyRNG._get_singleton()
|
||||||
|
rng_singleton._lock.acquire()
|
||||||
|
try:
|
||||||
|
return rng_singleton._fa.reseed_count
|
||||||
|
finally:
|
||||||
|
rng_singleton._lock.release()
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
# Regression test for CVE-2013-1445. We had a bug where, under the
|
||||||
|
# right conditions, two processes might see the same random sequence.
|
||||||
|
|
||||||
|
if sys.platform.startswith('win'): # windows can't fork
|
||||||
|
assert not hasattr(os, 'fork') # ... right?
|
||||||
|
return
|
||||||
|
|
||||||
|
# Wait 150 ms so that we don't trigger the rate-limit prematurely.
|
||||||
|
time.sleep(0.15)
|
||||||
|
|
||||||
|
reseed_count_before = self._get_reseed_count()
|
||||||
|
|
||||||
|
# One or both of these calls together should trigger a reseed right here.
|
||||||
|
Crypto.Random._UserFriendlyRNG._get_singleton().reinit()
|
||||||
|
Crypto.Random.get_random_bytes(1)
|
||||||
|
|
||||||
|
reseed_count_after = self._get_reseed_count()
|
||||||
|
self.assertNotEqual(reseed_count_before, reseed_count_after) # sanity check: test should reseed parent before forking
|
||||||
|
|
||||||
|
rfiles = []
|
||||||
|
for i in range(10):
|
||||||
|
rfd, wfd = os.pipe()
|
||||||
|
if os.fork() == 0:
|
||||||
|
# child
|
||||||
|
os.close(rfd)
|
||||||
|
f = os.fdopen(wfd, "wb")
|
||||||
|
|
||||||
|
Crypto.Random.atfork()
|
||||||
|
|
||||||
|
data = Crypto.Random.get_random_bytes(16)
|
||||||
|
|
||||||
|
f.write(data)
|
||||||
|
f.close()
|
||||||
|
os._exit(0)
|
||||||
|
# parent
|
||||||
|
os.close(wfd)
|
||||||
|
rfiles.append(os.fdopen(rfd, "rb"))
|
||||||
|
|
||||||
|
results = []
|
||||||
|
results_dict = {}
|
||||||
|
for f in rfiles:
|
||||||
|
data = binascii.hexlify(f.read())
|
||||||
|
results.append(data)
|
||||||
|
results_dict[data] = 1
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
if len(results) != len(list(results_dict.keys())):
|
||||||
|
raise AssertionError("RNG output duplicated across fork():\n%s" %
|
||||||
|
(pprint.pformat(results)))
|
||||||
|
|
||||||
|
|
||||||
|
# For RNGMultiprocessingForkTest
|
||||||
|
def _task_main(q):
|
||||||
|
a = Crypto.Random.get_random_bytes(16)
|
||||||
|
time.sleep(0.1) # wait 100 ms
|
||||||
|
b = Crypto.Random.get_random_bytes(16)
|
||||||
|
q.put(binascii.b2a_hex(a))
|
||||||
|
q.put(binascii.b2a_hex(b))
|
||||||
|
q.put(None) # Wait for acknowledgment
|
||||||
|
|
||||||
|
|
||||||
|
class RNGMultiprocessingForkTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
# Another regression test for CVE-2013-1445. This is basically the
|
||||||
|
# same as RNGForkTest, but less compatible with old versions of Python,
|
||||||
|
# and a little easier to read.
|
||||||
|
|
||||||
|
n_procs = 5
|
||||||
|
manager = multiprocessing.Manager()
|
||||||
|
queues = [manager.Queue(1) for i in range(n_procs)]
|
||||||
|
|
||||||
|
# Reseed the pool
|
||||||
|
time.sleep(0.15)
|
||||||
|
Crypto.Random._UserFriendlyRNG._get_singleton().reinit()
|
||||||
|
Crypto.Random.get_random_bytes(1)
|
||||||
|
|
||||||
|
# Start the child processes
|
||||||
|
pool = multiprocessing.Pool(processes=n_procs, initializer=Crypto.Random.atfork)
|
||||||
|
map_result = pool.map_async(_task_main, queues)
|
||||||
|
|
||||||
|
# Get the results, ensuring that no pool processes are reused.
|
||||||
|
aa = [queues[i].get(30) for i in range(n_procs)]
|
||||||
|
bb = [queues[i].get(30) for i in range(n_procs)]
|
||||||
|
res = list(zip(aa, bb))
|
||||||
|
|
||||||
|
# Shut down the pool
|
||||||
|
map_result.get(30)
|
||||||
|
pool.close()
|
||||||
|
pool.join()
|
||||||
|
|
||||||
|
# Check that the results are unique
|
||||||
|
if len(set(aa)) != len(aa) or len(set(res)) != len(res):
|
||||||
|
raise AssertionError("RNG output duplicated across fork():\n%s" %
|
||||||
|
(pprint.pformat(res),))
|
||||||
|
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
tests += [RNGForkTest()]
|
||||||
|
if multiprocessing is not None:
|
||||||
|
tests += [RNGMultiprocessingForkTest()]
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
171
Lib/site-packages/Crypto/SelfTest/Random/test_random.py
Normal file
171
Lib/site-packages/Crypto/SelfTest/Random/test_random.py
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Util/test_generic.py: Self-test for the Crypto.Random.new() function
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test suite for Crypto.Random.new()"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||||
|
from Crypto.Util.py21compat import *
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
class SimpleTest(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
"""Crypto.Random.new()"""
|
||||||
|
# Import the Random module and try to use it
|
||||||
|
from Crypto import Random
|
||||||
|
randobj = Random.new()
|
||||||
|
x = randobj.read(16)
|
||||||
|
y = randobj.read(16)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
z = Random.get_random_bytes(16)
|
||||||
|
self.assertNotEqual(x, z)
|
||||||
|
self.assertNotEqual(y, z)
|
||||||
|
# Test the Random.random module, which
|
||||||
|
# implements a subset of Python's random API
|
||||||
|
# Not implemented:
|
||||||
|
# seed(), getstate(), setstate(), jumpahead()
|
||||||
|
# random(), uniform(), triangular(), betavariate()
|
||||||
|
# expovariate(), gammavariate(), gauss(),
|
||||||
|
# longnormvariate(), normalvariate(),
|
||||||
|
# vonmisesvariate(), paretovariate()
|
||||||
|
# weibullvariate()
|
||||||
|
# WichmannHill(), whseed(), SystemRandom()
|
||||||
|
from Crypto.Random import random
|
||||||
|
x = random.getrandbits(16*8)
|
||||||
|
y = random.getrandbits(16*8)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
# Test randrange
|
||||||
|
if x>y:
|
||||||
|
start = y
|
||||||
|
stop = x
|
||||||
|
else:
|
||||||
|
start = x
|
||||||
|
stop = y
|
||||||
|
for step in range(1,10):
|
||||||
|
x = random.randrange(start,stop,step)
|
||||||
|
y = random.randrange(start,stop,step)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
self.assertEqual(start <= x < stop, True)
|
||||||
|
self.assertEqual(start <= y < stop, True)
|
||||||
|
self.assertEqual((x - start) % step, 0)
|
||||||
|
self.assertEqual((y - start) % step, 0)
|
||||||
|
for i in range(10):
|
||||||
|
self.assertEqual(random.randrange(1,2), 1)
|
||||||
|
self.assertRaises(ValueError, random.randrange, start, start)
|
||||||
|
self.assertRaises(ValueError, random.randrange, stop, start, step)
|
||||||
|
self.assertRaises(TypeError, random.randrange, start, stop, step, step)
|
||||||
|
self.assertRaises(TypeError, random.randrange, start, stop, "1")
|
||||||
|
self.assertRaises(TypeError, random.randrange, "1", stop, step)
|
||||||
|
self.assertRaises(TypeError, random.randrange, 1, "2", step)
|
||||||
|
self.assertRaises(ValueError, random.randrange, start, stop, 0)
|
||||||
|
# Test randint
|
||||||
|
x = random.randint(start,stop)
|
||||||
|
y = random.randint(start,stop)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
self.assertEqual(start <= x <= stop, True)
|
||||||
|
self.assertEqual(start <= y <= stop, True)
|
||||||
|
for i in range(10):
|
||||||
|
self.assertEqual(random.randint(1,1), 1)
|
||||||
|
self.assertRaises(ValueError, random.randint, stop, start)
|
||||||
|
self.assertRaises(TypeError, random.randint, start, stop, step)
|
||||||
|
self.assertRaises(TypeError, random.randint, "1", stop)
|
||||||
|
self.assertRaises(TypeError, random.randint, 1, "2")
|
||||||
|
# Test choice
|
||||||
|
seq = list(range(10000))
|
||||||
|
x = random.choice(seq)
|
||||||
|
y = random.choice(seq)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
self.assertEqual(x in seq, True)
|
||||||
|
self.assertEqual(y in seq, True)
|
||||||
|
for i in range(10):
|
||||||
|
self.assertEqual(random.choice((1,2,3)) in (1,2,3), True)
|
||||||
|
self.assertEqual(random.choice([1,2,3]) in [1,2,3], True)
|
||||||
|
if sys.version_info[0] is 3:
|
||||||
|
self.assertEqual(random.choice(bytearray(b('123'))) in bytearray(b('123')), True)
|
||||||
|
self.assertEqual(1, random.choice([1]))
|
||||||
|
self.assertRaises(IndexError, random.choice, [])
|
||||||
|
self.assertRaises(TypeError, random.choice, 1)
|
||||||
|
# Test shuffle. Lacks random parameter to specify function.
|
||||||
|
# Make copies of seq
|
||||||
|
seq = list(range(500))
|
||||||
|
x = list(seq)
|
||||||
|
y = list(seq)
|
||||||
|
random.shuffle(x)
|
||||||
|
random.shuffle(y)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
self.assertEqual(len(seq), len(x))
|
||||||
|
self.assertEqual(len(seq), len(y))
|
||||||
|
for i in range(len(seq)):
|
||||||
|
self.assertEqual(x[i] in seq, True)
|
||||||
|
self.assertEqual(y[i] in seq, True)
|
||||||
|
self.assertEqual(seq[i] in x, True)
|
||||||
|
self.assertEqual(seq[i] in y, True)
|
||||||
|
z = [1]
|
||||||
|
random.shuffle(z)
|
||||||
|
self.assertEqual(z, [1])
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
z = bytearray(b('12'))
|
||||||
|
random.shuffle(z)
|
||||||
|
self.assertEqual(b('1') in z, True)
|
||||||
|
self.assertRaises(TypeError, random.shuffle, b('12'))
|
||||||
|
self.assertRaises(TypeError, random.shuffle, 1)
|
||||||
|
self.assertRaises(TypeError, random.shuffle, "1")
|
||||||
|
self.assertRaises(TypeError, random.shuffle, (1,2))
|
||||||
|
# 2to3 wraps a list() around it, alas - but I want to shoot
|
||||||
|
# myself in the foot here! :D
|
||||||
|
# if sys.version_info[0] == 3:
|
||||||
|
# self.assertRaises(TypeError, random.shuffle, range(3))
|
||||||
|
# Test sample
|
||||||
|
x = random.sample(seq, 20)
|
||||||
|
y = random.sample(seq, 20)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
for i in range(20):
|
||||||
|
self.assertEqual(x[i] in seq, True)
|
||||||
|
self.assertEqual(y[i] in seq, True)
|
||||||
|
z = random.sample([1], 1)
|
||||||
|
self.assertEqual(z, [1])
|
||||||
|
z = random.sample((1,2,3), 1)
|
||||||
|
self.assertEqual(z[0] in (1,2,3), True)
|
||||||
|
z = random.sample("123", 1)
|
||||||
|
self.assertEqual(z[0] in "123", True)
|
||||||
|
z = random.sample(list(range(3)), 1)
|
||||||
|
self.assertEqual(z[0] in range(3), True)
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
z = random.sample(b("123"), 1)
|
||||||
|
self.assertEqual(z[0] in b("123"), True)
|
||||||
|
z = random.sample(bytearray(b("123")), 1)
|
||||||
|
self.assertEqual(z[0] in bytearray(b("123")), True)
|
||||||
|
self.assertRaises(TypeError, random.sample, 1)
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [SimpleTest()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
55
Lib/site-packages/Crypto/SelfTest/Random/test_rpoolcompat.py
Normal file
55
Lib/site-packages/Crypto/SelfTest/Random/test_rpoolcompat.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Util/test_winrandom.py: Self-test for the winrandom module
|
||||||
|
#
|
||||||
|
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test for the Crypto.Util.randpool.RandomPool wrapper class"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class SimpleTest(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
"""Crypto.Util.randpool.RandomPool"""
|
||||||
|
# Import the winrandom module and try to use it
|
||||||
|
from Crypto.Util.randpool import RandomPool
|
||||||
|
sys.stderr.write("SelfTest: You can ignore the RandomPool_DeprecationWarning that follows.\n")
|
||||||
|
rpool = RandomPool()
|
||||||
|
x = rpool.get_bytes(16)
|
||||||
|
y = rpool.get_bytes(16)
|
||||||
|
self.assertNotEqual(x, y)
|
||||||
|
self.assertNotEqual(rpool.entropy, 0)
|
||||||
|
|
||||||
|
rpool.randomize()
|
||||||
|
rpool.stir('foo')
|
||||||
|
rpool.add_event('foo')
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
return [SimpleTest()]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
40
Lib/site-packages/Crypto/SelfTest/Signature/__init__.py
Normal file
40
Lib/site-packages/Crypto/SelfTest/Signature/__init__.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# SelfTest/Signature/__init__.py: Self-test for signature modules
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# The contents of this file are dedicated to the public domain. To
|
||||||
|
# the extent that dedication to the public domain is not available,
|
||||||
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||||
|
# non-exclusive license to exercise all rights associated with the
|
||||||
|
# contents of this file for any purpose whatsoever.
|
||||||
|
# No rights are reserved.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""Self-test for signature modules"""
|
||||||
|
|
||||||
|
__revision__ = "$Id$"
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
def get_tests(config={}):
|
||||||
|
tests = []
|
||||||
|
from . import test_pkcs1_15; tests += test_pkcs1_15.get_tests(config=config)
|
||||||
|
from . import test_pkcs1_pss; tests += test_pkcs1_pss.get_tests(config=config)
|
||||||
|
return tests
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import unittest
|
||||||
|
suite = lambda: unittest.TestSuite(get_tests())
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:set ts=4 sw=4 sts=4 expandtab:
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue