Move test vectors in a separate package

This commit is contained in:
Helder Eijs 2021-01-02 00:52:11 +01:00
parent 6ccdb9a200
commit eda4f65718
363 changed files with 1198 additions and 1021 deletions

View file

@ -60,8 +60,13 @@ jobs:
if: matrix.os == 'windows-latest' && matrix.python-version == '2.7'
run: choco install vcpython27
- name: Install dependencies
run: |
pip install pycryptodome-test-vectors
- name: Test
run: python -bb setup.py test
run: |
python -bb setup.py test
mypy:
runs-on: ubuntu-latest
@ -73,7 +78,7 @@ jobs:
python-version: 3.9
- name: Install dependencies
run: |
pip install mypy
pip install mypy pycryptodome-test-vectors
- name: Test
run: |
mypy lib/

View file

@ -12,7 +12,8 @@ PyCryptodome can be used as:
In this case, all modules are installed under the ``Crypto`` package.
You can test everything is right with::
python -m Crypto.SelfTest
pip install pycryptodome-test-vectors
python -m Crypto.SelfTest
One must avoid having both PyCrypto and PyCryptodome installed
at the same time, as they will interfere with each other.
@ -27,6 +28,7 @@ PyCryptodome can be used as:
You can test everything is right with::
pip install pycryptodome-test-vectors
python -m Cryptodome.SelfTest
In this case, all modules are installed under the ``Cryptodome`` package.
@ -47,18 +49,21 @@ For Python 2.x::
$ sudo apt-get install build-essential python-dev
$ pip install pycryptodomex
$ pip install pycryptodome-test-vectors
$ python -m Cryptodome.SelfTest
For Python 3.x::
$ sudo apt-get install build-essential python3-dev
$ pip install pycryptodomex
$ pip install pycryptodome-test-vectors
$ python3 -m Cryptodome.SelfTest
For PyPy::
$ sudo apt-get install build-essential pypy-dev
$ pip install pycryptodomex
$ pip install pycryptodome-test-vectors
$ pypy -m Cryptodome.SelfTest
Compiling in Linux Fedora
@ -72,18 +77,21 @@ For Python 2.x::
$ sudo yum install gcc gmp python-devel
$ pip install pycryptodomex
$ pip install pycryptodome-test-vectors
$ python -m Cryptodome.SelfTest
For Python 3.x::
$ sudo yum install gcc gmp python3-devel
$ pip install pycryptodomex
$ pip install pycryptodome-test-vectors
$ python3 -m Cryptodome.SelfTest
For PyPy::
$ sudo yum install gcc gmp pypy-devel
$ pip install pycryptodomex
$ pip install pycryptodome-test-vectors
$ pypy -m Cryptodome.SelfTest
@ -134,6 +142,7 @@ components freely made available by Microsoft.
#. To make sure everything work fine, run the test suite::
> pip install pycryptodome-test-vectors
> python -m Cryptodome.SelfTest
Windows (from sources, Python 3.3 and 3.4)
@ -183,6 +192,7 @@ components freely made available by Microsoft.
#. To make sure everything work fine, run the test suite::
> pip install pycryptodome-test-vectors
> python -m Cryptodome.SelfTest
Windows (from sources, Python 3.5 and newer)
@ -206,6 +216,7 @@ components freely made available by Microsoft.
#. To make sure everything work fine, run the test suite::
> pip install pycryptodome-test-vectors
> python -m Cryptodome.SelfTest
Documentation

View file

@ -67,208 +67,3 @@ The OCB cipher mode is patented in the US under patent numbers 7,949,129 and
8,321,675. The directory Doc/ocb contains three free licenses for implementors
and users. As a general statement, OCB can be freely used for software not meant
for military purposes. Contact your attorney for further information.
Apache 2.0 license (Wycheproof)
===============================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -31,12 +31,13 @@
import unittest
from binascii import unhexlify
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Util.py3compat import tobytes, is_string
from Crypto.Cipher import AES, DES3, DES
from Crypto.Hash import SHAKE128
def get_tag_random(tag, length):
return SHAKE128.new(data=tobytes(tag)).read(length)
@ -311,11 +312,13 @@ class CbcTests(BlockChainingTests):
class NistBlockChainingVectors(unittest.TestCase):
def _do_kat_aes_test(self, file_name):
test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
file_name,
"AES KAT",
{ "count" : lambda x: int(x) } )
assert(test_vectors)
test_vectors = load_test_vectors(("Cipher", "AES"),
file_name,
"AES CBC KAT",
{ "count" : lambda x: int(x) } )
if test_vectors is None:
return
direction = None
for tv in test_vectors:
@ -337,11 +340,13 @@ class NistBlockChainingVectors(unittest.TestCase):
# See Section 6.4.2 in AESAVS
def _do_mct_aes_test(self, file_name):
test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
file_name,
"AES Montecarlo",
{ "count" : lambda x: int(x) } )
assert(test_vectors)
test_vectors = load_test_vectors(("Cipher", "AES"),
file_name,
"AES CBC Montecarlo",
{ "count" : lambda x: int(x) } )
if test_vectors is None:
return
direction = None
for tv in test_vectors:
@ -370,11 +375,13 @@ class NistBlockChainingVectors(unittest.TestCase):
assert False
def _do_tdes_test(self, file_name):
test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "TDES"),
file_name,
"TDES CBC KAT",
{ "count" : lambda x: int(x) } )
assert(test_vectors)
test_vectors = load_test_vectors(("Cipher", "TDES"),
file_name,
"TDES CBC KAT",
{ "count" : lambda x: int(x) } )
if test_vectors is None:
return
direction = None
for tv in test_vectors:

View file

@ -28,18 +28,18 @@
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import json
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_test_vectors_wycheproof
from Crypto.Util.py3compat import tobytes, bchr
from Crypto.Cipher import AES
from Crypto.Hash import SHAKE128
from Crypto.Util._file_system import pycryptodome_filename
from Crypto.Util.strxor import strxor
def get_tag_random(tag, length):
return SHAKE128.new(data=tobytes(tag)).read(length)
@ -830,27 +830,14 @@ class TestVectorsWycheproof(unittest.TestCase):
self._id = "None"
def setUp(self):
comps = "Crypto.SelfTest.Cipher.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, "aes_ccm_test.json"), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
self.tv = []
def filter_tag(group):
return group['tagSize'] // 8
for group in tv_tree['testGroups']:
tag_size = group['tagSize'] // 8
for test in group['tests']:
tv = TestVector()
tv.tag_size = tag_size
tv.id = test['tcId']
tv.comment = test['comment']
for attr in 'key', 'iv', 'aad', 'msg', 'ct', 'tag':
setattr(tv, attr, unhexlify(test[attr]))
tv.valid = test['result'] != "invalid"
tv.warning = test['result'] == "acceptable"
self.tv.append(tv)
self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
"aes_ccm_test.json",
"Wycheproof AES CCM",
group_tag={'tag_size': filter_tag})
def shortDescription(self):
return self._id
@ -865,7 +852,7 @@ class TestVectorsWycheproof(unittest.TestCase):
try:
cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size,
**self._extra_params)
**self._extra_params)
except ValueError as e:
if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e):
assert not tv.valid
@ -887,7 +874,7 @@ class TestVectorsWycheproof(unittest.TestCase):
try:
cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size,
**self._extra_params)
**self._extra_params)
except ValueError as e:
if len(tv.iv) not in range(7, 13 + 1, 2) and "Length of parameter 'nonce'" in str(e):
assert not tv.valid
@ -912,7 +899,7 @@ class TestVectorsWycheproof(unittest.TestCase):
if len(tv.iv) not in range(7, 13 + 1, 2) or len(tv.ct) == 0:
return
cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size,
**self._extra_params)
**self._extra_params)
cipher.update(tv.aad)
ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01")
self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag)
@ -932,11 +919,12 @@ def get_tests(config={}):
tests += list_test_cases(CcmTests)
tests += list_test_cases(CcmFSMTests)
tests += [TestVectors()]
tests += [ TestVectorsWycheproof(wycheproof_warnings) ]
tests += [TestVectorsWycheproof(wycheproof_warnings)]
return tests
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
def suite():
unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View file

@ -31,18 +31,19 @@
import unittest
from binascii import unhexlify
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Util.py3compat import tobytes, is_string
from Crypto.Cipher import AES, DES3, DES
from Crypto.Hash import SHAKE128
from Crypto.SelfTest.Cipher.test_CBC import BlockChainingTests
def get_tag_random(tag, length):
return SHAKE128.new(data=tobytes(tag)).read(length)
from Crypto.SelfTest.Cipher.test_CBC import BlockChainingTests
class CfbTests(BlockChainingTests):
aes_mode = AES.MODE_CFB
@ -101,11 +102,13 @@ class CfbTests(BlockChainingTests):
class NistCfbVectors(unittest.TestCase):
def _do_kat_aes_test(self, file_name, segment_size):
test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
file_name,
"AES CFB%d KAT" % segment_size,
{ "count" : lambda x: int(x) } )
assert(test_vectors)
test_vectors = load_test_vectors(("Cipher", "AES"),
file_name,
"AES CFB%d KAT" % segment_size,
{ "count" : lambda x: int(x) } )
if test_vectors is None:
return
direction = None
for tv in test_vectors:
@ -127,11 +130,14 @@ class NistCfbVectors(unittest.TestCase):
# See Section 6.4.5 in AESAVS
def _do_mct_aes_test(self, file_name, segment_size):
test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
file_name,
"AES CFB%d Montecarlo" % segment_size,
{ "count" : lambda x: int(x) } )
assert(test_vectors)
test_vectors = load_test_vectors(("Cipher", "AES"),
file_name,
"AES CFB%d Montecarlo" % segment_size,
{ "count" : lambda x: int(x) } )
if test_vectors is None:
return
assert(segment_size in (8, 128))
direction = None
@ -175,11 +181,13 @@ class NistCfbVectors(unittest.TestCase):
assert False
def _do_tdes_test(self, file_name, segment_size):
test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "TDES"),
file_name,
"AES CFB%d KAT" % segment_size,
{ "count" : lambda x: int(x) } )
assert(test_vectors)
test_vectors = load_test_vectors(("Cipher", "TDES"),
file_name,
"TDES CFB%d KAT" % segment_size,
{ "count" : lambda x: int(x) } )
if test_vectors is None:
return
direction = None
for tv in test_vectors:

View file

@ -28,11 +28,11 @@
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import json
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_test_vectors_wycheproof
from Crypto.Util.py3compat import tobytes
from Crypto.Cipher import ChaCha20_Poly1305
from Crypto.Hash import SHAKE128
@ -625,29 +625,18 @@ class TestVectorsWycheproof(unittest.TestCase):
self._id = "None"
def load_tests(self, filename):
comps = "Crypto.SelfTest.Cipher.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, filename), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
result = []
def filter_tag(group):
return group['tagSize'] // 8
for group in tv_tree['testGroups']:
tag_size = group['tagSize'] // 8
for test in group['tests']:
tv = TestVector()
tv.tag_size = tag_size
def filter_algo(root):
return root['algorithm']
tv.id = test['tcId']
tv.comment = test['comment']
for attr in 'key', 'iv', 'aad', 'msg', 'ct', 'tag':
setattr(tv, attr, unhexlify(test[attr]))
tv.valid = test['result'] != "invalid"
tv.warning = test['result'] == "acceptable"
tv.algo = tv_tree['algorithm']
result.append(tv)
result = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
filename,
"Wycheproof ChaCha20-Poly1305",
root_tag={'algo': filter_algo},
group_tag={'tag_size': filter_tag})
return result
def setUp(self):

View file

@ -31,7 +31,7 @@ from Crypto.Cipher import DES3
from Crypto.Util.strxor import strxor_c
from Crypto.Util.py3compat import bchr, tostr
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.SelfTest.st_common import list_test_cases
# This is a list of (plaintext, ciphertext, key, description) tuples.
@ -56,11 +56,13 @@ test_data = [
nist_tdes_mmt_files = ("TECBMMT2.rsp", "TECBMMT3.rsp")
for tdes_file in nist_tdes_mmt_files:
test_vectors = load_tests(("Crypto", "SelfTest", "Cipher", "test_vectors", "TDES"),
tdes_file,
"TDES ECB (%s)" % tdes_file,
{ "count" : lambda x: int(x) } )
assert(test_vectors)
test_vectors = load_test_vectors(
("Cipher", "TDES"),
tdes_file,
"TDES ECB (%s)" % tdes_file,
{"count": lambda x: int(x)}) or []
for index, tv in enumerate(test_vectors):
# The test vector file contains some directive lines
@ -107,7 +109,7 @@ class CheckParity(unittest.TestCase):
# K1 == K2 (with different parity)
self.assertRaises(ValueError, DES3.adjust_key_parity,
sub_key1 + strxor_c(sub_key1, 1) + sub_key2)
sub_key1 + strxor_c(sub_key1, 1) + sub_key2)
class DegenerateToDESTest(unittest.TestCase):
@ -128,7 +130,7 @@ class DegenerateToDESTest(unittest.TestCase):
# K1 == K2 == K3
self.assertRaises(ValueError, DES3.new,
sub_key1 *3,
sub_key1 * 3,
DES3.MODE_ECB)
# K2 == K3 (parity is ignored)
@ -184,7 +186,10 @@ def get_tests(config={}):
if __name__ == '__main__':
import unittest
suite = lambda: unittest.TestSuite(get_tests())
def suite():
unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')
# vim:set ts=4 sw=4 sts=4 expandtab:

View file

@ -28,16 +28,15 @@
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import json
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_test_vectors_wycheproof
from Crypto.Util.py3compat import tobytes, bchr
from Crypto.Cipher import AES, DES3
from Crypto.Hash import SHAKE128
from Crypto.Util._file_system import pycryptodome_filename
from Crypto.Util.strxor import strxor
@ -653,27 +652,14 @@ class TestVectorsWycheproof(unittest.TestCase):
self._id = "None"
def setUp(self):
comps = "Crypto.SelfTest.Cipher.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, "aes_eax_test.json"), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
self.tv = []
def filter_tag(group):
return group['tagSize'] // 8
for group in tv_tree['testGroups']:
tag_size = group['tagSize'] // 8
for test in group['tests']:
tv = TestVector()
tv.tag_size = tag_size
tv.id = test['tcId']
tv.comment = test['comment']
for attr in 'key', 'iv', 'aad', 'msg', 'ct', 'tag':
setattr(tv, attr, unhexlify(test[attr]))
tv.valid = test['result'] != "invalid"
tv.warning = test['result'] == "acceptable"
self.tv.append(tv)
self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
"aes_eax_test.json",
"Wycheproof EAX",
group_tag={'tag_size': filter_tag})
def shortDescription(self):
return self._id

View file

@ -30,18 +30,16 @@
from __future__ import print_function
import json
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof
from Crypto.Util.py3compat import tobytes, bchr
from Crypto.Cipher import AES
from Crypto.Hash import SHAKE128, SHA256
from Crypto.Util._file_system import pycryptodome_filename
from Crypto.Util.strxor import strxor
@ -561,7 +559,7 @@ class TestVectors(unittest.TestCase):
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
'42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' +
'42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' +
'21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091',
'5bc94fbc3221a5db94fae95ae7121a47',
'feffe9928665731c6d6a8f9467308308',
@ -586,7 +584,7 @@ class TestVectors(unittest.TestCase):
'619cc5aefffe0bfa462af43c1699d050',
'feffe9928665731c6d6a8f9467308308',
'9313225df88406e555909c5aff5269aa' +
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' +
'16aedbf5a0de6a57a637b39b'
),
(
@ -701,7 +699,7 @@ class TestVectors(unittest.TestCase):
'a44a8266ee1c8eb0c8b5d4cf5ae9f19a',
'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308',
'9313225df88406e555909c5aff5269aa' +
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' +
'16aedbf5a0de6a57a637b39b'
)
]
@ -767,13 +765,13 @@ class TestVectorsGueronKrasnov(unittest.TestCase):
self.assertEqual(digest, digest2)
class NISTTestVectorsGCM(unittest.TestCase):
def __init__(self, a):
self.use_clmul = True
unittest.TestCase.__init__(self, a)
class NISTTestVectorsGCM_no_clmul(unittest.TestCase):
def __init__(self, a):
@ -781,17 +779,17 @@ class NISTTestVectorsGCM_no_clmul(unittest.TestCase):
unittest.TestCase.__init__(self, a)
test_vectors_nist = load_tests(
("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
test_vectors_nist = load_test_vectors(
("Cipher", "AES"),
"gcmDecrypt128.rsp",
"GCM decrypt",
{ "count" : lambda x: int(x) })
{"count": lambda x: int(x)}) or []
test_vectors_nist += load_tests(
("Crypto", "SelfTest", "Cipher", "test_vectors", "AES"),
test_vectors_nist += load_test_vectors(
("Cipher", "AES"),
"gcmEncryptExtIV128.rsp",
"GCM encrypt",
{ "count" : lambda x: int(x) })
{"count": lambda x: int(x)}) or []
for idx, tv in enumerate(test_vectors_nist):
@ -801,16 +799,16 @@ for idx, tv in enumerate(test_vectors_nist):
def single_test(self, tv=tv):
self.description = tv.desc
cipher = AES.new(tv.key, AES.MODE_GCM, nonce=tv.iv,
self.description = tv.desc
cipher = AES.new(tv.key, AES.MODE_GCM, nonce=tv.iv,
mac_len=len(tv.tag), use_clmul=self.use_clmul)
cipher.update(tv.aad)
if "FAIL" in tv.others:
self.assertRaises(ValueError, cipher.decrypt_and_verify,
cipher.update(tv.aad)
if "FAIL" in tv.others:
self.assertRaises(ValueError, cipher.decrypt_and_verify,
tv.ct, tv.tag)
else:
pt = cipher.decrypt_and_verify(tv.ct, tv.tag)
self.assertEqual(pt, tv.pt)
else:
pt = cipher.decrypt_and_verify(tv.ct, tv.tag)
self.assertEqual(pt, tv.pt)
setattr(NISTTestVectorsGCM, "test_%d" % idx, single_test)
setattr(NISTTestVectorsGCM_no_clmul, "test_%d" % idx, single_test)
@ -825,27 +823,14 @@ class TestVectorsWycheproof(unittest.TestCase):
self._id = "None"
def setUp(self):
comps = "Crypto.SelfTest.Cipher.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, "aes_gcm_test.json"), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
self.tv = []
def filter_tag(group):
return group['tagSize'] // 8
for group in tv_tree['testGroups']:
tag_size = group['tagSize'] // 8
for test in group['tests']:
tv = TestVector()
tv.tag_size = tag_size
tv.id = test['tcId']
tv.comment = test['comment']
for attr in 'key', 'iv', 'aad', 'msg', 'ct', 'tag':
setattr(tv, attr, unhexlify(test[attr]))
tv.valid = test['result'] != "invalid"
tv.warning = test['result'] == "acceptable"
self.tv.append(tv)
self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
"aes_gcm_test.json",
"Wycheproof GCM",
group_tag={'tag_size': filter_tag})
def shortDescription(self):
return self._id
@ -860,7 +845,7 @@ class TestVectorsWycheproof(unittest.TestCase):
try:
cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size,
**self._extra_params)
**self._extra_params)
except ValueError as e:
if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e):
return
@ -878,7 +863,7 @@ class TestVectorsWycheproof(unittest.TestCase):
try:
cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size,
**self._extra_params)
**self._extra_params)
except ValueError as e:
if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e):
return
@ -899,7 +884,7 @@ class TestVectorsWycheproof(unittest.TestCase):
if len(tv.iv) == 0 or len(tv.ct) < 1:
return
cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size,
**self._extra_params)
**self._extra_params)
cipher.update(tv.aad)
ct_corrupt = strxor(tv.ct, b"\x00" * (len(tv.ct) - 1) + b"\x01")
self.assertRaises(ValueError, cipher.decrypt_and_verify, ct_corrupt, tv.tag)
@ -941,16 +926,16 @@ def get_tests(config={}):
tests = []
tests += list_test_cases(GcmTests)
tests += list_test_cases(GcmFSMTests)
tests += [ TestVectors() ]
tests += [ TestVectorsWycheproof(wycheproof_warnings) ]
tests += [TestVectors()]
tests += [TestVectorsWycheproof(wycheproof_warnings)]
tests += list_test_cases(TestVectorsGueronKrasnov)
tests += [ TestVariableLength() ]
tests += [TestVariableLength()]
if config.get('slow_tests'):
tests += list_test_cases(NISTTestVectorsGCM)
if _cpu_features.have_clmul():
tests += [ TestVectorsWycheproof(wycheproof_warnings, use_clmul=False) ]
tests += [ TestVariableLength(use_clmul = False) ]
tests += [TestVectorsWycheproof(wycheproof_warnings, use_clmul=False)]
tests += [TestVariableLength(use_clmul=False)]
if config.get('slow_tests'):
tests += list_test_cases(NISTTestVectorsGCM_no_clmul)
else:
@ -960,5 +945,6 @@ def get_tests(config={}):
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
def suite():
unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View file

@ -35,6 +35,7 @@ from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Util.py3compat import tobytes
from Crypto.Cipher import AES, DES3, DES
from Crypto.Hash import SHAKE128
from Crypto.SelfTest.loader import load_test_vectors_wycheproof
def get_tag_random(tag, length):
return SHAKE128.new(data=tobytes(tag)).read(length)

View file

@ -33,11 +33,12 @@ import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_test_vectors_wycheproof
from Crypto.Util.py3compat import tobytes, bchr
from Crypto.Cipher import AES
from Crypto.Hash import SHAKE128
from Crypto.Util._file_system import pycryptodome_filename
from Crypto.Util.strxor import strxor
@ -453,23 +454,9 @@ class TestVectorsWycheproof(unittest.TestCase):
self._id = "None"
def setUp(self):
comps = "Crypto.SelfTest.Cipher.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, "aes_siv_cmac_test.json"), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
self.tv = []
for group in tv_tree['testGroups']:
for test in group['tests']:
tv = TestVector()
tv.id = test['tcId']
for attr in 'key', 'aad', 'msg', 'ct':
setattr(tv, attr, unhexlify(test[attr]))
tv.valid = test['result'] != "invalid"
self.tv.append(tv)
self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
"aes_siv_cmac_test.json",
"Wycheproof AES SIV")
def shortDescription(self):
return self._id
@ -510,23 +497,9 @@ class TestVectorsWycheproof2(unittest.TestCase):
self._id = "None"
def setUp(self):
comps = "Crypto.SelfTest.Cipher.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, "aead_aes_siv_cmac_test.json"), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
self.tv = []
for group in tv_tree['testGroups']:
for test in group['tests']:
tv = TestVector()
tv.id = test['tcId']
for attr in 'key', 'iv', 'aad', 'msg', 'ct', 'tag':
setattr(tv, attr, unhexlify(test[attr]))
tv.valid = test['result'] != "invalid"
self.tv.append(tv)
self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
"aead_aes_siv_cmac_test.json",
"Wycheproof AEAD SIV")
def shortDescription(self):
return self._id

View file

@ -32,7 +32,8 @@ from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5 as PKCS
from Crypto.Util.py3compat import b
from Crypto.Util.number import bytes_to_long, long_to_bytes
from Crypto.Util._file_system import pycryptodome_filename
from Crypto.SelfTest.loader import load_test_vectors_wycheproof
def rws(t):
"""Remove white spaces, tabs, and new lines from a string"""
@ -187,31 +188,15 @@ class TestVectorsWycheproof(unittest.TestCase):
self._id = "None"
def load_tests(self, filename):
comps = "Crypto.SelfTest.Cipher.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, filename), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
result = []
def filter_rsa(group):
return RSA.import_key(group['privateKeyPem'])
for group in tv_tree['testGroups']:
rsa_key = RSA.import_key(group['privateKeyPem'])
for test in group['tests']:
tv = TestVector()
tv.rsa_key = rsa_key
tv.id = test['tcId']
tv.comment = test['comment']
for attr in 'msg', 'ct':
setattr(tv, attr, unhexlify(test[attr]))
tv.valid = test['result'] != "invalid"
tv.warning = test['result'] == "acceptable"
result.append(tv)
result = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
filename,
"Wycheproof PKCS#1v1.5 (%s)" % filename,
group_tag={'rsa_key': filter_rsa}
)
return result
def setUp(self):

View file

@ -20,11 +20,10 @@
# SOFTWARE.
# ===================================================================
import json
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex
from Crypto.SelfTest.loader import load_test_vectors_wycheproof
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP as PKCS
@ -33,21 +32,23 @@ from Crypto import Random
from Crypto.Signature.pss import MGF1
from Crypto.Util.py3compat import b, bchr
from Crypto.Util._file_system import pycryptodome_filename
def rws(t):
"""Remove white spaces, tabs, and new lines from a string"""
for c in ['\n', '\t', ' ']:
t = t.replace(c,'')
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:
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):
@ -267,98 +268,106 @@ class PKCS1_OAEP_Tests(unittest.TestCase):
)
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
cipher = PKCS.new(key, test[4], randfunc=randGen(t2b(test[3])))
ct = cipher.encrypt(t2b(test[1]))
self.assertEqual(ct, t2b(test[2]))
# 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
cipher = PKCS.new(key, test[4], randfunc=randGen(t2b(test[3])))
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)
# 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]))
# 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)
# 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)
cipher = PKCS.new(self.key1024)
ct = cipher.encrypt(pt)
pt2 = cipher.decrypt(ct)
self.assertEqual(pt,pt2)
# 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)
cipher = PKCS.new(self.key1024)
ct = cipher.encrypt(pt)
pt2 = cipher.decrypt(ct)
self.assertEqual(pt, pt2)
def testEncryptDecrypt2(self):
# Helper function to monitor what's requested from RNG
# Helper function to monitor what's requested from RNG
global asked
def localRng(N):
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,RIPEMD160):
# Verify that encrypt() asks for as many random bytes
# as the hash output size
asked = 0
pt = self.rng(40)
cipher = PKCS.new(self.key1024, hashmod, randfunc=localRng)
ct = cipher.encrypt(pt)
self.assertEqual(cipher.decrypt(ct), pt)
self.assertEqual(asked, hashmod.digest_size)
asked += N
return self.rng(N)
# Verify that OAEP is friendly to all hashes
for hashmod in (MD2, MD5, SHA1, SHA256, RIPEMD160):
# Verify that encrypt() asks for as many random bytes
# as the hash output size
asked = 0
pt = self.rng(40)
cipher = PKCS.new(self.key1024, hashmod, randfunc=localRng)
ct = cipher.encrypt(pt)
self.assertEqual(cipher.decrypt(ct), pt)
self.assertEqual(asked, hashmod.digest_size)
def testEncryptDecrypt3(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)
# 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 testEncryptDecrypt4(self):
# Verify that encrypt() uses the custom MGF
# Verify that encrypt() uses the custom MGF
global mgfcalls
# Helper function to monitor what's requested from MGF
def newMGF(seed, maskLen):
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)
mgfcalls += 1
return b'\x00' * 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 testByteArray(self):
pt = b("XER")
@ -384,59 +393,49 @@ class TestVectorsWycheproof(unittest.TestCase):
self._id = "None"
def load_tests(self, filename):
comps = "Crypto.SelfTest.Cipher.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, filename), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
result = []
def filter_rsa(group):
return RSA.import_key(group['privateKeyPem'])
for group in tv_tree['testGroups']:
rsa_key = RSA.import_key(group['privateKeyPem'])
def filter_sha(group):
if group['sha'] == "SHA-1":
hash_mod = SHA1
return SHA1
elif group['sha'] == "SHA-224":
hash_mod = SHA224
return SHA224
elif group['sha'] == "SHA-256":
hash_mod = SHA256
return SHA256
elif group['sha'] == "SHA-384":
hash_mod = SHA384
return SHA384
elif group['sha'] == "SHA-512":
hash_mod = SHA512
return SHA512
else:
raise ValueError("Unknown sha " + group['sha'])
def filter_mgf(group):
if group['mgfSha'] == "SHA-1":
mgf = lambda x,y: MGF1(x, y, SHA1)
return lambda x, y: MGF1(x, y, SHA1)
elif group['mgfSha'] == "SHA-224":
mgf = lambda x,y: MGF1(x, y, SHA224)
return lambda x, y: MGF1(x, y, SHA224)
elif group['mgfSha'] == "SHA-256":
mgf = lambda x,y: MGF1(x, y, SHA256)
return lambda x, y: MGF1(x, y, SHA256)
elif group['mgfSha'] == "SHA-384":
mgf = lambda x,y: MGF1(x, y, SHA384)
return lambda x, y: MGF1(x, y, SHA384)
elif group['mgfSha'] == "SHA-512":
mgf = lambda x,y: MGF1(x, y, SHA512)
return lambda x, y: MGF1(x, y, SHA512)
else:
raise ValueError("Unknown mgf/sha " + group['mgfSha'])
for test in group['tests']:
tv = TestVector()
def filter_algo(group):
return "%s with MGF1/%s" % (group['sha'], group['mgfSha'])
tv.rsa_key = rsa_key
tv.hash_mod = hash_mod
tv.mgf = mgf
tv.algo = "%s with MGF1/%s" % (group['sha'], group['mgfSha'])
tv.id = test['tcId']
tv.comment = test['comment']
for attr in 'msg', 'ct', 'label':
setattr(tv, attr, unhexlify(test[attr]))
tv.valid = test['result'] != "invalid"
tv.warning = test['result'] == "acceptable"
result.append(tv)
result = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
filename,
"Wycheproof PKCS#1 OAEP (%s)" % filename,
group_tag={'rsa_key': filter_rsa,
'hash_mod': filter_sha,
'mgf': filter_mgf,
'algo': filter_algo}
)
return result
def setUp(self):
@ -462,7 +461,6 @@ class TestVectorsWycheproof(unittest.TestCase):
self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json"))
self.tv.extend(self.load_tests("rsa_oaep_misc_test.json"))
def shortDescription(self):
return self._id
@ -499,8 +497,10 @@ def get_tests(config={}):
tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)]
return tests
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
def suite():
unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')
# vim:set ts=4 sw=4 sts=4 expandtab:

View file

@ -263,7 +263,7 @@ def make_hash_tests(module, module_name, test_data, digest_size, oid=None,
name = "%s #%d: %s" % (module_name, i+1, description)
tests.append(HashSelfTest(module, name, expected, input, extra_params))
name = "%s #%d: digest_size" % (module_name, i+1)
name = "%s #%d: digest_size" % (module_name, len(test_data) + 1)
tests.append(HashDigestSizeSelfTest(module, name, digest_size, extra_params))
if oid is not None:

View file

@ -28,13 +28,14 @@
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import os
import re
import unittest
import warnings
from binascii import unhexlify, hexlify
from Crypto.Util.py3compat import tobytes
from Crypto.Util.strxor import strxor_c
from Crypto.Util._file_system import pycryptodome_filename
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Hash import BLAKE2b, BLAKE2s
@ -112,7 +113,7 @@ class Blake2Test(unittest.TestCase):
self.failUnless(isinstance(digest, type(b"digest")))
def test_update_after_digest(self):
msg=b"rrrrttt"
msg = b"rrrrttt"
# Normally, update() cannot be done after digest()
h = self.BLAKE2.new(digest_bits=256, data=msg[:4])
@ -262,14 +263,9 @@ class Blake2sTest(Blake2Test):
class Blake2OfficialTestVector(unittest.TestCase):
def setUp(self):
test_vector_file = pycryptodome_filename(
("Crypto", "SelfTest", "Hash", "test_vectors", self.name),
self.name.lower() + "-test.txt")
def _load_tests(self, test_vector_file):
expected = "in"
self.test_vectors = []
test_vectors = []
with open(test_vector_file, "rt") as test_vector_fd:
for line_number, line in enumerate(test_vector_fd):
@ -294,7 +290,26 @@ class Blake2OfficialTestVector(unittest.TestCase):
else:
result = bin_value
expected = "in"
self.test_vectors.append((input_data, key, result))
test_vectors.append((input_data, key, result))
return test_vectors
def setUp(self):
dir_comps = ("Hash", self.name)
file_name = self.name.lower() + "-test.txt"
self.description = "%s tests" % self.name
try:
import pycryptodome_test_vectors # type: ignore
except ImportError:
warnings.warn("Warning: skipping extended tests for %s" % self.name,
UserWarning)
self.test_vectors = []
return
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(init_dir, *dir_comps, file_name)
self.test_vectors = self._load_tests(full_file_name)
def runTest(self):
for (input_data, key, result) in self.test_vectors:
@ -323,12 +338,8 @@ class Blake2sOfficialTestVector(Blake2OfficialTestVector):
class Blake2TestVector1(unittest.TestCase):
def setUp(self):
test_vector_file = pycryptodome_filename(
("Crypto", "SelfTest", "Hash", "test_vectors", self.name),
"tv1.txt")
self.test_vectors = []
def _load_tests(self, test_vector_file):
test_vectors = []
with open(test_vector_file, "rt") as test_vector_fd:
for line_number, line in enumerate(test_vector_fd):
if line.strip() == "" or line.startswith("#"):
@ -338,7 +349,25 @@ class Blake2TestVector1(unittest.TestCase):
raise ValueError("Incorrect test vector format (line %d)"
% line_number)
self.test_vectors.append(unhexlify(tobytes(res.group(1))))
test_vectors.append(unhexlify(tobytes(res.group(1))))
return test_vectors
def setUp(self):
dir_comps = ("Hash", self.name)
file_name = "tv1.txt"
self.description = "%s tests" % self.name
try:
import pycryptodome_test_vectors
except ImportError:
warnings.warn("Warning: skipping extended tests for %s" % self.name,
UserWarning)
self.test_vectors = []
return
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(init_dir, *dir_comps, file_name)
self.test_vectors = self._load_tests(full_file_name)
def runTest(self):
@ -368,12 +397,8 @@ class Blake2sTestVector1(Blake2TestVector1):
class Blake2TestVector2(unittest.TestCase):
def setUp(self):
test_vector_file = pycryptodome_filename(
("Crypto", "SelfTest", "Hash", "test_vectors", self.name),
"tv2.txt")
self.test_vectors = []
def _load_tests(self, test_vector_file):
test_vectors = []
with open(test_vector_file, "rt") as test_vector_fd:
for line_number, line in enumerate(test_vector_fd):
if line.strip() == "" or line.startswith("#"):
@ -382,10 +407,27 @@ class Blake2TestVector2(unittest.TestCase):
if not res:
raise ValueError("Incorrect test vector format (line %d)"
% line_number)
key_size = int(res.group(1))
result = unhexlify(tobytes(res.group(2)))
self.test_vectors.append((key_size, result))
test_vectors.append((key_size, result))
return test_vectors
def setUp(self):
dir_comps = ("Hash", self.name)
file_name = "tv2.txt"
self.description = "%s tests" % self.name
try:
import pycryptodome_test_vectors # type: ignore
except ImportError:
warnings.warn("Warning: skipping extended tests for %s" % self.name,
UserWarning)
self.test_vectors = []
return
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(init_dir, *dir_comps, file_name)
self.test_vectors = self._load_tests(full_file_name)
def runTest(self):
@ -435,5 +477,6 @@ def get_tests(config={}):
if __name__ == '__main__':
import unittest
suite = lambda: unittest.TestSuite(get_tests())
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View file

@ -43,10 +43,10 @@ from Crypto.Hash import CMAC
from Crypto.Cipher import AES, DES3
from Crypto.Hash import SHAKE128
from Crypto.Util._file_system import pycryptodome_filename
from Crypto.Util.strxor import strxor
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_test_vectors_wycheproof
# This is a list of (key, data, result, description, module) tuples.
test_data = [
@ -366,27 +366,14 @@ class TestVectorsWycheproof(unittest.TestCase):
self._id = "None"
def setUp(self):
comps = "Crypto.SelfTest.Hash.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, "aes_cmac_test.json"), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
self.tv = []
def filter_tag(group):
return group['tagSize'] // 8
for group in tv_tree['testGroups']:
tag_size = group['tagSize'] // 8
for test in group['tests']:
tv = TestVector()
tv.tag_size = tag_size
tv.id = test['tcId']
tv.comment = test['comment']
for attr in 'key', 'msg', 'tag':
setattr(tv, attr, unhexlify(test[attr]))
tv.valid = test['result'] != "invalid"
tv.warning = test['result'] == "acceptable"
self.tv.append(tv)
self.tv = load_test_vectors_wycheproof(("Hash", "wycheproof"),
"aes_cmac_test.json",
"Wycheproof CMAC",
group_tag={'tag_size': filter_tag})
def shortDescription(self):
return self._id

View file

@ -26,7 +26,7 @@
from binascii import hexlify
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
# Test vectors from various sources
# This is a list of (expected_result, input[, description]) tuples.
@ -55,10 +55,10 @@ def get_tests(config={}):
tests = []
test_vectors = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA1"),
test_vectors = load_test_vectors(("Hash", "SHA1"),
"SHA1ShortMsg.rsp",
"KAT SHA-1",
{ "len" : lambda x: int(x) } )
{ "len" : lambda x: int(x) } ) or []
test_data = test_data_various[:]
for tv in test_vectors:

View file

@ -25,7 +25,7 @@
import unittest
from binascii import hexlify
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Hash import SHA3_224 as SHA3
from Crypto.Util.py3compat import b
@ -56,10 +56,10 @@ def get_tests(config={}):
tests = []
test_vectors = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA3"),
test_vectors = load_test_vectors(("Hash", "SHA3"),
"ShortMsgKAT_SHA3-224.txt",
"KAT SHA-3 224",
{ "len" : lambda x: int(x) } )
{ "len" : lambda x: int(x) } ) or []
test_data = []
for tv in test_vectors:

View file

@ -25,7 +25,7 @@
import unittest
from binascii import hexlify
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Hash import SHA3_256 as SHA3
from Crypto.Util.py3compat import b
@ -56,10 +56,10 @@ def get_tests(config={}):
tests = []
test_vectors = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA3"),
test_vectors = load_test_vectors(("Hash", "SHA3"),
"ShortMsgKAT_SHA3-256.txt",
"KAT SHA-3 256",
{ "len" : lambda x: int(x) } )
{ "len" : lambda x: int(x) } ) or []
test_data = []
for tv in test_vectors:

View file

@ -25,7 +25,7 @@
import unittest
from binascii import hexlify
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Hash import SHA3_384 as SHA3
from Crypto.Util.py3compat import b
@ -56,10 +56,10 @@ def get_tests(config={}):
tests = []
test_vectors = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA3"),
test_vectors = load_test_vectors(("Hash", "SHA3"),
"ShortMsgKAT_SHA3-384.txt",
"KAT SHA-3 384",
{ "len" : lambda x: int(x) } )
{ "len" : lambda x: int(x) } ) or []
test_data = []
for tv in test_vectors:

View file

@ -25,7 +25,7 @@
import unittest
from binascii import hexlify
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Hash import SHA3_512 as SHA3
from Crypto.Util.py3compat import b
@ -56,10 +56,10 @@ def get_tests(config={}):
tests = []
test_vectors = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA3"),
test_vectors = load_test_vectors(("Hash", "SHA3"),
"ShortMsgKAT_SHA3-512.txt",
"KAT SHA-3 512",
{ "len" : lambda x: int(x) } )
{ "len" : lambda x: int(x) } ) or []
test_data = []
for tv in test_vectors:

View file

@ -28,7 +28,7 @@ from binascii import hexlify
from Crypto.Hash import SHA512
from .common import make_hash_tests
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
# Test vectors from various sources
# This is a list of (expected_result, input[, description]) tuples.
@ -52,10 +52,10 @@ test_data_512_other = [
def get_tests_SHA512():
test_vectors = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA2"),
test_vectors = load_test_vectors(("Hash", "SHA2"),
"SHA512ShortMsg.rsp",
"KAT SHA-512",
{ "len" : lambda x: int(x) } )
{"len": lambda x: int(x)}) or []
test_data = test_data_512_other[:]
for tv in test_vectors:
@ -76,10 +76,10 @@ def get_tests_SHA512():
def get_tests_SHA512_224():
test_vectors = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA2"),
test_vectors = load_test_vectors(("Hash", "SHA2"),
"SHA512_224ShortMsg.rsp",
"KAT SHA-512/224",
{ "len" : lambda x: int(x) } )
{"len": lambda x: int(x)}) or []
test_data = []
for tv in test_vectors:
@ -101,10 +101,10 @@ def get_tests_SHA512_224():
def get_tests_SHA512_256():
test_vectors = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA2"),
test_vectors = load_test_vectors(("Hash", "SHA2"),
"SHA512_256ShortMsg.rsp",
"KAT SHA-512/256",
{ "len" : lambda x: int(x) } )
{"len": lambda x: int(x)}) or []
test_data = []
for tv in test_vectors:

View file

@ -33,7 +33,7 @@
import unittest
from binascii import hexlify, unhexlify
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Hash import SHAKE128, SHAKE256
@ -91,10 +91,10 @@ class SHAKEVectors(unittest.TestCase):
pass
test_vectors_128 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA3"),
test_vectors_128 = load_test_vectors(("Hash", "SHA3"),
"ShortMsgKAT_SHAKE128.txt",
"Short Messages KAT SHAKE128",
{ "len" : lambda x: int(x) } )
{ "len" : lambda x: int(x) } ) or []
for idx, tv in enumerate(test_vectors_128):
if tv.len == 0:
@ -110,10 +110,10 @@ for idx, tv in enumerate(test_vectors_128):
setattr(SHAKEVectors, "test_128_%d" % idx, new_test)
test_vectors_256 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "SHA3"),
test_vectors_256 = load_test_vectors(("Hash", "SHA3"),
"ShortMsgKAT_SHAKE256.txt",
"Short Messages KAT SHAKE256",
{ "len" : lambda x: int(x) } )
{ "len" : lambda x: int(x) } ) or []
for idx, tv in enumerate(test_vectors_256):
if tv.len == 0:

View file

@ -33,7 +33,7 @@
import unittest
from binascii import hexlify, unhexlify
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Hash import keccak
@ -141,15 +141,15 @@ class KeccakVectors(unittest.TestCase):
# TODO: add ExtremelyLong tests
test_vectors_224 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
test_vectors_224 = load_test_vectors(("Hash", "keccak"),
"ShortMsgKAT_224.txt",
"Short Messages KAT 224",
{ "len" : lambda x: int(x) } )
{"len": lambda x: int(x)}) or []
test_vectors_224 += load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
test_vectors_224 += load_test_vectors(("Hash", "keccak"),
"LongMsgKAT_224.txt",
"Long Messages KAT 224",
{ "len" : lambda x: int(x) } )
{"len": lambda x: int(x)}) or []
for idx, tv in enumerate(test_vectors_224):
if tv.len == 0:
@ -165,15 +165,15 @@ for idx, tv in enumerate(test_vectors_224):
# ---
test_vectors_256 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
test_vectors_256 = load_test_vectors(("Hash", "keccak"),
"ShortMsgKAT_256.txt",
"Short Messages KAT 256",
{ "len" : lambda x: int(x) } )
{ "len" : lambda x: int(x) } ) or []
test_vectors_256 += load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
test_vectors_256 += load_test_vectors(("Hash", "keccak"),
"LongMsgKAT_256.txt",
"Long Messages KAT 256",
{ "len" : lambda x: int(x) } )
{ "len" : lambda x: int(x) } ) or []
for idx, tv in enumerate(test_vectors_256):
if tv.len == 0:
@ -190,15 +190,15 @@ for idx, tv in enumerate(test_vectors_256):
# ---
test_vectors_384 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
test_vectors_384 = load_test_vectors(("Hash", "keccak"),
"ShortMsgKAT_384.txt",
"Short Messages KAT 384",
{ "len" : lambda x: int(x) } )
{"len": lambda x: int(x)}) or []
test_vectors_384 += load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
test_vectors_384 += load_test_vectors(("Hash", "keccak"),
"LongMsgKAT_384.txt",
"Long Messages KAT 384",
{ "len" : lambda x: int(x) } )
{"len": lambda x: int(x)}) or []
for idx, tv in enumerate(test_vectors_384):
if tv.len == 0:
@ -214,15 +214,15 @@ for idx, tv in enumerate(test_vectors_384):
# ---
test_vectors_512 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
test_vectors_512 = load_test_vectors(("Hash", "keccak"),
"ShortMsgKAT_512.txt",
"Short Messages KAT 512",
{ "len" : lambda x: int(x) } )
{"len": lambda x: int(x)}) or []
test_vectors_512 += load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
test_vectors_512 += load_test_vectors(("Hash", "keccak"),
"LongMsgKAT_512.txt",
"Long Messages KAT 512",
{ "len" : lambda x: int(x) } )
{"len": lambda x: int(x)}) or []
for idx, tv in enumerate(test_vectors_512):
if tv.len == 0:

View file

@ -20,13 +20,13 @@
# SOFTWARE.
# ===================================================================
import json
import unittest
from binascii import unhexlify
from Crypto.Util.py3compat import *
from Crypto.Util.py3compat import b, bchr
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_test_vectors_wycheproof
from Crypto.Hash import SHA1, HMAC, SHA256, MD5, SHA224, SHA384, SHA512
from Crypto.Cipher import AES, DES3
@ -34,7 +34,6 @@ from Crypto.Protocol.KDF import (PBKDF1, PBKDF2, _S2V, HKDF, scrypt,
bcrypt, bcrypt_check)
from Crypto.Protocol.KDF import _bcrypt_decode
from Crypto.Util._file_system import pycryptodome_filename
def t2b(t):
@ -59,7 +58,7 @@ class PBKDF1_Tests(unittest.TestCase):
# Item #4: expected result (encoded in hex)
_testData = (
# From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf
("password","78578E5A5D63CB06",16,1000,"DC19847E05C64D2FAF10EBFB4A3D2A20"),
("password", "78578E5A5D63CB06", 16, 1000, "DC19847E05C64D2FAF10EBFB4A3D2A20"),
)
def test1(self):
@ -67,6 +66,7 @@ class PBKDF1_Tests(unittest.TestCase):
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.
@ -650,42 +650,29 @@ class TestVectorsHKDFWycheproof(unittest.TestCase):
self._id = "None"
def add_tests(self, filename):
comps = "Crypto.SelfTest.Protocol.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, filename), "rt") as file_in:
tv_tree = json.load(file_in)
algo_name = tv_tree['algorithm']
if algo_name == "HKDF-SHA-1":
hash_module = SHA1
elif algo_name == "HKDF-SHA-256":
hash_module = SHA256
elif algo_name == "HKDF-SHA-384":
hash_module = SHA384
elif algo_name == "HKDF-SHA-512":
hash_module = SHA512
else:
raise ValueError("Unknown algorithm " + algo_name)
def filter_algo(root):
algo_name = root['algorithm']
if algo_name == "HKDF-SHA-1":
return SHA1
elif algo_name == "HKDF-SHA-256":
return SHA256
elif algo_name == "HKDF-SHA-384":
return SHA384
elif algo_name == "HKDF-SHA-512":
return SHA512
else:
raise ValueError("Unknown algorithm " + algo_name)
for group in tv_tree['testGroups']:
def filter_size(unit):
return int(unit['size'])
from collections import namedtuple
TestVector = namedtuple('TestVector', 'id comment ikm salt info size okm hash_module valid warning filename')
for test in group['tests']:
tv = TestVector(
test['tcId'],
test['comment'],
unhexlify(test['ikm']),
unhexlify(test['salt']),
unhexlify(test['info']),
int(test['size']),
unhexlify(test['okm']),
hash_module,
test['result'] != "invalid",
test['result'] == "acceptable",
filename
)
self.tv.append(tv)
result = load_test_vectors_wycheproof(("Protocol", "wycheproof"),
filename,
"Wycheproof HMAC (%s)" % filename,
root_tag={'hash_module': filter_algo},
unit_tag={'size': filter_size})
return result
def setUp(self):
self.tv = []
@ -733,7 +720,7 @@ def get_tests(config={}):
tests += list_test_cases(PBKDF2_Tests)
tests += list_test_cases(S2V_Tests)
tests += list_test_cases(HKDF_Tests)
tests += [ TestVectorsHKDFWycheproof(wycheproof_warnings) ]
tests += [TestVectorsHKDFWycheproof(wycheproof_warnings)]
tests += list_test_cases(scrypt_Tests)
tests += list_test_cases(bcrypt_Tests)

View file

@ -31,7 +31,7 @@
import unittest
import time
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors
from Crypto.PublicKey import ECC
from Crypto.PublicKey.ECC import EccPoint, _curves, EccKey
@ -479,13 +479,12 @@ class TestEccPoint_PAI_P256(unittest.TestCase):
pointG = EccPoint(curve.Gx, curve.Gy, "p256")
tv_pai = load_tests(("Crypto", "SelfTest", "PublicKey", "test_vectors", "ECC"),
tv_pai = load_test_vectors(("PublicKey", "ECC"),
"point-at-infinity.org-P256.txt",
"P-256 tests from point-at-infinity.org",
{ "k" : lambda k: int(k),
"x" : lambda x: int(x, 16),
"y" : lambda y: int(y, 16)} )
assert(tv_pai)
{"k": lambda k: int(k),
"x": lambda x: int(x, 16),
"y": lambda y: int(y, 16)}) or []
for tv in tv_pai:
def new_test(self, scalar=tv.k, x=tv.x, y=tv.y):
result = self.pointG * scalar
@ -501,13 +500,12 @@ class TestEccPoint_PAI_P384(unittest.TestCase):
pointG = EccPoint(curve.Gx, curve.Gy, "p384")
tv_pai = load_tests(("Crypto", "SelfTest", "PublicKey", "test_vectors", "ECC"),
tv_pai = load_test_vectors(("PublicKey", "ECC"),
"point-at-infinity.org-P384.txt",
"P-384 tests from point-at-infinity.org",
{ "k" : lambda k: int(k),
"x" : lambda x: int(x, 16),
"y" : lambda y: int(y, 16)} )
assert(tv_pai)
{"k" : lambda k: int(k),
"x" : lambda x: int(x, 16),
"y" : lambda y: int(y, 16)}) or []
for tv in tv_pai:
def new_test(self, scalar=tv.k, x=tv.x, y=tv.y):
result = self.pointG * scalar
@ -523,13 +521,12 @@ class TestEccPoint_PAI_P521(unittest.TestCase):
pointG = EccPoint(curve.Gx, curve.Gy, "p521")
tv_pai = load_tests(("Crypto", "SelfTest", "PublicKey", "test_vectors", "ECC"),
tv_pai = load_test_vectors(("PublicKey", "ECC"),
"point-at-infinity.org-P521.txt",
"P-521 tests from point-at-infinity.org",
{ "k" : lambda k: int(k),
"x" : lambda x: int(x, 16),
"y" : lambda y: int(y, 16)} )
assert(tv_pai)
{"k": lambda k: int(k),
"x": lambda x: int(x, 16),
"y": lambda y: int(y, 16)}) or []
for tv in tv_pai:
def new_test(self, scalar=tv.k, x=tv.x, y=tv.y):
result = self.pointG * scalar

View file

@ -28,21 +28,54 @@
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import os
import errno
import warnings
import unittest
from binascii import unhexlify
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.Util._file_system import pycryptodome_filename
from Crypto.Util.py3compat import bord, tostr
from Crypto.Util.number import bytes_to_long
from Crypto.Hash import SHAKE128
from Crypto.PublicKey import ECC
def load_file(filename, mode="rb"):
comps = [ "Crypto", "SelfTest", "PublicKey", "test_vectors", "ECC" ]
with open(pycryptodome_filename(comps, filename), mode) as fd:
return fd.read()
try:
import pycryptodome_test_vectors # type: ignore
test_vectors_available = True
except ImportError:
test_vectors_available = False
class MissingTestVectorException(ValueError):
pass
def load_file(file_name, mode="rb"):
results = None
try:
if not test_vectors_available:
raise FileNotFoundError(errno.ENOENT,
os.strerror(errno.ENOENT),
file_name)
dir_comps = ("PublicKey", "ECC")
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(init_dir, *dir_comps, file_name)
with open(full_file_name, mode) as file_in:
results = file_in.read()
except FileNotFoundError:
warnings.warn("Warning: skipping extended tests for ECC",
UserWarning,
stacklevel=2)
if results is None:
raise MissingTestVectorException("Missing %s" % file_name)
return results
def compact(lines):
@ -86,13 +119,11 @@ def create_ref_keys_p521():
return (ECC.construct(curve="P-521", d=private_key_d),
ECC.construct(curve="P-521", point_x=public_key_x, point_y=public_key_y))
# Create reference key pair
# ref_private, ref_public = create_ref_keys_p521()
def get_fixed_prng():
return SHAKE128.new().update(b"SEED").read
return SHAKE128.new().update(b"SEED").read
class TestImport(unittest.TestCase):
@ -103,7 +134,9 @@ class TestImport(unittest.TestCase):
class TestImport_P256(unittest.TestCase):
ref_private, ref_public = create_ref_keys_p256()
def __init__(self, *args, **kwargs):
super(TestImport_P256, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_p256()
def test_import_public_der(self):
key_file = load_file("ecc_p256_public.der")
@ -229,7 +262,9 @@ class TestImport_P256(unittest.TestCase):
class TestImport_P384(unittest.TestCase):
ref_private, ref_public = create_ref_keys_p384()
def __init__(self, *args, **kwargs):
super(TestImport_P384, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_p384()
def test_import_public_der(self):
key_file = load_file("ecc_p384_public.der")
@ -350,7 +385,9 @@ class TestImport_P384(unittest.TestCase):
class TestImport_P521(unittest.TestCase):
ref_private, ref_public = create_ref_keys_p521()
def __init__(self, *args, **kwargs):
super(TestImport_P521, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_p521()
def test_import_public_der(self):
key_file = load_file("ecc_p521_public.der")
@ -471,7 +508,9 @@ class TestImport_P521(unittest.TestCase):
class TestExport_P256(unittest.TestCase):
ref_private, ref_public = create_ref_keys_p256()
def __init__(self, *args, **kwargs):
super(TestExport_P256, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_p256()
def test_export_public_der_uncompressed(self):
key_file = load_file("ecc_p256_public.der")
@ -517,7 +556,7 @@ class TestExport_P256(unittest.TestCase):
def test_export_private_pkcs8_encrypted(self):
encoded = self.ref_private._export_pkcs8(passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
# This should prove that the output is password-protected
self.assertRaises(ValueError, ECC._import_pkcs8, encoded, None)
@ -528,8 +567,8 @@ class TestExport_P256(unittest.TestCase):
# ---
encoded = self.ref_private.export_key(format="DER",
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
passphrase="secret",
protection="PBKDF2WithHMAC-SHA1AndAES128-CBC")
decoded = ECC.import_key(encoded, "secret")
self.assertEqual(self.ref_private, decoded)
@ -749,7 +788,9 @@ gVnJp9EBND/tHQ==
class TestExport_P384(unittest.TestCase):
ref_private, ref_public = create_ref_keys_p384()
def __init__(self, *args, **kwargs):
super(TestExport_P384, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_p384()
def test_export_public_der_uncompressed(self):
key_file = load_file("ecc_p384_public.der")
@ -1016,7 +1057,9 @@ YC46ZRsnKNayw3wATdPjgja7L/DSII3nZK0G6KOOVwJBznT/e+zudUJYhZKaBLRx
class TestExport_P521(unittest.TestCase):
ref_private, ref_public = create_ref_keys_p521()
def __init__(self, *args, **kwargs):
super(TestExport_P521, self).__init__(*args, **kwargs)
self.ref_private, self.ref_public = create_ref_keys_p521()
def test_export_public_der_uncompressed(self):
key_file = load_file("ecc_p521_public.der")
@ -1286,14 +1329,18 @@ vv6oYkMIIi7r5oQWAiQDrR2mlrrFDL9V7GH/r8SWQw==
def get_tests(config={}):
tests = []
tests += list_test_cases(TestImport)
tests += list_test_cases(TestImport_P256)
tests += list_test_cases(TestImport_P384)
tests += list_test_cases(TestImport_P521)
tests += list_test_cases(TestExport_P256)
tests += list_test_cases(TestExport_P384)
tests += list_test_cases(TestExport_P521)
try:
tests += list_test_cases(TestImport_P256)
tests += list_test_cases(TestImport_P384)
tests += list_test_cases(TestImport_P521)
tests += list_test_cases(TestExport_P256)
tests += list_test_cases(TestExport_P384)
tests += list_test_cases(TestExport_P521)
except MissingTestVectorException:
pass
return tests
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View file

@ -20,32 +20,57 @@
# SOFTWARE.
# ===================================================================
import unittest
import os
import re
import errno
import warnings
import unittest
from Crypto.PublicKey import RSA
from Crypto.SelfTest.st_common import *
from Crypto.Util.py3compat import *
from Crypto.SelfTest.st_common import a2b_hex, list_test_cases
from Crypto.Util.py3compat import b, tostr
from Crypto.Util.number import inverse
from Crypto.Util import asn1
from Crypto.Util._file_system import pycryptodome_filename
try:
import pycryptodome_test_vectors # type: ignore
test_vectors_available = True
except ImportError:
test_vectors_available = False
def load_file(filename, mode="rb"):
comps = [ "Crypto", "SelfTest", "PublicKey", "test_vectors", "RSA" ]
with open(pycryptodome_filename(comps, filename), mode) as fd:
return fd.read()
def load_file(file_name, mode="rb"):
results = None
try:
if not test_vectors_available:
raise FileNotFoundError(errno.ENOENT,
os.strerror(errno.ENOENT),
file_name)
dir_comps = ("PublicKey", "RSA")
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(init_dir, *dir_comps, file_name)
with open(full_file_name, mode) as file_in:
results = file_in.read()
except FileNotFoundError:
warnings.warn("Warning: skipping extended tests for RSA",
UserWarning,
stacklevel=2)
return results
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)
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 = u'''-----BEGIN RSA PRIVATE KEY-----
@ -71,7 +96,7 @@ BX85JB8zqwHB
-----END PRIVATE KEY-----'''
# The same RSA private key as in rsaKeyPEM, but now encrypted
rsaKeyEncryptedPEM=(
rsaKeyEncryptedPEM = (
# PEM encryption
# With DES and passphrase 'test'
@ -507,6 +532,10 @@ class TestImport_2048(unittest.TestCase):
key_file_ref = load_file("rsa2048_private.pem")
key_file = load_file("rsa2048_public_openssh.txt")
# Skip test if test vectors are not installed
if None in (key_file_ref, key_file):
return
key_ref = RSA.import_key(key_file_ref).public_key()
key = RSA.import_key(key_file)
self.assertEqual(key_ref, key)
@ -515,6 +544,10 @@ class TestImport_2048(unittest.TestCase):
key_file = load_file("rsa2048_private_openssh.pem")
key_file_old = load_file("rsa2048_private_openssh_old.pem")
# Skip test if test vectors are not installed
if None in (key_file_old, key_file):
return
key = RSA.import_key(key_file)
key_old = RSA.import_key(key_file_old)
@ -524,6 +557,10 @@ class TestImport_2048(unittest.TestCase):
key_file = load_file("rsa2048_private_openssh_pwd.pem")
key_file_old = load_file("rsa2048_private_openssh_pwd_old.pem")
# Skip test if test vectors are not installed
if None in (key_file_old, key_file):
return
key = RSA.import_key(key_file, b"password")
key_old = RSA.import_key(key_file_old)
self.assertEqual(key, key_old)

View file

@ -32,7 +32,6 @@
# ===================================================================
import re
import json
import unittest
from binascii import hexlify, unhexlify
@ -43,12 +42,9 @@ from Crypto.Hash import (SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_256,
from Crypto.Signature import DSS
from Crypto.PublicKey import DSA, ECC
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof
from Crypto.Util.number import bytes_to_long, long_to_bytes
from Crypto.Util._file_system import pycryptodome_filename
from Crypto.Util.strxor import strxor
def t2b(hexstring):
ws = hexstring.replace(" ", "").replace("\n", "")
@ -147,13 +143,15 @@ class FIPS_DSA_Tests(unittest.TestCase):
signer = DSS.new(self.key_pub, 'fips-186-3')
self.failIf(signer.can_sign())
class FIPS_DSA_Tests_KAT(unittest.TestCase):
pass
test_vectors_verify = load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "DSA"),
"FIPS_186_3_SigVer.rsp",
"Signature Verification 186-3",
{'result' : lambda x: x})
test_vectors_verify = load_test_vectors(("Signature", "DSA"),
"FIPS_186_3_SigVer.rsp",
"Signature Verification 186-3",
{'result': lambda x: x}) or []
for idx, tv in enumerate(test_vectors_verify):
@ -173,7 +171,7 @@ for idx, tv in enumerate(test_vectors_verify):
hash_obj = hash_module.new(tv.msg)
comps = [bytes_to_long(x) for x in (tv.y, generator, modulus, suborder)]
key = DSA.construct(comps, False) # type: ignore
key = DSA.construct(comps, False) # type: ignore
verifier = DSS.new(key, 'fips-186-3')
def positive_test(self, verifier=verifier, hash_obj=hash_obj, signature=tv.r+tv.s):
@ -188,10 +186,10 @@ for idx, tv in enumerate(test_vectors_verify):
setattr(FIPS_DSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test)
test_vectors_sign = load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "DSA"),
"FIPS_186_3_SigGen.txt",
"Signature Creation 186-3",
{})
test_vectors_sign = load_test_vectors(("Signature", "DSA"),
"FIPS_186_3_SigGen.txt",
"Signature Creation 186-3",
{}) or []
for idx, tv in enumerate(test_vectors_sign):
@ -285,13 +283,13 @@ class FIPS_ECDSA_Tests_KAT(unittest.TestCase):
pass
test_vectors_verify = load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "ECDSA"),
"SigVer.rsp",
"ECDSA Signature Verification 186-3",
{'result': lambda x: x,
'qx': lambda x: int(x, 16),
'qy': lambda x: int(x, 16),
})
test_vectors_verify = load_test_vectors(("Signature", "ECDSA"),
"SigVer.rsp",
"ECDSA Signature Verification 186-3",
{'result': lambda x: x,
'qx': lambda x: int(x, 16),
'qy': lambda x: int(x, 16),
}) or []
for idx, tv in enumerate(test_vectors_verify):
@ -319,10 +317,10 @@ for idx, tv in enumerate(test_vectors_verify):
setattr(FIPS_ECDSA_Tests_KAT, "test_verify_negative_%d" % idx, negative_test)
test_vectors_sign = load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "ECDSA"),
"SigGen.txt",
"ECDSA Signature Verification 186-3",
{'d': lambda x: int(x, 16)})
test_vectors_sign = load_test_vectors(("Signature", "ECDSA"),
"SigGen.txt",
"ECDSA Signature Verification 186-3",
{'d': lambda x: int(x, 16)}) or []
for idx, tv in enumerate(test_vectors_sign):
@ -576,7 +574,7 @@ class Det_DSA_Tests(unittest.TestCase):
TestKey = namedtuple('TestKey', 'p q g x y')
new_keys = {}
for k in self.keys:
tk = TestKey(*[ t2l(y) for y in k[:-1] ])
tk = TestKey(*[t2l(y) for y in k[:-1]])
new_keys[k[-1]] = tk
self.keys = new_keys
@ -900,26 +898,46 @@ class Det_ECDSA_Tests(unittest.TestCase):
def test_data_rfc6979_p256(self):
signer = DSS.new(self.key_priv_p256, 'deterministic-rfc6979')
for message, k, r, s, module in self.signatures_p256:
for message, k, r, s, module in self.signatures_p256:
hash_obj = module.new(message)
result = signer.sign(hash_obj)
self.assertEqual(r + s, result)
def test_data_rfc6979_p384(self):
signer = DSS.new(self.key_priv_p384, 'deterministic-rfc6979')
for message, k, r, s, module in self.signatures_p384:
for message, k, r, s, module in self.signatures_p384:
hash_obj = module.new(message)
result = signer.sign(hash_obj)
self.assertEqual(r + s, result)
def test_data_rfc6979_p521(self):
signer = DSS.new(self.key_priv_p521, 'deterministic-rfc6979')
for message, k, r, s, module in self.signatures_p521:
for message, k, r, s, module in self.signatures_p521:
hash_obj = module.new(message)
result = signer.sign(hash_obj)
self.assertEqual(r + s, result)
def get_hash_module(hash_name):
if hash_name == "SHA-512":
hash_module = SHA512
elif hash_name == "SHA-512/224":
hash_module = SHA512.new(truncate="224")
elif hash_name == "SHA-512/256":
hash_module = SHA512.new(truncate="256")
elif hash_name == "SHA-384":
hash_module = SHA384
elif hash_name == "SHA-256":
hash_module = SHA256
elif hash_name == "SHA-224":
hash_module = SHA224
elif hash_name == "SHA-1":
hash_module = SHA1
else:
raise ValueError("Unknown hash algorithm: " + hash_name)
return hash_module
class TestVectorsDSAWycheproof(unittest.TestCase):
def __init__(self, wycheproof_warnings, slow_tests):
@ -927,42 +945,29 @@ class TestVectorsDSAWycheproof(unittest.TestCase):
self._wycheproof_warnings = wycheproof_warnings
self._slow_tests = slow_tests
self._id = "None"
def setUp(self):
comps = "Crypto.SelfTest.Signature.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, "dsa_test.json"), "rt") as file_in:
tv_tree = json.load(file_in)
self.tv = []
for group in tv_tree['testGroups']:
key = DSA.import_key(group['keyPem'])
hash_name = group['sha']
if hash_name == "SHA-256":
hash_module = SHA256
elif hash_name == "SHA-224":
hash_module = SHA224
elif hash_name == "SHA-1":
hash_module = SHA1
else:
assert False
assert group['type'] == "DsaVerify"
def setUp(self):
from collections import namedtuple
TestVector = namedtuple('TestVector', 'id comment msg sig key hash_module valid warning')
def filter_dsa(group):
return DSA.import_key(group['keyPem'])
for test in group['tests']:
tv = TestVector(
test['tcId'],
test['comment'],
unhexlify(test['msg']),
unhexlify(test['sig']),
key,
hash_module,
test['result'] != "invalid",
test['result'] == "acceptable"
)
self.tv.append(tv)
def filter_sha(group):
return get_hash_module(group['sha'])
def filter_type(group):
sig_type = group['type']
if sig_type != 'DsaVerify':
raise ValueError("Unknown signature type " + sig_type)
return sig_type
result = load_test_vectors_wycheproof(("Signature", "wycheproof"),
"dsa_test.json",
"Wycheproof DSA signature",
group_tag={'key': filter_dsa,
'hash_module': filter_sha,
'sig_type': filter_type})
self.tv += result
def shortDescription(self):
return self._id
@ -1001,62 +1006,39 @@ class TestVectorsECDSAWycheproof(unittest.TestCase):
self._id = "None"
def add_tests(self, filename):
comps = "Crypto.SelfTest.Signature.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, filename), "rt") as file_in:
tv_tree = json.load(file_in)
for group in tv_tree['testGroups']:
def filter_ecc(group):
# These are the only curves we accept to skip
if group['key']['curve'] in ('secp224r1', 'secp224k1', 'secp256k1',
'brainpoolP224r1', 'brainpoolP224t1',
'brainpoolP256r1', 'brainpoolP256t1',
'brainpoolP320r1', 'brainpoolP320t1',
'brainpoolP384r1', 'brainpoolP384t1',
'brainpoolP512r1', 'brainpoolP512t1',
):
return None
return ECC.import_key(group['keyPem'])
try:
key = ECC.import_key(group['keyPem'])
except ValueError:
continue
hash_name = group['sha']
if hash_name == "SHA-512":
hash_module = SHA512
elif hash_name == "SHA3-512":
hash_module = SHA3_512
elif hash_name == "SHA-384":
hash_module = SHA384
elif hash_name == "SHA3-384":
hash_module = SHA3_384
elif hash_name == "SHA-256":
hash_module = SHA256
elif hash_name == "SHA3-256":
hash_module = SHA3_256
elif hash_name == "SHA-224":
hash_module = SHA224
elif hash_name == "SHA-1":
hash_module = SHA1
else:
raise ValueError("Unknown hash type " + hash_name)
def filter_sha(group):
return get_hash_module(group['sha'])
def filter_encoding(group):
encoding_name = group['type']
if encoding_name == "EcdsaVerify":
encoding = "der"
return "der"
elif encoding_name == "EcdsaP1363Verify":
encoding = "binary"
return "binary"
else:
raise ValueError("Unknown signature type " + encoding_name)
from collections import namedtuple
TestVector = namedtuple('TestVector', 'id comment msg encoding sig key hash_module valid warning filename')
for test in group['tests']:
tv = TestVector(
test['tcId'],
test['comment'],
unhexlify(test['msg']),
encoding,
unhexlify(test['sig']),
key,
hash_module,
test['result'] != "invalid",
test['result'] == "acceptable",
filename
)
self.tv.append(tv)
result = load_test_vectors_wycheproof(("Signature", "wycheproof"),
filename,
"Wycheproof ECDSA signature (%s)" % filename,
group_tag={'key': filter_ecc,
'hash_module': filter_sha,
'encoding': filter_encoding,
})
self.tv += result
def setUp(self):
self.tv = []
@ -1101,6 +1083,10 @@ class TestVectorsECDSAWycheproof(unittest.TestCase):
def test_verify(self, tv):
self._id = "Wycheproof ECDSA Test #%d (%s, %s)" % (tv.id, tv.comment, tv.filename)
# Skip tests with unsupported curves
if tv.key is None:
return
hashed_msg = tv.hash_module.new(tv.msg)
signer = DSS.new(tv.key, 'fips-186-3', encoding=tv.encoding)
try:
@ -1134,12 +1120,13 @@ def get_tests(config={}):
tests += list_test_cases(FIPS_DSA_Tests_KAT)
tests += list_test_cases(FIPS_ECDSA_Tests_KAT)
tests += [ TestVectorsDSAWycheproof(wycheproof_warnings, slow_tests) ]
tests += [ TestVectorsECDSAWycheproof(wycheproof_warnings, slow_tests) ]
tests += [TestVectorsDSAWycheproof(wycheproof_warnings, slow_tests)]
tests += [TestVectorsECDSAWycheproof(wycheproof_warnings, slow_tests)]
return tests
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View file

@ -36,7 +36,7 @@ from Crypto.Util.py3compat import bchr
from Crypto.Util.number import bytes_to_long
from Crypto.Util.strxor import strxor
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof
from Crypto.Hash import (SHA1, SHA224, SHA256, SHA384, SHA512, SHA3_384,
SHA3_224, SHA3_256, SHA3_512)
@ -67,12 +67,12 @@ class FIPS_PKCS1_Verify_Tests_KAT(unittest.TestCase):
pass
test_vectors_verify = load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "PKCS1-v1.5"),
test_vectors_verify = load_test_vectors(("Signature", "PKCS1-v1.5"),
"SigVer15_186-3.rsp",
"Signature Verification 186-3",
{ 'shaalg' : lambda x: x,
'd' : lambda x: int(x),
'result' : lambda x: x })
{'shaalg': lambda x: x,
'd': lambda x: int(x),
'result': lambda x: x}) or []
for count, tv in enumerate(test_vectors_verify):
@ -114,15 +114,15 @@ class FIPS_PKCS1_Sign_Tests_KAT(unittest.TestCase):
pass
test_vectors_sign = load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "PKCS1-v1.5"),
"SigGen15_186-2.txt",
"Signature Generation 186-2",
{ 'shaalg' : lambda x: x })
test_vectors_sign = load_test_vectors(("Signature", "PKCS1-v1.5"),
"SigGen15_186-2.txt",
"Signature Generation 186-2",
{'shaalg': lambda x: x}) or []
test_vectors_sign += load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "PKCS1-v1.5"),
"SigGen15_186-3.txt",
"Signature Generation 186-3",
{ 'shaalg' : lambda x: x })
test_vectors_sign += load_test_vectors(("Signature", "PKCS1-v1.5"),
"SigGen15_186-3.txt",
"Signature Generation 186-3",
{'shaalg': lambda x: x}) or []
for count, tv in enumerate(test_vectors_sign):
if isinstance(tv, str):
@ -254,59 +254,49 @@ class TestVectorsWycheproof(unittest.TestCase):
self.add_tests("rsa_signature_test.json")
def add_tests(self, filename):
comps = "Crypto.SelfTest.Signature.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, filename), "rt") as file_in:
tv_tree = json.load(file_in)
class TestVector(object):
pass
self.tv = []
for group in tv_tree['testGroups']:
key = RSA.import_key(group['keyPem'])
def filter_rsa(group):
return RSA.import_key(group['keyPem'])
def filter_sha(group):
hash_name = group['sha']
if hash_name == "SHA-512":
hash_module = SHA512
return SHA512
elif hash_name == "SHA-512/224":
hash_module = SHA512.new(truncate="224")
return SHA512.new(truncate="224")
elif hash_name == "SHA-512/256":
hash_module = SHA512.new(truncate="256")
return SHA512.new(truncate="256")
elif hash_name == "SHA3-512":
hash_module = SHA3_512
return SHA3_512
elif hash_name == "SHA-384":
hash_module = SHA384
return SHA384
elif hash_name == "SHA3-384":
hash_module = SHA3_384
return SHA3_384
elif hash_name == "SHA-256":
hash_module = SHA256
return SHA256
elif hash_name == "SHA3-256":
hash_module = SHA3_256
return SHA3_256
elif hash_name == "SHA-224":
hash_module = SHA224
return SHA224
elif hash_name == "SHA3-224":
hash_module = SHA3_224
return SHA3_224
elif hash_name == "SHA-1":
hash_module = SHA1
return SHA1
else:
raise ValueError("Unknown hash algorithm: " + hash_name)
def filter_type(group):
type_name = group['type']
if type_name not in ("RsassaPkcs1Verify", "RsassaPkcs1Generate"):
raise ValueError("Unknown type name " + type_name)
for test in group['tests']:
tv = TestVector()
tv.id = test['tcId']
tv.comment = test['comment']
for attr in 'msg', 'sig':
setattr(tv, attr, unhexlify(test[attr]))
tv.key = key
tv.hash_module = hash_module
tv.valid = test['result'] != "invalid"
tv.warning = test['result'] == "acceptable"
self.tv.append(tv)
result = load_test_vectors_wycheproof(("Signature", "wycheproof"),
filename,
"Wycheproof PKCS#1v1.5 signature (%s)" % filename,
group_tag={'rsa_key': filter_rsa,
'hash_mod': filter_sha,
'type': filter_type})
return result
def shortDescription(self):
return self._id

View file

@ -28,15 +28,13 @@
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import json
import unittest
from binascii import unhexlify
from Crypto.Util.py3compat import b, bchr
from Crypto.Util.number import bytes_to_long
from Crypto.Util.strxor import strxor
from Crypto.SelfTest.st_common import list_test_cases
from Crypto.SelfTest.loader import load_tests
from Crypto.SelfTest.loader import load_test_vectors, load_test_vectors_wycheproof
from Crypto.Hash import SHA1, SHA224, SHA256, SHA384, SHA512
from Crypto.PublicKey import RSA
@ -45,8 +43,6 @@ from Crypto.Signature import PKCS1_PSS
from Crypto.Signature.pss import MGF1
from Crypto.Util._file_system import pycryptodome_filename
def load_hash_by_name(hash_name):
return __import__("Crypto.Hash." + hash_name, globals(), locals(), ["new"])
@ -118,11 +114,11 @@ class FIPS_PKCS1_Verify_Tests_KAT(unittest.TestCase):
pass
test_vectors_verify = load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "PKCS1-PSS"),
"SigVerPSS_186-3.rsp",
"Signature Verification 186-3",
{ 'shaalg' : lambda x: x,
'result' : lambda x: x })
test_vectors_verify = load_test_vectors(("Signature", "PKCS1-PSS"),
"SigVerPSS_186-3.rsp",
"Signature Verification 186-3",
{'shaalg': lambda x: x,
'result': lambda x: x}) or []
for count, tv in enumerate(test_vectors_verify):
@ -136,7 +132,7 @@ for count, tv in enumerate(test_vectors_verify):
hash_module = load_hash_by_name(tv.shaalg.upper())
hash_obj = hash_module.new(tv.msg)
public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore
public_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e)]) # type: ignore
if tv.saltval != b("\x00"):
prng = PRNG(tv.saltval)
verifier = pss.new(public_key, salt_bytes=len(tv.saltval), rand_func=prng)
@ -170,15 +166,15 @@ class FIPS_PKCS1_Sign_Tests_KAT(unittest.TestCase):
pass
test_vectors_sign = load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "PKCS1-PSS"),
"SigGenPSS_186-2.txt",
"Signature Generation 186-2",
{ 'shaalg' : lambda x: x })
test_vectors_sign = load_test_vectors(("Signature", "PKCS1-PSS"),
"SigGenPSS_186-2.txt",
"Signature Generation 186-2",
{'shaalg': lambda x: x}) or []
test_vectors_sign += load_tests(("Crypto", "SelfTest", "Signature", "test_vectors", "PKCS1-PSS"),
"SigGenPSS_186-3.txt",
"Signature Generation 186-3",
{ 'shaalg' : lambda x: x })
test_vectors_sign += load_test_vectors(("Signature", "PKCS1-PSS"),
"SigGenPSS_186-3.txt",
"Signature Generation 186-3",
{'shaalg': lambda x: x}) or []
for count, tv in enumerate(test_vectors_sign):
if isinstance(tv, str):
@ -187,7 +183,7 @@ for count, tv in enumerate(test_vectors_sign):
modulus = tv.n
continue
if hasattr(tv, "e"):
private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore
private_key = RSA.construct([bytes_to_long(x) for x in (modulus, tv.e, tv.d)]) # type: ignore
continue
hash_module = load_hash_by_name(tv.shaalg.upper())
@ -280,41 +276,41 @@ class TestVectorsPSSWycheproof(unittest.TestCase):
self._id = "None"
def add_tests(self, filename):
comps = "Crypto.SelfTest.Signature.test_vectors.wycheproof".split(".")
with open(pycryptodome_filename(comps, filename), "rt") as file_in:
tv_tree = json.load(file_in)
for group in tv_tree['testGroups']:
def filter_rsa(group):
return RSA.import_key(group['keyPem'])
key = RSA.import_key(group['keyPem'])
hash_module = get_hash_module(group['sha'])
sLen = group['sLen']
def filter_sha(group):
return get_hash_module(group['sha'])
assert group['type'] == "RsassaPssVerify"
assert group['mgf'] == "MGF1"
def filter_type(group):
type_name = group['type']
if type_name not in ("RsassaPssVerify", ):
raise ValueError("Unknown type name " + type_name)
mgf1_hash = get_hash_module(group['mgfSha'])
def filter_slen(group):
return group['sLen']
def filter_mgf(group):
mgf = group['mgf']
if mgf not in ("MGF1", ):
raise ValueError("Unknown MGF " + mgf)
mgf1_hash = get_hash_module(group['mgfSha'])
def mgf(x, y, mh=mgf1_hash):
return MGF1(x, y, mh)
from collections import namedtuple
TestVector = namedtuple('TestVector', 'id comment msg sig key mgf sLen hash_module valid warning')
return mgf
for test in group['tests']:
tv = TestVector(
test['tcId'],
test['comment'],
unhexlify(test['msg']),
unhexlify(test['sig']),
key,
mgf,
sLen,
hash_module,
test['result'] != "invalid",
test['result'] == "acceptable"
)
self.tv.append(tv)
result = load_test_vectors_wycheproof(("Signature", "wycheproof"),
filename,
"Wycheproof PSS signature (%s)" % filename,
group_tag={'key': filter_rsa,
'hash_module': filter_sha,
'sLen': filter_slen,
'mgf': filter_mgf,
'type': filter_type})
return result
def setUp(self):
self.tv = []
@ -370,10 +366,12 @@ def get_tests(config={}):
tests += list_test_cases(FIPS_PKCS1_Verify_Tests_KAT)
tests += list_test_cases(FIPS_PKCS1_Sign_Tests_KAT)
tests += [ TestVectorsPSSWycheproof(wycheproof_warnings) ]
tests += [TestVectorsPSSWycheproof(wycheproof_warnings)]
return tests
if __name__ == '__main__':
suite = lambda: unittest.TestSuite(get_tests())
def suite():
return unittest.TestSuite(get_tests())
unittest.main(defaultTest='suite')

View file

@ -28,11 +28,19 @@
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
import os
import re
import sys
import json
import errno
import binascii
import warnings
from binascii import unhexlify
from Crypto.Util._file_system import pycryptodome_filename
try:
import pycryptodome_test_vectors # type: ignore
test_vectors_available = True
except ImportError:
test_vectors_available = False
def _load_tests(dir_comps, file_in, description, conversions):
@ -103,17 +111,94 @@ def _load_tests(dir_comps, file_in, description, conversions):
# This line is ignored
return results
def load_tests(dir_comps, file_name, description, conversions):
def load_test_vectors(dir_comps, file_name, description, conversions):
"""Load and parse a test vector file
This function returnis a list of objects, one per group of adjacent
This function returns a list of objects, one per group of adjacent
KV lines or for a single line in the form "[.*]".
For a group of lines, the object has one attribute per line.
"""
description = "%s test (%s)" % (description, file_name)
results = None
try:
if not test_vectors_available:
raise FileNotFoundError(errno.ENOENT,
os.strerror(errno.ENOENT),
file_name)
description = "%s test (%s)" % (description, file_name)
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(init_dir, *dir_comps, file_name)
with open(full_file_name) as file_in:
results = _load_tests(dir_comps, file_in, description, conversions)
except FileNotFoundError:
warnings.warn("Warning: skipping extended tests for " + description,
UserWarning,
stacklevel=2)
with open(pycryptodome_filename(dir_comps, file_name)) as file_in:
results = _load_tests(dir_comps, file_in, description, conversions)
return results
def load_test_vectors_wycheproof(dir_comps, file_name, description,
root_tag={}, group_tag={}, unit_tag={}):
result = []
try:
if not test_vectors_available:
raise FileNotFoundError(errno.ENOENT,
os.strerror(errno.ENOENT),
file_name)
init_dir = os.path.dirname(pycryptodome_test_vectors.__file__)
full_file_name = os.path.join(init_dir, *dir_comps, file_name)
with open(full_file_name) as file_in:
tv_tree = json.load(file_in)
except FileNotFoundError:
warnings.warn("Warning: skipping extended tests for " + description,
UserWarning,
stacklevel=2)
return result
class TestVector(object):
pass
common_root = {}
for k, v in root_tag.items():
common_root[k] = v(tv_tree)
for group in tv_tree['testGroups']:
common_group = {}
for k, v in group_tag.items():
common_group[k] = v(group)
for test in group['tests']:
tv = TestVector()
for k, v in common_root.items():
setattr(tv, k, v)
for k, v in common_group.items():
setattr(tv, k, v)
tv.id = test['tcId']
tv.comment = test['comment']
for attr in 'key', 'iv', 'aad', 'msg', 'ct', 'tag', 'label', 'ikm', 'salt', 'info', 'okm', 'sig':
if attr in test:
setattr(tv, attr, unhexlify(test[attr]))
tv.filename = file_name
for k, v in unit_tag.items():
setattr(tv, k, v(test))
tv.valid = test['result'] != "invalid"
tv.warning = test['result'] == "acceptable"
result.append(tv)
return result

View file

@ -40,6 +40,7 @@ from Crypto.Math.Numbers import Integer
from Crypto.Hash import HMAC
from Crypto.PublicKey.ECC import EccKey
from Crypto.PublicKey.DSA import DsaKey
class DssSigScheme(object):
@ -393,9 +394,11 @@ def new(key, mode, encoding='binary', randfunc=None):
if isinstance(key, EccKey):
order = key._curve.order
private_key_attr = 'd'
else:
elif isinstance(key, DsaKey):
order = Integer(key.q)
private_key_attr = 'x'
else:
raise ValueError("Unsupported key type " + str(type(key)))
if key.has_private():
private_key = getattr(key, private_key_attr)

View file

@ -271,34 +271,6 @@ package_data = {
"Crypto.Signature" : [ "*.pyi" ],
"Crypto.IO" : [ "*.pyi" ],
"Crypto.Util" : [ "*.pyi" ],
"Crypto.SelfTest.Cipher" : [
"test_vectors/AES/*.*",
"test_vectors/TDES/*.*",
"test_vectors/wycheproof/*.*",
],
"Crypto.SelfTest.Hash" : [
"test_vectors/SHA1/*.*",
"test_vectors/SHA2/*.*",
"test_vectors/SHA3/*.*",
"test_vectors/keccak/*.*",
"test_vectors/BLAKE2s/*.*",
"test_vectors/BLAKE2b/*.*",
"test_vectors/wycheproof/*.*",
],
"Crypto.SelfTest.Signature" : [
"test_vectors/DSA/*.*",
"test_vectors/ECDSA/*.*",
"test_vectors/PKCS1-v1.5/*.*",
"test_vectors/PKCS1-PSS/*.*",
"test_vectors/wycheproof/*.*",
],
"Crypto.SelfTest.PublicKey" : [
"test_vectors/ECC/*.*",
"test_vectors/RSA/*.*",
],
"Crypto.SelfTest.Protocol" : [
"test_vectors/wycheproof/*.*",
],
}
ext_modules = [
@ -494,7 +466,7 @@ setup(
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
],
license="BSD, Public Domain, Apache",
license="BSD, Public Domain",
packages=packages,
package_dir={"": "lib"},
package_data=package_data,

231
test_vectors/LICENSE.rst Normal file
View file

@ -0,0 +1,231 @@
BSD license
===========
All direct contributions to PyCryptodome are released under the following
license. The copyright of each piece belongs to the respective author.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Apache 2.0 license (Wycheproof)
===============================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

4
test_vectors/MANIFEST.in Normal file
View file

@ -0,0 +1,4 @@
include MANIFEST.in
include setup.py
graft pycryptodome_test_vectors
global-exclude __pycache__ *.pyc

Some files were not shown because too many files have changed in this diff Show more