second commit
This commit is contained in:
60
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__init__.py
vendored
Normal file
60
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__init__.py
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/__init__.py: Self-test for cipher modules
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-test for cipher modules"""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
from Crypto.SelfTest.Cipher import test_AES; tests += test_AES.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_ARC2; tests += test_ARC2.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_ARC4; tests += test_ARC4.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_Blowfish; tests += test_Blowfish.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_CAST; tests += test_CAST.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_DES3; tests += test_DES3.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_DES; tests += test_DES.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_Salsa20; tests += test_Salsa20.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_ChaCha20; tests += test_ChaCha20.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_ChaCha20_Poly1305; tests += test_ChaCha20_Poly1305.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_pkcs1_15; tests += test_pkcs1_15.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_pkcs1_oaep; tests += test_pkcs1_oaep.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_OCB; tests += test_OCB.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_CBC; tests += test_CBC.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_CFB; tests += test_CFB.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_OpenPGP; tests += test_OpenPGP.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_OFB; tests += test_OFB.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_CTR; tests += test_CTR.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_CCM; tests += test_CCM.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_EAX; tests += test_EAX.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_GCM; tests += test_GCM.get_tests(config=config)
|
||||
from Crypto.SelfTest.Cipher import test_SIV; tests += test_SIV.get_tests(config=config)
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/common.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/common.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_AES.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_AES.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_ARC2.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_ARC2.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_ARC4.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_ARC4.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_Blowfish.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_Blowfish.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CAST.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CAST.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CBC.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CBC.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CCM.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CCM.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CFB.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CFB.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CTR.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_CTR.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_ChaCha20.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_ChaCha20.cpython-311.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_DES.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_DES.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_DES3.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_DES3.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_EAX.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_EAX.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_GCM.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_GCM.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_OCB.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_OCB.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_OFB.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_OFB.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_OpenPGP.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_OpenPGP.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_SIV.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_SIV.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_Salsa20.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_Salsa20.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_15.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_15.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_oaep.cpython-311.pyc
vendored
Normal file
BIN
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_oaep.cpython-311.pyc
vendored
Normal file
Binary file not shown.
510
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/common.py
vendored
Normal file
510
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/common.py
vendored
Normal file
@ -0,0 +1,510 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Hash/common.py: Common code for Crypto.SelfTest.Hash
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-testing for PyCrypto hash modules"""
|
||||
|
||||
import unittest
|
||||
from binascii import a2b_hex, b2a_hex, hexlify
|
||||
|
||||
from Crypto.Util.py3compat import b
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
|
||||
class _NoDefault: pass # sentinel object
|
||||
def _extract(d, k, default=_NoDefault):
|
||||
"""Get an item from a dictionary, and remove it from the dictionary."""
|
||||
try:
|
||||
retval = d[k]
|
||||
except KeyError:
|
||||
if default is _NoDefault:
|
||||
raise
|
||||
return default
|
||||
del d[k]
|
||||
return retval
|
||||
|
||||
# Generic cipher test case
|
||||
class CipherSelfTest(unittest.TestCase):
|
||||
|
||||
def __init__(self, module, params):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
|
||||
# Extract the parameters
|
||||
params = params.copy()
|
||||
self.description = _extract(params, 'description')
|
||||
self.key = b(_extract(params, 'key'))
|
||||
self.plaintext = b(_extract(params, 'plaintext'))
|
||||
self.ciphertext = b(_extract(params, 'ciphertext'))
|
||||
self.module_name = _extract(params, 'module_name', None)
|
||||
self.assoc_data = _extract(params, 'assoc_data', None)
|
||||
self.mac = _extract(params, 'mac', None)
|
||||
if self.assoc_data:
|
||||
self.mac = b(self.mac)
|
||||
|
||||
mode = _extract(params, 'mode', None)
|
||||
self.mode_name = str(mode)
|
||||
|
||||
if mode is not None:
|
||||
# Block cipher
|
||||
self.mode = getattr(self.module, "MODE_" + mode)
|
||||
|
||||
self.iv = _extract(params, 'iv', None)
|
||||
if self.iv is None:
|
||||
self.iv = _extract(params, 'nonce', None)
|
||||
if self.iv is not None:
|
||||
self.iv = b(self.iv)
|
||||
|
||||
else:
|
||||
# Stream cipher
|
||||
self.mode = None
|
||||
self.iv = _extract(params, 'iv', None)
|
||||
if self.iv is not None:
|
||||
self.iv = b(self.iv)
|
||||
|
||||
self.extra_params = params
|
||||
|
||||
def shortDescription(self):
|
||||
return self.description
|
||||
|
||||
def _new(self):
|
||||
params = self.extra_params.copy()
|
||||
key = a2b_hex(self.key)
|
||||
|
||||
old_style = []
|
||||
if self.mode is not None:
|
||||
old_style = [ self.mode ]
|
||||
if self.iv is not None:
|
||||
old_style += [ a2b_hex(self.iv) ]
|
||||
|
||||
return self.module.new(key, *old_style, **params)
|
||||
|
||||
def isMode(self, name):
|
||||
if not hasattr(self.module, "MODE_"+name):
|
||||
return False
|
||||
return self.mode == getattr(self.module, "MODE_"+name)
|
||||
|
||||
def runTest(self):
|
||||
plaintext = a2b_hex(self.plaintext)
|
||||
ciphertext = a2b_hex(self.ciphertext)
|
||||
assoc_data = []
|
||||
if self.assoc_data:
|
||||
assoc_data = [ a2b_hex(b(x)) for x in self.assoc_data]
|
||||
|
||||
ct = None
|
||||
pt = None
|
||||
|
||||
#
|
||||
# Repeat the same encryption or decryption twice and verify
|
||||
# that the result is always the same
|
||||
#
|
||||
for i in range(2):
|
||||
cipher = self._new()
|
||||
decipher = self._new()
|
||||
|
||||
# Only AEAD modes
|
||||
for comp in assoc_data:
|
||||
cipher.update(comp)
|
||||
decipher.update(comp)
|
||||
|
||||
ctX = b2a_hex(cipher.encrypt(plaintext))
|
||||
ptX = b2a_hex(decipher.decrypt(ciphertext))
|
||||
|
||||
if ct:
|
||||
self.assertEqual(ct, ctX)
|
||||
self.assertEqual(pt, ptX)
|
||||
ct, pt = ctX, ptX
|
||||
|
||||
self.assertEqual(self.ciphertext, ct) # encrypt
|
||||
self.assertEqual(self.plaintext, pt) # decrypt
|
||||
|
||||
if self.mac:
|
||||
mac = b2a_hex(cipher.digest())
|
||||
self.assertEqual(self.mac, mac)
|
||||
decipher.verify(a2b_hex(self.mac))
|
||||
|
||||
class CipherStreamingSelfTest(CipherSelfTest):
|
||||
|
||||
def shortDescription(self):
|
||||
desc = self.module_name
|
||||
if self.mode is not None:
|
||||
desc += " in %s mode" % (self.mode_name,)
|
||||
return "%s should behave like a stream cipher" % (desc,)
|
||||
|
||||
def runTest(self):
|
||||
plaintext = a2b_hex(self.plaintext)
|
||||
ciphertext = a2b_hex(self.ciphertext)
|
||||
|
||||
# The cipher should work like a stream cipher
|
||||
|
||||
# Test counter mode encryption, 3 bytes at a time
|
||||
ct3 = []
|
||||
cipher = self._new()
|
||||
for i in range(0, len(plaintext), 3):
|
||||
ct3.append(cipher.encrypt(plaintext[i:i+3]))
|
||||
ct3 = b2a_hex(b("").join(ct3))
|
||||
self.assertEqual(self.ciphertext, ct3) # encryption (3 bytes at a time)
|
||||
|
||||
# Test counter mode decryption, 3 bytes at a time
|
||||
pt3 = []
|
||||
cipher = self._new()
|
||||
for i in range(0, len(ciphertext), 3):
|
||||
pt3.append(cipher.encrypt(ciphertext[i:i+3]))
|
||||
# PY3K: This is meant to be text, do not change to bytes (data)
|
||||
pt3 = b2a_hex(b("").join(pt3))
|
||||
self.assertEqual(self.plaintext, pt3) # decryption (3 bytes at a time)
|
||||
|
||||
|
||||
class RoundtripTest(unittest.TestCase):
|
||||
def __init__(self, module, params):
|
||||
from Crypto import Random
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
self.iv = Random.get_random_bytes(module.block_size)
|
||||
self.key = b(params['key'])
|
||||
self.plaintext = 100 * b(params['plaintext'])
|
||||
self.module_name = params.get('module_name', None)
|
||||
|
||||
def shortDescription(self):
|
||||
return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
## ECB mode
|
||||
mode = self.module.MODE_ECB
|
||||
encryption_cipher = self.module.new(a2b_hex(self.key), mode)
|
||||
ciphertext = encryption_cipher.encrypt(self.plaintext)
|
||||
decryption_cipher = self.module.new(a2b_hex(self.key), mode)
|
||||
decrypted_plaintext = decryption_cipher.decrypt(ciphertext)
|
||||
self.assertEqual(self.plaintext, decrypted_plaintext)
|
||||
|
||||
|
||||
class IVLengthTest(unittest.TestCase):
|
||||
def __init__(self, module, params):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
self.key = b(params['key'])
|
||||
|
||||
def shortDescription(self):
|
||||
return "Check that all modes except MODE_ECB and MODE_CTR require an IV of the proper length"
|
||||
|
||||
def runTest(self):
|
||||
self.assertRaises(TypeError, self.module.new, a2b_hex(self.key),
|
||||
self.module.MODE_ECB, b(""))
|
||||
|
||||
def _dummy_counter(self):
|
||||
return "\0" * self.module.block_size
|
||||
|
||||
|
||||
class NoDefaultECBTest(unittest.TestCase):
|
||||
def __init__(self, module, params):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
self.key = b(params['key'])
|
||||
|
||||
def runTest(self):
|
||||
self.assertRaises(TypeError, self.module.new, a2b_hex(self.key))
|
||||
|
||||
|
||||
class BlockSizeTest(unittest.TestCase):
|
||||
def __init__(self, module, params):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
self.key = a2b_hex(b(params['key']))
|
||||
|
||||
def runTest(self):
|
||||
cipher = self.module.new(self.key, self.module.MODE_ECB)
|
||||
self.assertEqual(cipher.block_size, self.module.block_size)
|
||||
|
||||
|
||||
class ByteArrayTest(unittest.TestCase):
|
||||
"""Verify we can use bytearray's for encrypting and decrypting"""
|
||||
|
||||
def __init__(self, module, params):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
|
||||
# Extract the parameters
|
||||
params = params.copy()
|
||||
self.description = _extract(params, 'description')
|
||||
self.key = b(_extract(params, 'key'))
|
||||
self.plaintext = b(_extract(params, 'plaintext'))
|
||||
self.ciphertext = b(_extract(params, 'ciphertext'))
|
||||
self.module_name = _extract(params, 'module_name', None)
|
||||
self.assoc_data = _extract(params, 'assoc_data', None)
|
||||
self.mac = _extract(params, 'mac', None)
|
||||
if self.assoc_data:
|
||||
self.mac = b(self.mac)
|
||||
|
||||
mode = _extract(params, 'mode', None)
|
||||
self.mode_name = str(mode)
|
||||
|
||||
if mode is not None:
|
||||
# Block cipher
|
||||
self.mode = getattr(self.module, "MODE_" + mode)
|
||||
|
||||
self.iv = _extract(params, 'iv', None)
|
||||
if self.iv is None:
|
||||
self.iv = _extract(params, 'nonce', None)
|
||||
if self.iv is not None:
|
||||
self.iv = b(self.iv)
|
||||
else:
|
||||
# Stream cipher
|
||||
self.mode = None
|
||||
self.iv = _extract(params, 'iv', None)
|
||||
if self.iv is not None:
|
||||
self.iv = b(self.iv)
|
||||
|
||||
self.extra_params = params
|
||||
|
||||
def _new(self):
|
||||
params = self.extra_params.copy()
|
||||
key = a2b_hex(self.key)
|
||||
|
||||
old_style = []
|
||||
if self.mode is not None:
|
||||
old_style = [ self.mode ]
|
||||
if self.iv is not None:
|
||||
old_style += [ a2b_hex(self.iv) ]
|
||||
|
||||
return self.module.new(key, *old_style, **params)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
plaintext = a2b_hex(self.plaintext)
|
||||
ciphertext = a2b_hex(self.ciphertext)
|
||||
assoc_data = []
|
||||
if self.assoc_data:
|
||||
assoc_data = [ bytearray(a2b_hex(b(x))) for x in self.assoc_data]
|
||||
|
||||
cipher = self._new()
|
||||
decipher = self._new()
|
||||
|
||||
# Only AEAD modes
|
||||
for comp in assoc_data:
|
||||
cipher.update(comp)
|
||||
decipher.update(comp)
|
||||
|
||||
ct = b2a_hex(cipher.encrypt(bytearray(plaintext)))
|
||||
pt = b2a_hex(decipher.decrypt(bytearray(ciphertext)))
|
||||
|
||||
self.assertEqual(self.ciphertext, ct) # encrypt
|
||||
self.assertEqual(self.plaintext, pt) # decrypt
|
||||
|
||||
if self.mac:
|
||||
mac = b2a_hex(cipher.digest())
|
||||
self.assertEqual(self.mac, mac)
|
||||
decipher.verify(bytearray(a2b_hex(self.mac)))
|
||||
|
||||
|
||||
class MemoryviewTest(unittest.TestCase):
|
||||
"""Verify we can use memoryviews for encrypting and decrypting"""
|
||||
|
||||
def __init__(self, module, params):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
|
||||
# Extract the parameters
|
||||
params = params.copy()
|
||||
self.description = _extract(params, 'description')
|
||||
self.key = b(_extract(params, 'key'))
|
||||
self.plaintext = b(_extract(params, 'plaintext'))
|
||||
self.ciphertext = b(_extract(params, 'ciphertext'))
|
||||
self.module_name = _extract(params, 'module_name', None)
|
||||
self.assoc_data = _extract(params, 'assoc_data', None)
|
||||
self.mac = _extract(params, 'mac', None)
|
||||
if self.assoc_data:
|
||||
self.mac = b(self.mac)
|
||||
|
||||
mode = _extract(params, 'mode', None)
|
||||
self.mode_name = str(mode)
|
||||
|
||||
if mode is not None:
|
||||
# Block cipher
|
||||
self.mode = getattr(self.module, "MODE_" + mode)
|
||||
|
||||
self.iv = _extract(params, 'iv', None)
|
||||
if self.iv is None:
|
||||
self.iv = _extract(params, 'nonce', None)
|
||||
if self.iv is not None:
|
||||
self.iv = b(self.iv)
|
||||
else:
|
||||
# Stream cipher
|
||||
self.mode = None
|
||||
self.iv = _extract(params, 'iv', None)
|
||||
if self.iv is not None:
|
||||
self.iv = b(self.iv)
|
||||
|
||||
self.extra_params = params
|
||||
|
||||
def _new(self):
|
||||
params = self.extra_params.copy()
|
||||
key = a2b_hex(self.key)
|
||||
|
||||
old_style = []
|
||||
if self.mode is not None:
|
||||
old_style = [ self.mode ]
|
||||
if self.iv is not None:
|
||||
old_style += [ a2b_hex(self.iv) ]
|
||||
|
||||
return self.module.new(key, *old_style, **params)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
plaintext = a2b_hex(self.plaintext)
|
||||
ciphertext = a2b_hex(self.ciphertext)
|
||||
assoc_data = []
|
||||
if self.assoc_data:
|
||||
assoc_data = [ memoryview(a2b_hex(b(x))) for x in self.assoc_data]
|
||||
|
||||
cipher = self._new()
|
||||
decipher = self._new()
|
||||
|
||||
# Only AEAD modes
|
||||
for comp in assoc_data:
|
||||
cipher.update(comp)
|
||||
decipher.update(comp)
|
||||
|
||||
ct = b2a_hex(cipher.encrypt(memoryview(plaintext)))
|
||||
pt = b2a_hex(decipher.decrypt(memoryview(ciphertext)))
|
||||
|
||||
self.assertEqual(self.ciphertext, ct) # encrypt
|
||||
self.assertEqual(self.plaintext, pt) # decrypt
|
||||
|
||||
if self.mac:
|
||||
mac = b2a_hex(cipher.digest())
|
||||
self.assertEqual(self.mac, mac)
|
||||
decipher.verify(memoryview(a2b_hex(self.mac)))
|
||||
|
||||
|
||||
def make_block_tests(module, module_name, test_data, additional_params=dict()):
|
||||
tests = []
|
||||
extra_tests_added = False
|
||||
for i in range(len(test_data)):
|
||||
row = test_data[i]
|
||||
|
||||
# Build the "params" dictionary with
|
||||
# - plaintext
|
||||
# - ciphertext
|
||||
# - key
|
||||
# - mode (default is ECB)
|
||||
# - (optionally) description
|
||||
# - (optionally) any other parameter that this cipher mode requires
|
||||
params = {}
|
||||
if len(row) == 3:
|
||||
(params['plaintext'], params['ciphertext'], params['key']) = row
|
||||
elif len(row) == 4:
|
||||
(params['plaintext'], params['ciphertext'], params['key'], params['description']) = row
|
||||
elif len(row) == 5:
|
||||
(params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row
|
||||
params.update(extra_params)
|
||||
else:
|
||||
raise AssertionError("Unsupported tuple size %d" % (len(row),))
|
||||
|
||||
if not "mode" in params:
|
||||
params["mode"] = "ECB"
|
||||
|
||||
# Build the display-name for the test
|
||||
p2 = params.copy()
|
||||
p_key = _extract(p2, 'key')
|
||||
p_plaintext = _extract(p2, 'plaintext')
|
||||
p_ciphertext = _extract(p2, 'ciphertext')
|
||||
p_mode = _extract(p2, 'mode')
|
||||
p_description = _extract(p2, 'description', None)
|
||||
|
||||
if p_description is not None:
|
||||
description = p_description
|
||||
elif p_mode == 'ECB' and not p2:
|
||||
description = "p=%s, k=%s" % (p_plaintext, p_key)
|
||||
else:
|
||||
description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2)
|
||||
name = "%s #%d: %s" % (module_name, i+1, description)
|
||||
params['description'] = name
|
||||
params['module_name'] = module_name
|
||||
params.update(additional_params)
|
||||
|
||||
# Add extra test(s) to the test suite before the current test
|
||||
if not extra_tests_added:
|
||||
tests += [
|
||||
RoundtripTest(module, params),
|
||||
IVLengthTest(module, params),
|
||||
NoDefaultECBTest(module, params),
|
||||
ByteArrayTest(module, params),
|
||||
BlockSizeTest(module, params),
|
||||
]
|
||||
extra_tests_added = True
|
||||
|
||||
# Add the current test to the test suite
|
||||
tests.append(CipherSelfTest(module, params))
|
||||
|
||||
return tests
|
||||
|
||||
def make_stream_tests(module, module_name, test_data):
|
||||
tests = []
|
||||
extra_tests_added = False
|
||||
for i in range(len(test_data)):
|
||||
row = test_data[i]
|
||||
|
||||
# Build the "params" dictionary
|
||||
params = {}
|
||||
if len(row) == 3:
|
||||
(params['plaintext'], params['ciphertext'], params['key']) = row
|
||||
elif len(row) == 4:
|
||||
(params['plaintext'], params['ciphertext'], params['key'], params['description']) = row
|
||||
elif len(row) == 5:
|
||||
(params['plaintext'], params['ciphertext'], params['key'], params['description'], extra_params) = row
|
||||
params.update(extra_params)
|
||||
else:
|
||||
raise AssertionError("Unsupported tuple size %d" % (len(row),))
|
||||
|
||||
# Build the display-name for the test
|
||||
p2 = params.copy()
|
||||
p_key = _extract(p2, 'key')
|
||||
p_plaintext = _extract(p2, 'plaintext')
|
||||
p_ciphertext = _extract(p2, 'ciphertext')
|
||||
p_description = _extract(p2, 'description', None)
|
||||
|
||||
if p_description is not None:
|
||||
description = p_description
|
||||
elif not p2:
|
||||
description = "p=%s, k=%s" % (p_plaintext, p_key)
|
||||
else:
|
||||
description = "p=%s, k=%s, %r" % (p_plaintext, p_key, p2)
|
||||
name = "%s #%d: %s" % (module_name, i+1, description)
|
||||
params['description'] = name
|
||||
params['module_name'] = module_name
|
||||
|
||||
# Add extra test(s) to the test suite before the current test
|
||||
if not extra_tests_added:
|
||||
tests += [
|
||||
ByteArrayTest(module, params),
|
||||
]
|
||||
|
||||
tests.append(MemoryviewTest(module, params))
|
||||
extra_tests_added = True
|
||||
|
||||
# Add the test to the test suite
|
||||
tests.append(CipherSelfTest(module, params))
|
||||
tests.append(CipherStreamingSelfTest(module, params))
|
||||
return tests
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
1351
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_AES.py
vendored
Normal file
1351
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_AES.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
167
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_ARC2.py
vendored
Normal file
167
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_ARC2.py
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/ARC2.py: Self-test for the Alleged-RC2 cipher
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-test suite for Crypto.Cipher.ARC2"""
|
||||
|
||||
import unittest
|
||||
|
||||
from Crypto.Util.py3compat import b, bchr
|
||||
|
||||
from Crypto.Cipher import ARC2
|
||||
|
||||
# This is a list of (plaintext, ciphertext, key[, description[, extra_params]]) tuples.
|
||||
test_data = [
|
||||
# Test vectors from RFC 2268
|
||||
|
||||
# 63-bit effective key length
|
||||
('0000000000000000', 'ebb773f993278eff', '0000000000000000',
|
||||
'RFC2268-1', dict(effective_keylen=63)),
|
||||
|
||||
# 64-bit effective key length
|
||||
('ffffffffffffffff', '278b27e42e2f0d49', 'ffffffffffffffff',
|
||||
'RFC2268-2', dict(effective_keylen=64)),
|
||||
('1000000000000001', '30649edf9be7d2c2', '3000000000000000',
|
||||
'RFC2268-3', dict(effective_keylen=64)),
|
||||
#('0000000000000000', '61a8a244adacccf0', '88',
|
||||
# 'RFC2268-4', dict(effective_keylen=64)),
|
||||
('0000000000000000', '6ccf4308974c267f', '88bca90e90875a',
|
||||
'RFC2268-5', dict(effective_keylen=64)),
|
||||
('0000000000000000', '1a807d272bbe5db1', '88bca90e90875a7f0f79c384627bafb2',
|
||||
'RFC2268-6', dict(effective_keylen=64)),
|
||||
|
||||
# 128-bit effective key length
|
||||
('0000000000000000', '2269552ab0f85ca6', '88bca90e90875a7f0f79c384627bafb2',
|
||||
"RFC2268-7", dict(effective_keylen=128)),
|
||||
('0000000000000000', '5b78d3a43dfff1f1',
|
||||
'88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e',
|
||||
"RFC2268-8", dict(effective_keylen=129)),
|
||||
|
||||
# Test vectors from PyCrypto 2.0.1's testdata.py
|
||||
# 1024-bit effective key length
|
||||
('0000000000000000', '624fb3e887419e48', '5068696c6970476c617373',
|
||||
'PCTv201-0'),
|
||||
('ffffffffffffffff', '79cadef44c4a5a85', '5068696c6970476c617373',
|
||||
'PCTv201-1'),
|
||||
('0001020304050607', '90411525b34e4c2c', '5068696c6970476c617373',
|
||||
'PCTv201-2'),
|
||||
('0011223344556677', '078656aaba61cbfb', '5068696c6970476c617373',
|
||||
'PCTv201-3'),
|
||||
('0000000000000000', 'd7bcc5dbb4d6e56a', 'ffffffffffffffff',
|
||||
'PCTv201-4'),
|
||||
('ffffffffffffffff', '7259018ec557b357', 'ffffffffffffffff',
|
||||
'PCTv201-5'),
|
||||
('0001020304050607', '93d20a497f2ccb62', 'ffffffffffffffff',
|
||||
'PCTv201-6'),
|
||||
('0011223344556677', 'cb15a7f819c0014d', 'ffffffffffffffff',
|
||||
'PCTv201-7'),
|
||||
('0000000000000000', '63ac98cdf3843a7a', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553',
|
||||
'PCTv201-8'),
|
||||
('ffffffffffffffff', '3fb49e2fa12371dd', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553',
|
||||
'PCTv201-9'),
|
||||
('0001020304050607', '46414781ab387d5f', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553',
|
||||
'PCTv201-10'),
|
||||
('0011223344556677', 'be09dc81feaca271', 'ffffffffffffffff5065746572477265656e6177617953e5ffe553',
|
||||
'PCTv201-11'),
|
||||
('0000000000000000', 'e64221e608be30ab', '53e5ffe553',
|
||||
'PCTv201-12'),
|
||||
('ffffffffffffffff', '862bc60fdcd4d9a9', '53e5ffe553',
|
||||
'PCTv201-13'),
|
||||
('0001020304050607', '6a34da50fa5e47de', '53e5ffe553',
|
||||
'PCTv201-14'),
|
||||
('0011223344556677', '584644c34503122c', '53e5ffe553',
|
||||
'PCTv201-15'),
|
||||
]
|
||||
|
||||
class BufferOverflowTest(unittest.TestCase):
|
||||
# Test a buffer overflow found in older versions of PyCrypto
|
||||
|
||||
def runTest(self):
|
||||
"""ARC2 with keylength > 128"""
|
||||
key = b("x") * 16384
|
||||
self.assertRaises(ValueError, ARC2.new, key, ARC2.MODE_ECB)
|
||||
|
||||
class KeyLength(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
ARC2.new(b'\x00' * 16, ARC2.MODE_ECB, effective_keylen=40)
|
||||
self.assertRaises(ValueError, ARC2.new, bchr(0) * 4, ARC2.MODE_ECB)
|
||||
self.assertRaises(ValueError, ARC2.new, bchr(0) * 129, ARC2.MODE_ECB)
|
||||
|
||||
self.assertRaises(ValueError, ARC2.new, bchr(0) * 16, ARC2.MODE_ECB,
|
||||
effective_keylen=39)
|
||||
self.assertRaises(ValueError, ARC2.new, bchr(0) * 16, ARC2.MODE_ECB,
|
||||
effective_keylen=1025)
|
||||
|
||||
|
||||
class TestOutput(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
# Encrypt/Decrypt data and test output parameter
|
||||
|
||||
cipher = ARC2.new(b'4'*16, ARC2.MODE_ECB)
|
||||
|
||||
pt = b'5' * 16
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(16)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
output = memoryview(bytearray(16))
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16)
|
||||
|
||||
shorter_output = bytearray(7)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
from Crypto.Cipher import ARC2
|
||||
from .common import make_block_tests
|
||||
|
||||
tests = make_block_tests(ARC2, "ARC2", test_data)
|
||||
tests.append(BufferOverflowTest())
|
||||
tests.append(KeyLength())
|
||||
tests += [TestOutput()]
|
||||
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
471
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_ARC4.py
vendored
Normal file
471
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_ARC4.py
vendored
Normal file
@ -0,0 +1,471 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/ARC4.py: Self-test for the Alleged-RC4 cipher
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-test suite for Crypto.Cipher.ARC4"""
|
||||
|
||||
import unittest
|
||||
|
||||
from Crypto.Util.py3compat import b
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
from binascii import unhexlify
|
||||
|
||||
from Crypto.Cipher import ARC4
|
||||
|
||||
# This is a list of (plaintext, ciphertext, key[, description]) tuples.
|
||||
test_data = [
|
||||
# Test vectors from Eric Rescorla's message with the subject
|
||||
# "RC4 compatibility testing", sent to the cipherpunks mailing list on
|
||||
# September 13, 1994.
|
||||
# http://cypherpunks.venona.com/date/1994/09/msg00420.html
|
||||
|
||||
('0123456789abcdef', '75b7878099e0c596', '0123456789abcdef',
|
||||
'Test vector 0'),
|
||||
|
||||
('0000000000000000', '7494c2e7104b0879', '0123456789abcdef',
|
||||
'Test vector 1'),
|
||||
|
||||
('0000000000000000', 'de188941a3375d3a', '0000000000000000',
|
||||
'Test vector 2'),
|
||||
|
||||
('00000000000000000000', 'd6a141a7ec3c38dfbd61', 'ef012345',
|
||||
'Test vector 3'),
|
||||
|
||||
('01' * 512,
|
||||
'7595c3e6114a09780c4ad452338e1ffd9a1be9498f813d76533449b6778dcad8'
|
||||
+ 'c78a8d2ba9ac66085d0e53d59c26c2d1c490c1ebbe0ce66d1b6b1b13b6b919b8'
|
||||
+ '47c25a91447a95e75e4ef16779cde8bf0a95850e32af9689444fd377108f98fd'
|
||||
+ 'cbd4e726567500990bcc7e0ca3c4aaa304a387d20f3b8fbbcd42a1bd311d7a43'
|
||||
+ '03dda5ab078896ae80c18b0af66dff319616eb784e495ad2ce90d7f772a81747'
|
||||
+ 'b65f62093b1e0db9e5ba532fafec47508323e671327df9444432cb7367cec82f'
|
||||
+ '5d44c0d00b67d650a075cd4b70dedd77eb9b10231b6b5b741347396d62897421'
|
||||
+ 'd43df9b42e446e358e9c11a9b2184ecbef0cd8e7a877ef968f1390ec9b3d35a5'
|
||||
+ '585cb009290e2fcde7b5ec66d9084be44055a619d9dd7fc3166f9487f7cb2729'
|
||||
+ '12426445998514c15d53a18c864ce3a2b7555793988126520eacf2e3066e230c'
|
||||
+ '91bee4dd5304f5fd0405b35bd99c73135d3d9bc335ee049ef69b3867bf2d7bd1'
|
||||
+ 'eaa595d8bfc0066ff8d31509eb0c6caa006c807a623ef84c3d33c195d23ee320'
|
||||
+ 'c40de0558157c822d4b8c569d849aed59d4e0fd7f379586b4b7ff684ed6a189f'
|
||||
+ '7486d49b9c4bad9ba24b96abf924372c8a8fffb10d55354900a77a3db5f205e1'
|
||||
+ 'b99fcd8660863a159ad4abe40fa48934163ddde542a6585540fd683cbfd8c00f'
|
||||
+ '12129a284deacc4cdefe58be7137541c047126c8d49e2755ab181ab7e940b0c0',
|
||||
'0123456789abcdef',
|
||||
"Test vector 4"),
|
||||
# shortest key - generated with arc4 package
|
||||
('7468697320697320616e206578616d706c65',
|
||||
'7260677d38495a09585d69321e17eaf3cdd0',
|
||||
'01'),
|
||||
]
|
||||
|
||||
|
||||
class RFC6229_Tests(unittest.TestCase):
|
||||
# Test vectors from RFC 6229. Each test vector is a tuple with two items:
|
||||
# the ARC4 key and a dictionary. The dictionary has keystream offsets as keys
|
||||
# and the 16-byte keystream starting at the relevant offset as value.
|
||||
rfc6229_data = [
|
||||
# Page 3
|
||||
(
|
||||
'0102030405',
|
||||
{
|
||||
0: 'b2 39 63 05 f0 3d c0 27 cc c3 52 4a 0a 11 18 a8',
|
||||
16: '69 82 94 4f 18 fc 82 d5 89 c4 03 a4 7a 0d 09 19',
|
||||
240: '28 cb 11 32 c9 6c e2 86 42 1d ca ad b8 b6 9e ae',
|
||||
256: '1c fc f6 2b 03 ed db 64 1d 77 df cf 7f 8d 8c 93',
|
||||
496: '42 b7 d0 cd d9 18 a8 a3 3d d5 17 81 c8 1f 40 41',
|
||||
512: '64 59 84 44 32 a7 da 92 3c fb 3e b4 98 06 61 f6',
|
||||
752: 'ec 10 32 7b de 2b ee fd 18 f9 27 76 80 45 7e 22',
|
||||
768: 'eb 62 63 8d 4f 0b a1 fe 9f ca 20 e0 5b f8 ff 2b',
|
||||
1008: '45 12 90 48 e6 a0 ed 0b 56 b4 90 33 8f 07 8d a5',
|
||||
1024: '30 ab bc c7 c2 0b 01 60 9f 23 ee 2d 5f 6b b7 df',
|
||||
1520: '32 94 f7 44 d8 f9 79 05 07 e7 0f 62 e5 bb ce ea',
|
||||
1536: 'd8 72 9d b4 18 82 25 9b ee 4f 82 53 25 f5 a1 30',
|
||||
2032: '1e b1 4a 0c 13 b3 bf 47 fa 2a 0b a9 3a d4 5b 8b',
|
||||
2048: 'cc 58 2f 8b a9 f2 65 e2 b1 be 91 12 e9 75 d2 d7',
|
||||
3056: 'f2 e3 0f 9b d1 02 ec bf 75 aa ad e9 bc 35 c4 3c',
|
||||
3072: 'ec 0e 11 c4 79 dc 32 9d c8 da 79 68 fe 96 56 81',
|
||||
4080: '06 83 26 a2 11 84 16 d2 1f 9d 04 b2 cd 1c a0 50',
|
||||
4096: 'ff 25 b5 89 95 99 67 07 e5 1f bd f0 8b 34 d8 75'
|
||||
}
|
||||
),
|
||||
# Page 4
|
||||
(
|
||||
'01020304050607',
|
||||
{
|
||||
0: '29 3f 02 d4 7f 37 c9 b6 33 f2 af 52 85 fe b4 6b',
|
||||
16: 'e6 20 f1 39 0d 19 bd 84 e2 e0 fd 75 20 31 af c1',
|
||||
240: '91 4f 02 53 1c 92 18 81 0d f6 0f 67 e3 38 15 4c',
|
||||
256: 'd0 fd b5 83 07 3c e8 5a b8 39 17 74 0e c0 11 d5',
|
||||
496: '75 f8 14 11 e8 71 cf fa 70 b9 0c 74 c5 92 e4 54',
|
||||
512: '0b b8 72 02 93 8d ad 60 9e 87 a5 a1 b0 79 e5 e4',
|
||||
752: 'c2 91 12 46 b6 12 e7 e7 b9 03 df ed a1 da d8 66',
|
||||
768: '32 82 8f 91 50 2b 62 91 36 8d e8 08 1d e3 6f c2',
|
||||
1008: 'f3 b9 a7 e3 b2 97 bf 9a d8 04 51 2f 90 63 ef f1',
|
||||
1024: '8e cb 67 a9 ba 1f 55 a5 a0 67 e2 b0 26 a3 67 6f',
|
||||
1520: 'd2 aa 90 2b d4 2d 0d 7c fd 34 0c d4 58 10 52 9f',
|
||||
1536: '78 b2 72 c9 6e 42 ea b4 c6 0b d9 14 e3 9d 06 e3',
|
||||
2032: 'f4 33 2f d3 1a 07 93 96 ee 3c ee 3f 2a 4f f0 49',
|
||||
2048: '05 45 97 81 d4 1f da 7f 30 c1 be 7e 12 46 c6 23',
|
||||
3056: 'ad fd 38 68 b8 e5 14 85 d5 e6 10 01 7e 3d d6 09',
|
||||
3072: 'ad 26 58 1c 0c 5b e4 5f 4c ea 01 db 2f 38 05 d5',
|
||||
4080: 'f3 17 2c ef fc 3b 3d 99 7c 85 cc d5 af 1a 95 0c',
|
||||
4096: 'e7 4b 0b 97 31 22 7f d3 7c 0e c0 8a 47 dd d8 b8'
|
||||
}
|
||||
),
|
||||
(
|
||||
'0102030405060708',
|
||||
{
|
||||
0: '97 ab 8a 1b f0 af b9 61 32 f2 f6 72 58 da 15 a8',
|
||||
16: '82 63 ef db 45 c4 a1 86 84 ef 87 e6 b1 9e 5b 09',
|
||||
240: '96 36 eb c9 84 19 26 f4 f7 d1 f3 62 bd df 6e 18',
|
||||
256: 'd0 a9 90 ff 2c 05 fe f5 b9 03 73 c9 ff 4b 87 0a',
|
||||
496: '73 23 9f 1d b7 f4 1d 80 b6 43 c0 c5 25 18 ec 63',
|
||||
512: '16 3b 31 99 23 a6 bd b4 52 7c 62 61 26 70 3c 0f',
|
||||
752: '49 d6 c8 af 0f 97 14 4a 87 df 21 d9 14 72 f9 66',
|
||||
768: '44 17 3a 10 3b 66 16 c5 d5 ad 1c ee 40 c8 63 d0',
|
||||
1008: '27 3c 9c 4b 27 f3 22 e4 e7 16 ef 53 a4 7d e7 a4',
|
||||
1024: 'c6 d0 e7 b2 26 25 9f a9 02 34 90 b2 61 67 ad 1d',
|
||||
1520: '1f e8 98 67 13 f0 7c 3d 9a e1 c1 63 ff 8c f9 d3',
|
||||
1536: '83 69 e1 a9 65 61 0b e8 87 fb d0 c7 91 62 aa fb',
|
||||
2032: '0a 01 27 ab b4 44 84 b9 fb ef 5a bc ae 1b 57 9f',
|
||||
2048: 'c2 cd ad c6 40 2e 8e e8 66 e1 f3 7b db 47 e4 2c',
|
||||
3056: '26 b5 1e a3 7d f8 e1 d6 f7 6f c3 b6 6a 74 29 b3',
|
||||
3072: 'bc 76 83 20 5d 4f 44 3d c1 f2 9d da 33 15 c8 7b',
|
||||
4080: 'd5 fa 5a 34 69 d2 9a aa f8 3d 23 58 9d b8 c8 5b',
|
||||
4096: '3f b4 6e 2c 8f 0f 06 8e dc e8 cd cd 7d fc 58 62'
|
||||
}
|
||||
),
|
||||
# Page 5
|
||||
(
|
||||
'0102030405060708090a',
|
||||
{
|
||||
0: 'ed e3 b0 46 43 e5 86 cc 90 7d c2 18 51 70 99 02',
|
||||
16: '03 51 6b a7 8f 41 3b eb 22 3a a5 d4 d2 df 67 11',
|
||||
240: '3c fd 6c b5 8e e0 fd de 64 01 76 ad 00 00 04 4d',
|
||||
256: '48 53 2b 21 fb 60 79 c9 11 4c 0f fd 9c 04 a1 ad',
|
||||
496: '3e 8c ea 98 01 71 09 97 90 84 b1 ef 92 f9 9d 86',
|
||||
512: 'e2 0f b4 9b db 33 7e e4 8b 8d 8d c0 f4 af ef fe',
|
||||
752: '5c 25 21 ea cd 79 66 f1 5e 05 65 44 be a0 d3 15',
|
||||
768: 'e0 67 a7 03 19 31 a2 46 a6 c3 87 5d 2f 67 8a cb',
|
||||
1008: 'a6 4f 70 af 88 ae 56 b6 f8 75 81 c0 e2 3e 6b 08',
|
||||
1024: 'f4 49 03 1d e3 12 81 4e c6 f3 19 29 1f 4a 05 16',
|
||||
1520: 'bd ae 85 92 4b 3c b1 d0 a2 e3 3a 30 c6 d7 95 99',
|
||||
1536: '8a 0f ed db ac 86 5a 09 bc d1 27 fb 56 2e d6 0a',
|
||||
2032: 'b5 5a 0a 5b 51 a1 2a 8b e3 48 99 c3 e0 47 51 1a',
|
||||
2048: 'd9 a0 9c ea 3c e7 5f e3 96 98 07 03 17 a7 13 39',
|
||||
3056: '55 22 25 ed 11 77 f4 45 84 ac 8c fa 6c 4e b5 fc',
|
||||
3072: '7e 82 cb ab fc 95 38 1b 08 09 98 44 21 29 c2 f8',
|
||||
4080: '1f 13 5e d1 4c e6 0a 91 36 9d 23 22 be f2 5e 3c',
|
||||
4096: '08 b6 be 45 12 4a 43 e2 eb 77 95 3f 84 dc 85 53'
|
||||
}
|
||||
),
|
||||
(
|
||||
'0102030405060708090a0b0c0d0e0f10',
|
||||
{
|
||||
0: '9a c7 cc 9a 60 9d 1e f7 b2 93 28 99 cd e4 1b 97',
|
||||
16: '52 48 c4 95 90 14 12 6a 6e 8a 84 f1 1d 1a 9e 1c',
|
||||
240: '06 59 02 e4 b6 20 f6 cc 36 c8 58 9f 66 43 2f 2b',
|
||||
256: 'd3 9d 56 6b c6 bc e3 01 07 68 15 15 49 f3 87 3f',
|
||||
496: 'b6 d1 e6 c4 a5 e4 77 1c ad 79 53 8d f2 95 fb 11',
|
||||
512: 'c6 8c 1d 5c 55 9a 97 41 23 df 1d bc 52 a4 3b 89',
|
||||
752: 'c5 ec f8 8d e8 97 fd 57 fe d3 01 70 1b 82 a2 59',
|
||||
768: 'ec cb e1 3d e1 fc c9 1c 11 a0 b2 6c 0b c8 fa 4d',
|
||||
1008: 'e7 a7 25 74 f8 78 2a e2 6a ab cf 9e bc d6 60 65',
|
||||
1024: 'bd f0 32 4e 60 83 dc c6 d3 ce dd 3c a8 c5 3c 16',
|
||||
1520: 'b4 01 10 c4 19 0b 56 22 a9 61 16 b0 01 7e d2 97',
|
||||
1536: 'ff a0 b5 14 64 7e c0 4f 63 06 b8 92 ae 66 11 81',
|
||||
2032: 'd0 3d 1b c0 3c d3 3d 70 df f9 fa 5d 71 96 3e bd',
|
||||
2048: '8a 44 12 64 11 ea a7 8b d5 1e 8d 87 a8 87 9b f5',
|
||||
3056: 'fa be b7 60 28 ad e2 d0 e4 87 22 e4 6c 46 15 a3',
|
||||
3072: 'c0 5d 88 ab d5 03 57 f9 35 a6 3c 59 ee 53 76 23',
|
||||
4080: 'ff 38 26 5c 16 42 c1 ab e8 d3 c2 fe 5e 57 2b f8',
|
||||
4096: 'a3 6a 4c 30 1a e8 ac 13 61 0c cb c1 22 56 ca cc'
|
||||
}
|
||||
),
|
||||
# Page 6
|
||||
(
|
||||
'0102030405060708090a0b0c0d0e0f101112131415161718',
|
||||
{
|
||||
0: '05 95 e5 7f e5 f0 bb 3c 70 6e da c8 a4 b2 db 11',
|
||||
16: 'df de 31 34 4a 1a f7 69 c7 4f 07 0a ee 9e 23 26',
|
||||
240: 'b0 6b 9b 1e 19 5d 13 d8 f4 a7 99 5c 45 53 ac 05',
|
||||
256: '6b d2 37 8e c3 41 c9 a4 2f 37 ba 79 f8 8a 32 ff',
|
||||
496: 'e7 0b ce 1d f7 64 5a db 5d 2c 41 30 21 5c 35 22',
|
||||
512: '9a 57 30 c7 fc b4 c9 af 51 ff da 89 c7 f1 ad 22',
|
||||
752: '04 85 05 5f d4 f6 f0 d9 63 ef 5a b9 a5 47 69 82',
|
||||
768: '59 1f c6 6b cd a1 0e 45 2b 03 d4 55 1f 6b 62 ac',
|
||||
1008: '27 53 cc 83 98 8a fa 3e 16 88 a1 d3 b4 2c 9a 02',
|
||||
1024: '93 61 0d 52 3d 1d 3f 00 62 b3 c2 a3 bb c7 c7 f0',
|
||||
1520: '96 c2 48 61 0a ad ed fe af 89 78 c0 3d e8 20 5a',
|
||||
1536: '0e 31 7b 3d 1c 73 b9 e9 a4 68 8f 29 6d 13 3a 19',
|
||||
2032: 'bd f0 e6 c3 cc a5 b5 b9 d5 33 b6 9c 56 ad a1 20',
|
||||
2048: '88 a2 18 b6 e2 ec e1 e6 24 6d 44 c7 59 d1 9b 10',
|
||||
3056: '68 66 39 7e 95 c1 40 53 4f 94 26 34 21 00 6e 40',
|
||||
3072: '32 cb 0a 1e 95 42 c6 b3 b8 b3 98 ab c3 b0 f1 d5',
|
||||
4080: '29 a0 b8 ae d5 4a 13 23 24 c6 2e 42 3f 54 b4 c8',
|
||||
4096: '3c b0 f3 b5 02 0a 98 b8 2a f9 fe 15 44 84 a1 68'
|
||||
}
|
||||
),
|
||||
(
|
||||
'0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
{
|
||||
0: 'ea a6 bd 25 88 0b f9 3d 3f 5d 1e 4c a2 61 1d 91',
|
||||
16: 'cf a4 5c 9f 7e 71 4b 54 bd fa 80 02 7c b1 43 80',
|
||||
240: '11 4a e3 44 de d7 1b 35 f2 e6 0f eb ad 72 7f d8',
|
||||
256: '02 e1 e7 05 6b 0f 62 39 00 49 64 22 94 3e 97 b6',
|
||||
496: '91 cb 93 c7 87 96 4e 10 d9 52 7d 99 9c 6f 93 6b',
|
||||
512: '49 b1 8b 42 f8 e8 36 7c be b5 ef 10 4b a1 c7 cd',
|
||||
752: '87 08 4b 3b a7 00 ba de 95 56 10 67 27 45 b3 74',
|
||||
768: 'e7 a7 b9 e9 ec 54 0d 5f f4 3b db 12 79 2d 1b 35',
|
||||
1008: 'c7 99 b5 96 73 8f 6b 01 8c 76 c7 4b 17 59 bd 90',
|
||||
1024: '7f ec 5b fd 9f 9b 89 ce 65 48 30 90 92 d7 e9 58',
|
||||
1520: '40 f2 50 b2 6d 1f 09 6a 4a fd 4c 34 0a 58 88 15',
|
||||
1536: '3e 34 13 5c 79 db 01 02 00 76 76 51 cf 26 30 73',
|
||||
2032: 'f6 56 ab cc f8 8d d8 27 02 7b 2c e9 17 d4 64 ec',
|
||||
2048: '18 b6 25 03 bf bc 07 7f ba bb 98 f2 0d 98 ab 34',
|
||||
3056: '8a ed 95 ee 5b 0d cb fb ef 4e b2 1d 3a 3f 52 f9',
|
||||
3072: '62 5a 1a b0 0e e3 9a 53 27 34 6b dd b0 1a 9c 18',
|
||||
4080: 'a1 3a 7c 79 c7 e1 19 b5 ab 02 96 ab 28 c3 00 b9',
|
||||
4096: 'f3 e4 c0 a2 e0 2d 1d 01 f7 f0 a7 46 18 af 2b 48'
|
||||
}
|
||||
),
|
||||
# Page 7
|
||||
(
|
||||
'833222772a',
|
||||
{
|
||||
0: '80 ad 97 bd c9 73 df 8a 2e 87 9e 92 a4 97 ef da',
|
||||
16: '20 f0 60 c2 f2 e5 12 65 01 d3 d4 fe a1 0d 5f c0',
|
||||
240: 'fa a1 48 e9 90 46 18 1f ec 6b 20 85 f3 b2 0e d9',
|
||||
256: 'f0 da f5 ba b3 d5 96 83 98 57 84 6f 73 fb fe 5a',
|
||||
496: '1c 7e 2f c4 63 92 32 fe 29 75 84 b2 96 99 6b c8',
|
||||
512: '3d b9 b2 49 40 6c c8 ed ff ac 55 cc d3 22 ba 12',
|
||||
752: 'e4 f9 f7 e0 06 61 54 bb d1 25 b7 45 56 9b c8 97',
|
||||
768: '75 d5 ef 26 2b 44 c4 1a 9c f6 3a e1 45 68 e1 b9',
|
||||
1008: '6d a4 53 db f8 1e 82 33 4a 3d 88 66 cb 50 a1 e3',
|
||||
1024: '78 28 d0 74 11 9c ab 5c 22 b2 94 d7 a9 bf a0 bb',
|
||||
1520: 'ad b8 9c ea 9a 15 fb e6 17 29 5b d0 4b 8c a0 5c',
|
||||
1536: '62 51 d8 7f d4 aa ae 9a 7e 4a d5 c2 17 d3 f3 00',
|
||||
2032: 'e7 11 9b d6 dd 9b 22 af e8 f8 95 85 43 28 81 e2',
|
||||
2048: '78 5b 60 fd 7e c4 e9 fc b6 54 5f 35 0d 66 0f ab',
|
||||
3056: 'af ec c0 37 fd b7 b0 83 8e b3 d7 0b cd 26 83 82',
|
||||
3072: 'db c1 a7 b4 9d 57 35 8c c9 fa 6d 61 d7 3b 7c f0',
|
||||
4080: '63 49 d1 26 a3 7a fc ba 89 79 4f 98 04 91 4f dc',
|
||||
4096: 'bf 42 c3 01 8c 2f 7c 66 bf de 52 49 75 76 81 15'
|
||||
}
|
||||
),
|
||||
(
|
||||
'1910833222772a',
|
||||
{
|
||||
0: 'bc 92 22 db d3 27 4d 8f c6 6d 14 cc bd a6 69 0b',
|
||||
16: '7a e6 27 41 0c 9a 2b e6 93 df 5b b7 48 5a 63 e3',
|
||||
240: '3f 09 31 aa 03 de fb 30 0f 06 01 03 82 6f 2a 64',
|
||||
256: 'be aa 9e c8 d5 9b b6 81 29 f3 02 7c 96 36 11 81',
|
||||
496: '74 e0 4d b4 6d 28 64 8d 7d ee 8a 00 64 b0 6c fe',
|
||||
512: '9b 5e 81 c6 2f e0 23 c5 5b e4 2f 87 bb f9 32 b8',
|
||||
752: 'ce 17 8f c1 82 6e fe cb c1 82 f5 79 99 a4 61 40',
|
||||
768: '8b df 55 cd 55 06 1c 06 db a6 be 11 de 4a 57 8a',
|
||||
1008: '62 6f 5f 4d ce 65 25 01 f3 08 7d 39 c9 2c c3 49',
|
||||
1024: '42 da ac 6a 8f 9a b9 a7 fd 13 7c 60 37 82 56 82',
|
||||
1520: 'cc 03 fd b7 91 92 a2 07 31 2f 53 f5 d4 dc 33 d9',
|
||||
1536: 'f7 0f 14 12 2a 1c 98 a3 15 5d 28 b8 a0 a8 a4 1d',
|
||||
2032: '2a 3a 30 7a b2 70 8a 9c 00 fe 0b 42 f9 c2 d6 a1',
|
||||
2048: '86 26 17 62 7d 22 61 ea b0 b1 24 65 97 ca 0a e9',
|
||||
3056: '55 f8 77 ce 4f 2e 1d db bf 8e 13 e2 cd e0 fd c8',
|
||||
3072: '1b 15 56 cb 93 5f 17 33 37 70 5f bb 5d 50 1f c1',
|
||||
4080: 'ec d0 e9 66 02 be 7f 8d 50 92 81 6c cc f2 c2 e9',
|
||||
4096: '02 78 81 fa b4 99 3a 1c 26 20 24 a9 4f ff 3f 61'
|
||||
}
|
||||
),
|
||||
# Page 8
|
||||
(
|
||||
'641910833222772a',
|
||||
{
|
||||
0: 'bb f6 09 de 94 13 17 2d 07 66 0c b6 80 71 69 26',
|
||||
16: '46 10 1a 6d ab 43 11 5d 6c 52 2b 4f e9 36 04 a9',
|
||||
240: 'cb e1 ff f2 1c 96 f3 ee f6 1e 8f e0 54 2c bd f0',
|
||||
256: '34 79 38 bf fa 40 09 c5 12 cf b4 03 4b 0d d1 a7',
|
||||
496: '78 67 a7 86 d0 0a 71 47 90 4d 76 dd f1 e5 20 e3',
|
||||
512: '8d 3e 9e 1c ae fc cc b3 fb f8 d1 8f 64 12 0b 32',
|
||||
752: '94 23 37 f8 fd 76 f0 fa e8 c5 2d 79 54 81 06 72',
|
||||
768: 'b8 54 8c 10 f5 16 67 f6 e6 0e 18 2f a1 9b 30 f7',
|
||||
1008: '02 11 c7 c6 19 0c 9e fd 12 37 c3 4c 8f 2e 06 c4',
|
||||
1024: 'bd a6 4f 65 27 6d 2a ac b8 f9 02 12 20 3a 80 8e',
|
||||
1520: 'bd 38 20 f7 32 ff b5 3e c1 93 e7 9d 33 e2 7c 73',
|
||||
1536: 'd0 16 86 16 86 19 07 d4 82 e3 6c da c8 cf 57 49',
|
||||
2032: '97 b0 f0 f2 24 b2 d2 31 71 14 80 8f b0 3a f7 a0',
|
||||
2048: 'e5 96 16 e4 69 78 79 39 a0 63 ce ea 9a f9 56 d1',
|
||||
3056: 'c4 7e 0d c1 66 09 19 c1 11 01 20 8f 9e 69 aa 1f',
|
||||
3072: '5a e4 f1 28 96 b8 37 9a 2a ad 89 b5 b5 53 d6 b0',
|
||||
4080: '6b 6b 09 8d 0c 29 3b c2 99 3d 80 bf 05 18 b6 d9',
|
||||
4096: '81 70 cc 3c cd 92 a6 98 62 1b 93 9d d3 8f e7 b9'
|
||||
}
|
||||
),
|
||||
(
|
||||
'8b37641910833222772a',
|
||||
{
|
||||
0: 'ab 65 c2 6e dd b2 87 60 0d b2 fd a1 0d 1e 60 5c',
|
||||
16: 'bb 75 90 10 c2 96 58 f2 c7 2d 93 a2 d1 6d 29 30',
|
||||
240: 'b9 01 e8 03 6e d1 c3 83 cd 3c 4c 4d d0 a6 ab 05',
|
||||
256: '3d 25 ce 49 22 92 4c 55 f0 64 94 33 53 d7 8a 6c',
|
||||
496: '12 c1 aa 44 bb f8 7e 75 e6 11 f6 9b 2c 38 f4 9b',
|
||||
512: '28 f2 b3 43 4b 65 c0 98 77 47 00 44 c6 ea 17 0d',
|
||||
752: 'bd 9e f8 22 de 52 88 19 61 34 cf 8a f7 83 93 04',
|
||||
768: '67 55 9c 23 f0 52 15 84 70 a2 96 f7 25 73 5a 32',
|
||||
1008: '8b ab 26 fb c2 c1 2b 0f 13 e2 ab 18 5e ab f2 41',
|
||||
1024: '31 18 5a 6d 69 6f 0c fa 9b 42 80 8b 38 e1 32 a2',
|
||||
1520: '56 4d 3d ae 18 3c 52 34 c8 af 1e 51 06 1c 44 b5',
|
||||
1536: '3c 07 78 a7 b5 f7 2d 3c 23 a3 13 5c 7d 67 b9 f4',
|
||||
2032: 'f3 43 69 89 0f cf 16 fb 51 7d ca ae 44 63 b2 dd',
|
||||
2048: '02 f3 1c 81 e8 20 07 31 b8 99 b0 28 e7 91 bf a7',
|
||||
3056: '72 da 64 62 83 22 8c 14 30 08 53 70 17 95 61 6f',
|
||||
3072: '4e 0a 8c 6f 79 34 a7 88 e2 26 5e 81 d6 d0 c8 f4',
|
||||
4080: '43 8d d5 ea fe a0 11 1b 6f 36 b4 b9 38 da 2a 68',
|
||||
4096: '5f 6b fc 73 81 58 74 d9 71 00 f0 86 97 93 57 d8'
|
||||
}
|
||||
),
|
||||
# Page 9
|
||||
(
|
||||
'ebb46227c6cc8b37641910833222772a',
|
||||
{
|
||||
0: '72 0c 94 b6 3e df 44 e1 31 d9 50 ca 21 1a 5a 30',
|
||||
16: 'c3 66 fd ea cf 9c a8 04 36 be 7c 35 84 24 d2 0b',
|
||||
240: 'b3 39 4a 40 aa bf 75 cb a4 22 82 ef 25 a0 05 9f',
|
||||
256: '48 47 d8 1d a4 94 2d bc 24 9d ef c4 8c 92 2b 9f',
|
||||
496: '08 12 8c 46 9f 27 53 42 ad da 20 2b 2b 58 da 95',
|
||||
512: '97 0d ac ef 40 ad 98 72 3b ac 5d 69 55 b8 17 61',
|
||||
752: '3c b8 99 93 b0 7b 0c ed 93 de 13 d2 a1 10 13 ac',
|
||||
768: 'ef 2d 67 6f 15 45 c2 c1 3d c6 80 a0 2f 4a db fe',
|
||||
1008: 'b6 05 95 51 4f 24 bc 9f e5 22 a6 ca d7 39 36 44',
|
||||
1024: 'b5 15 a8 c5 01 17 54 f5 90 03 05 8b db 81 51 4e',
|
||||
1520: '3c 70 04 7e 8c bc 03 8e 3b 98 20 db 60 1d a4 95',
|
||||
1536: '11 75 da 6e e7 56 de 46 a5 3e 2b 07 56 60 b7 70',
|
||||
2032: '00 a5 42 bb a0 21 11 cc 2c 65 b3 8e bd ba 58 7e',
|
||||
2048: '58 65 fd bb 5b 48 06 41 04 e8 30 b3 80 f2 ae de',
|
||||
3056: '34 b2 1a d2 ad 44 e9 99 db 2d 7f 08 63 f0 d9 b6',
|
||||
3072: '84 a9 21 8f c3 6e 8a 5f 2c cf be ae 53 a2 7d 25',
|
||||
4080: 'a2 22 1a 11 b8 33 cc b4 98 a5 95 40 f0 54 5f 4a',
|
||||
4096: '5b be b4 78 7d 59 e5 37 3f db ea 6c 6f 75 c2 9b'
|
||||
}
|
||||
),
|
||||
(
|
||||
'c109163908ebe51debb46227c6cc8b37641910833222772a',
|
||||
{
|
||||
0: '54 b6 4e 6b 5a 20 b5 e2 ec 84 59 3d c7 98 9d a7',
|
||||
16: 'c1 35 ee e2 37 a8 54 65 ff 97 dc 03 92 4f 45 ce',
|
||||
240: 'cf cc 92 2f b4 a1 4a b4 5d 61 75 aa bb f2 d2 01',
|
||||
256: '83 7b 87 e2 a4 46 ad 0e f7 98 ac d0 2b 94 12 4f',
|
||||
496: '17 a6 db d6 64 92 6a 06 36 b3 f4 c3 7a 4f 46 94',
|
||||
512: '4a 5f 9f 26 ae ee d4 d4 a2 5f 63 2d 30 52 33 d9',
|
||||
752: '80 a3 d0 1e f0 0c 8e 9a 42 09 c1 7f 4e eb 35 8c',
|
||||
768: 'd1 5e 7d 5f fa aa bc 02 07 bf 20 0a 11 77 93 a2',
|
||||
1008: '34 96 82 bf 58 8e aa 52 d0 aa 15 60 34 6a ea fa',
|
||||
1024: 'f5 85 4c db 76 c8 89 e3 ad 63 35 4e 5f 72 75 e3',
|
||||
1520: '53 2c 7c ec cb 39 df 32 36 31 84 05 a4 b1 27 9c',
|
||||
1536: 'ba ef e6 d9 ce b6 51 84 22 60 e0 d1 e0 5e 3b 90',
|
||||
2032: 'e8 2d 8c 6d b5 4e 3c 63 3f 58 1c 95 2b a0 42 07',
|
||||
2048: '4b 16 e5 0a bd 38 1b d7 09 00 a9 cd 9a 62 cb 23',
|
||||
3056: '36 82 ee 33 bd 14 8b d9 f5 86 56 cd 8f 30 d9 fb',
|
||||
3072: '1e 5a 0b 84 75 04 5d 9b 20 b2 62 86 24 ed fd 9e',
|
||||
4080: '63 ed d6 84 fb 82 62 82 fe 52 8f 9c 0e 92 37 bc',
|
||||
4096: 'e4 dd 2e 98 d6 96 0f ae 0b 43 54 54 56 74 33 91'
|
||||
}
|
||||
),
|
||||
# Page 10
|
||||
(
|
||||
'1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a',
|
||||
{
|
||||
0: 'dd 5b cb 00 18 e9 22 d4 94 75 9d 7c 39 5d 02 d3',
|
||||
16: 'c8 44 6f 8f 77 ab f7 37 68 53 53 eb 89 a1 c9 eb',
|
||||
240: 'af 3e 30 f9 c0 95 04 59 38 15 15 75 c3 fb 90 98',
|
||||
256: 'f8 cb 62 74 db 99 b8 0b 1d 20 12 a9 8e d4 8f 0e',
|
||||
496: '25 c3 00 5a 1c b8 5d e0 76 25 98 39 ab 71 98 ab',
|
||||
512: '9d cb c1 83 e8 cb 99 4b 72 7b 75 be 31 80 76 9c',
|
||||
752: 'a1 d3 07 8d fa 91 69 50 3e d9 d4 49 1d ee 4e b2',
|
||||
768: '85 14 a5 49 58 58 09 6f 59 6e 4b cd 66 b1 06 65',
|
||||
1008: '5f 40 d5 9e c1 b0 3b 33 73 8e fa 60 b2 25 5d 31',
|
||||
1024: '34 77 c7 f7 64 a4 1b ac ef f9 0b f1 4f 92 b7 cc',
|
||||
1520: 'ac 4e 95 36 8d 99 b9 eb 78 b8 da 8f 81 ff a7 95',
|
||||
1536: '8c 3c 13 f8 c2 38 8b b7 3f 38 57 6e 65 b7 c4 46',
|
||||
2032: '13 c4 b9 c1 df b6 65 79 ed dd 8a 28 0b 9f 73 16',
|
||||
2048: 'dd d2 78 20 55 01 26 69 8e fa ad c6 4b 64 f6 6e',
|
||||
3056: 'f0 8f 2e 66 d2 8e d1 43 f3 a2 37 cf 9d e7 35 59',
|
||||
3072: '9e a3 6c 52 55 31 b8 80 ba 12 43 34 f5 7b 0b 70',
|
||||
4080: 'd5 a3 9e 3d fc c5 02 80 ba c4 a6 b5 aa 0d ca 7d',
|
||||
4096: '37 0b 1c 1f e6 55 91 6d 97 fd 0d 47 ca 1d 72 b8'
|
||||
}
|
||||
)
|
||||
]
|
||||
|
||||
def test_keystream(self):
|
||||
for tv in self.rfc6229_data:
|
||||
key = unhexlify(b((tv[0])))
|
||||
cipher = ARC4.new(key)
|
||||
count = 0
|
||||
for offset in range(0, 4096+1, 16):
|
||||
ct = cipher.encrypt(b('\x00')*16)
|
||||
expected = tv[1].get(offset)
|
||||
if expected:
|
||||
expected = unhexlify(b(expected.replace(" ", '')))
|
||||
self.assertEqual(ct, expected)
|
||||
count += 1
|
||||
self.assertEqual(count, len(tv[1]))
|
||||
|
||||
|
||||
class Drop_Tests(unittest.TestCase):
|
||||
key = b('\xAA')*16
|
||||
data = b('\x00')*5000
|
||||
|
||||
def setUp(self):
|
||||
self.cipher = ARC4.new(self.key)
|
||||
|
||||
def test_drop256_encrypt(self):
|
||||
cipher_drop = ARC4.new(self.key, 256)
|
||||
ct_drop = cipher_drop.encrypt(self.data[:16])
|
||||
ct = self.cipher.encrypt(self.data)[256:256+16]
|
||||
self.assertEqual(ct_drop, ct)
|
||||
|
||||
def test_drop256_decrypt(self):
|
||||
cipher_drop = ARC4.new(self.key, 256)
|
||||
pt_drop = cipher_drop.decrypt(self.data[:16])
|
||||
pt = self.cipher.decrypt(self.data)[256:256+16]
|
||||
self.assertEqual(pt_drop, pt)
|
||||
|
||||
|
||||
class KeyLength(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
self.assertRaises(ValueError, ARC4.new, b'')
|
||||
self.assertRaises(ValueError, ARC4.new, b'\x00' * 257)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
from .common import make_stream_tests
|
||||
tests = make_stream_tests(ARC4, "ARC4", test_data)
|
||||
tests += list_test_cases(RFC6229_Tests)
|
||||
tests += list_test_cases(Drop_Tests)
|
||||
tests.append(KeyLength())
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def suite():
|
||||
return unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
160
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_Blowfish.py
vendored
Normal file
160
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_Blowfish.py
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/test_Blowfish.py: Self-test for the Blowfish cipher
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-test suite for Crypto.Cipher.Blowfish"""
|
||||
|
||||
import unittest
|
||||
|
||||
from Crypto.Util.py3compat import bchr
|
||||
|
||||
from Crypto.Cipher import Blowfish
|
||||
|
||||
# This is a list of (plaintext, ciphertext, key) tuples.
|
||||
test_data = [
|
||||
# Test vectors from http://www.schneier.com/code/vectors.txt
|
||||
('0000000000000000', '4ef997456198dd78', '0000000000000000'),
|
||||
('ffffffffffffffff', '51866fd5b85ecb8a', 'ffffffffffffffff'),
|
||||
('1000000000000001', '7d856f9a613063f2', '3000000000000000'),
|
||||
('1111111111111111', '2466dd878b963c9d', '1111111111111111'),
|
||||
('1111111111111111', '61f9c3802281b096', '0123456789abcdef'),
|
||||
('0123456789abcdef', '7d0cc630afda1ec7', '1111111111111111'),
|
||||
('0000000000000000', '4ef997456198dd78', '0000000000000000'),
|
||||
('0123456789abcdef', '0aceab0fc6a0a28d', 'fedcba9876543210'),
|
||||
('01a1d6d039776742', '59c68245eb05282b', '7ca110454a1a6e57'),
|
||||
('5cd54ca83def57da', 'b1b8cc0b250f09a0', '0131d9619dc1376e'),
|
||||
('0248d43806f67172', '1730e5778bea1da4', '07a1133e4a0b2686'),
|
||||
('51454b582ddf440a', 'a25e7856cf2651eb', '3849674c2602319e'),
|
||||
('42fd443059577fa2', '353882b109ce8f1a', '04b915ba43feb5b6'),
|
||||
('059b5e0851cf143a', '48f4d0884c379918', '0113b970fd34f2ce'),
|
||||
('0756d8e0774761d2', '432193b78951fc98', '0170f175468fb5e6'),
|
||||
('762514b829bf486a', '13f04154d69d1ae5', '43297fad38e373fe'),
|
||||
('3bdd119049372802', '2eedda93ffd39c79', '07a7137045da2a16'),
|
||||
('26955f6835af609a', 'd887e0393c2da6e3', '04689104c2fd3b2f'),
|
||||
('164d5e404f275232', '5f99d04f5b163969', '37d06bb516cb7546'),
|
||||
('6b056e18759f5cca', '4a057a3b24d3977b', '1f08260d1ac2465e'),
|
||||
('004bd6ef09176062', '452031c1e4fada8e', '584023641aba6176'),
|
||||
('480d39006ee762f2', '7555ae39f59b87bd', '025816164629b007'),
|
||||
('437540c8698f3cfa', '53c55f9cb49fc019', '49793ebc79b3258f'),
|
||||
('072d43a077075292', '7a8e7bfa937e89a3', '4fb05e1515ab73a7'),
|
||||
('02fe55778117f12a', 'cf9c5d7a4986adb5', '49e95d6d4ca229bf'),
|
||||
('1d9d5c5018f728c2', 'd1abb290658bc778', '018310dc409b26d6'),
|
||||
('305532286d6f295a', '55cb3774d13ef201', '1c587f1c13924fef'),
|
||||
('0123456789abcdef', 'fa34ec4847b268b2', '0101010101010101'),
|
||||
('0123456789abcdef', 'a790795108ea3cae', '1f1f1f1f0e0e0e0e'),
|
||||
('0123456789abcdef', 'c39e072d9fac631d', 'e0fee0fef1fef1fe'),
|
||||
('ffffffffffffffff', '014933e0cdaff6e4', '0000000000000000'),
|
||||
('0000000000000000', 'f21e9a77b71c49bc', 'ffffffffffffffff'),
|
||||
('0000000000000000', '245946885754369a', '0123456789abcdef'),
|
||||
('ffffffffffffffff', '6b5c5a9c5d9e0a5a', 'fedcba9876543210'),
|
||||
#('fedcba9876543210', 'f9ad597c49db005e', 'f0'),
|
||||
#('fedcba9876543210', 'e91d21c1d961a6d6', 'f0e1'),
|
||||
#('fedcba9876543210', 'e9c2b70a1bc65cf3', 'f0e1d2'),
|
||||
('fedcba9876543210', 'be1e639408640f05', 'f0e1d2c3'),
|
||||
('fedcba9876543210', 'b39e44481bdb1e6e', 'f0e1d2c3b4'),
|
||||
('fedcba9876543210', '9457aa83b1928c0d', 'f0e1d2c3b4a5'),
|
||||
('fedcba9876543210', '8bb77032f960629d', 'f0e1d2c3b4a596'),
|
||||
('fedcba9876543210', 'e87a244e2cc85e82', 'f0e1d2c3b4a59687'),
|
||||
('fedcba9876543210', '15750e7a4f4ec577', 'f0e1d2c3b4a5968778'),
|
||||
('fedcba9876543210', '122ba70b3ab64ae0', 'f0e1d2c3b4a596877869'),
|
||||
('fedcba9876543210', '3a833c9affc537f6', 'f0e1d2c3b4a5968778695a'),
|
||||
('fedcba9876543210', '9409da87a90f6bf2', 'f0e1d2c3b4a5968778695a4b'),
|
||||
('fedcba9876543210', '884f80625060b8b4', 'f0e1d2c3b4a5968778695a4b3c'),
|
||||
('fedcba9876543210', '1f85031c19e11968', 'f0e1d2c3b4a5968778695a4b3c2d'),
|
||||
('fedcba9876543210', '79d9373a714ca34f', 'f0e1d2c3b4a5968778695a4b3c2d1e'),
|
||||
('fedcba9876543210', '93142887ee3be15c',
|
||||
'f0e1d2c3b4a5968778695a4b3c2d1e0f'),
|
||||
('fedcba9876543210', '03429e838ce2d14b',
|
||||
'f0e1d2c3b4a5968778695a4b3c2d1e0f00'),
|
||||
('fedcba9876543210', 'a4299e27469ff67b',
|
||||
'f0e1d2c3b4a5968778695a4b3c2d1e0f0011'),
|
||||
('fedcba9876543210', 'afd5aed1c1bc96a8',
|
||||
'f0e1d2c3b4a5968778695a4b3c2d1e0f001122'),
|
||||
('fedcba9876543210', '10851c0e3858da9f',
|
||||
'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233'),
|
||||
('fedcba9876543210', 'e6f51ed79b9db21f',
|
||||
'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344'),
|
||||
('fedcba9876543210', '64a6e14afd36b46f',
|
||||
'f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455'),
|
||||
('fedcba9876543210', '80c7d7d45a5479ad',
|
||||
'f0e1d2c3b4a5968778695a4b3c2d1e0f00112233445566'),
|
||||
('fedcba9876543210', '05044b62fa52d080',
|
||||
'f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677'),
|
||||
]
|
||||
|
||||
|
||||
class KeyLength(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
self.assertRaises(ValueError, Blowfish.new, bchr(0) * 3,
|
||||
Blowfish.MODE_ECB)
|
||||
self.assertRaises(ValueError, Blowfish.new, bchr(0) * 57,
|
||||
Blowfish.MODE_ECB)
|
||||
|
||||
|
||||
class TestOutput(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
# Encrypt/Decrypt data and test output parameter
|
||||
|
||||
cipher = Blowfish.new(b'4'*16, Blowfish.MODE_ECB)
|
||||
|
||||
pt = b'5' * 16
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(16)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
output = memoryview(bytearray(16))
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16)
|
||||
|
||||
shorter_output = bytearray(7)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
from .common import make_block_tests
|
||||
tests = make_block_tests(Blowfish, "Blowfish", test_data)
|
||||
tests.append(KeyLength())
|
||||
tests += [TestOutput()]
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
101
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CAST.py
vendored
Normal file
101
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CAST.py
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/CAST.py: Self-test for the CAST-128 (CAST5) cipher
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-test suite for Crypto.Cipher.CAST"""
|
||||
|
||||
import unittest
|
||||
|
||||
from Crypto.Util.py3compat import bchr
|
||||
|
||||
from Crypto.Cipher import CAST
|
||||
|
||||
# This is a list of (plaintext, ciphertext, key) tuples.
|
||||
test_data = [
|
||||
# Test vectors from RFC 2144, B.1
|
||||
('0123456789abcdef', '238b4fe5847e44b2',
|
||||
'0123456712345678234567893456789a',
|
||||
'128-bit key'),
|
||||
|
||||
('0123456789abcdef', 'eb6a711a2c02271b',
|
||||
'01234567123456782345',
|
||||
'80-bit key'),
|
||||
|
||||
('0123456789abcdef', '7ac816d16e9b302e',
|
||||
'0123456712',
|
||||
'40-bit key'),
|
||||
]
|
||||
|
||||
|
||||
class KeyLength(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
self.assertRaises(ValueError, CAST.new, bchr(0) * 4, CAST.MODE_ECB)
|
||||
self.assertRaises(ValueError, CAST.new, bchr(0) * 17, CAST.MODE_ECB)
|
||||
|
||||
|
||||
class TestOutput(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
# Encrypt/Decrypt data and test output parameter
|
||||
|
||||
cipher = CAST.new(b'4'*16, CAST.MODE_ECB)
|
||||
|
||||
pt = b'5' * 16
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(16)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
output = memoryview(bytearray(16))
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16)
|
||||
|
||||
shorter_output = bytearray(7)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
from .common import make_block_tests
|
||||
|
||||
tests = make_block_tests(CAST, "CAST", test_data)
|
||||
tests.append(KeyLength())
|
||||
tests.append(TestOutput())
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
556
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CBC.py
vendored
Normal file
556
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CBC.py
vendored
Normal file
@ -0,0 +1,556 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
import unittest
|
||||
from binascii import unhexlify
|
||||
|
||||
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)
|
||||
|
||||
class BlockChainingTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
key_192 = get_tag_random("key_192", 24)
|
||||
iv_128 = get_tag_random("iv_128", 16)
|
||||
iv_64 = get_tag_random("iv_64", 8)
|
||||
data_128 = get_tag_random("data_128", 16)
|
||||
|
||||
def test_loopback_128(self):
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
pt = get_tag_random("plaintext", 16 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_loopback_64(self):
|
||||
cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64)
|
||||
pt = get_tag_random("plaintext", 8 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_iv(self):
|
||||
# If not passed, the iv is created randomly
|
||||
cipher = AES.new(self.key_128, self.aes_mode)
|
||||
iv1 = cipher.iv
|
||||
cipher = AES.new(self.key_128, self.aes_mode)
|
||||
iv2 = cipher.iv
|
||||
self.assertNotEqual(iv1, iv2)
|
||||
self.assertEqual(len(iv1), 16)
|
||||
|
||||
# IV can be passed in uppercase or lowercase
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
ct = cipher.encrypt(self.data_128)
|
||||
|
||||
cipher = AES.new(self.key_128, self.aes_mode, iv=self.iv_128)
|
||||
self.assertEqual(ct, cipher.encrypt(self.data_128))
|
||||
|
||||
cipher = AES.new(self.key_128, self.aes_mode, IV=self.iv_128)
|
||||
self.assertEqual(ct, cipher.encrypt(self.data_128))
|
||||
|
||||
def test_iv_must_be_bytes(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode,
|
||||
iv = u'test1234567890-*')
|
||||
|
||||
def test_only_one_iv(self):
|
||||
# Only one IV/iv keyword allowed
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode,
|
||||
iv=self.iv_128, IV=self.iv_128)
|
||||
|
||||
def test_iv_with_matching_length(self):
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode,
|
||||
b"")
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode,
|
||||
self.iv_128[:15])
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, self.aes_mode,
|
||||
self.iv_128 + b"0")
|
||||
|
||||
def test_block_size_128(self):
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
self.assertEqual(cipher.block_size, AES.block_size)
|
||||
|
||||
def test_block_size_64(self):
|
||||
cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64)
|
||||
self.assertEqual(cipher.block_size, DES3.block_size)
|
||||
|
||||
def test_unaligned_data_128(self):
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
for wrong_length in range(1,16):
|
||||
self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length)
|
||||
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
for wrong_length in range(1,16):
|
||||
self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length)
|
||||
|
||||
def test_unaligned_data_64(self):
|
||||
cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64)
|
||||
for wrong_length in range(1,8):
|
||||
self.assertRaises(ValueError, cipher.encrypt, b"5" * wrong_length)
|
||||
|
||||
cipher = DES3.new(self.key_192, self.des3_mode, self.iv_64)
|
||||
for wrong_length in range(1,8):
|
||||
self.assertRaises(ValueError, cipher.decrypt, b"5" * wrong_length)
|
||||
|
||||
def test_IV_iv_attributes(self):
|
||||
data = get_tag_random("data", 16 * 100)
|
||||
for func in "encrypt", "decrypt":
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
getattr(cipher, func)(data)
|
||||
self.assertEqual(cipher.iv, self.iv_128)
|
||||
self.assertEqual(cipher.IV, self.iv_128)
|
||||
|
||||
def test_unknown_parameters(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode,
|
||||
self.iv_128, 7)
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, self.aes_mode,
|
||||
iv=self.iv_128, unknown=7)
|
||||
# But some are only known by the base cipher (e.g. use_aesni consumed by the AES module)
|
||||
AES.new(self.key_128, self.aes_mode, iv=self.iv_128, use_aesni=False)
|
||||
|
||||
def test_null_encryption_decryption(self):
|
||||
for func in "encrypt", "decrypt":
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
result = getattr(cipher, func)(b"")
|
||||
self.assertEqual(result, b"")
|
||||
|
||||
def test_either_encrypt_or_decrypt(self):
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
cipher.encrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.decrypt, b"")
|
||||
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
cipher.decrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.encrypt, b"")
|
||||
|
||||
def test_data_must_be_bytes(self):
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*')
|
||||
|
||||
cipher = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*')
|
||||
|
||||
def test_bytearray(self):
|
||||
data = b"1" * 128
|
||||
data_ba = bytearray(data)
|
||||
|
||||
# Encrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
iv_ba = bytearray(self.iv_128)
|
||||
|
||||
cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
ref1 = cipher1.encrypt(data)
|
||||
|
||||
cipher2 = AES.new(key_ba, self.aes_mode, iv_ba)
|
||||
key_ba[:3] = b'\xFF\xFF\xFF'
|
||||
iv_ba[:3] = b'\xFF\xFF\xFF'
|
||||
ref2 = cipher2.encrypt(data_ba)
|
||||
|
||||
self.assertEqual(ref1, ref2)
|
||||
self.assertEqual(cipher1.iv, cipher2.iv)
|
||||
|
||||
# Decrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
iv_ba = bytearray(self.iv_128)
|
||||
|
||||
cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
ref3 = cipher3.decrypt(data)
|
||||
|
||||
cipher4 = AES.new(key_ba, self.aes_mode, iv_ba)
|
||||
key_ba[:3] = b'\xFF\xFF\xFF'
|
||||
iv_ba[:3] = b'\xFF\xFF\xFF'
|
||||
ref4 = cipher4.decrypt(data_ba)
|
||||
|
||||
self.assertEqual(ref3, ref4)
|
||||
|
||||
def test_memoryview(self):
|
||||
data = b"1" * 128
|
||||
data_mv = memoryview(bytearray(data))
|
||||
|
||||
# Encrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
iv_mv = memoryview(bytearray(self.iv_128))
|
||||
|
||||
cipher1 = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
ref1 = cipher1.encrypt(data)
|
||||
|
||||
cipher2 = AES.new(key_mv, self.aes_mode, iv_mv)
|
||||
key_mv[:3] = b'\xFF\xFF\xFF'
|
||||
iv_mv[:3] = b'\xFF\xFF\xFF'
|
||||
ref2 = cipher2.encrypt(data_mv)
|
||||
|
||||
self.assertEqual(ref1, ref2)
|
||||
self.assertEqual(cipher1.iv, cipher2.iv)
|
||||
|
||||
# Decrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
iv_mv = memoryview(bytearray(self.iv_128))
|
||||
|
||||
cipher3 = AES.new(self.key_128, self.aes_mode, self.iv_128)
|
||||
ref3 = cipher3.decrypt(data)
|
||||
|
||||
cipher4 = AES.new(key_mv, self.aes_mode, iv_mv)
|
||||
key_mv[:3] = b'\xFF\xFF\xFF'
|
||||
iv_mv[:3] = b'\xFF\xFF\xFF'
|
||||
ref4 = cipher4.decrypt(data_mv)
|
||||
|
||||
self.assertEqual(ref3, ref4)
|
||||
|
||||
def test_output_param(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(128)
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
|
||||
def test_output_param_same_buffer(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
pt_ba = bytearray(pt)
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
res = cipher.encrypt(pt_ba, output=pt_ba)
|
||||
self.assertEqual(ct, pt_ba)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
ct_ba = bytearray(ct)
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
res = cipher.decrypt(ct_ba, output=ct_ba)
|
||||
self.assertEqual(pt, ct_ba)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
|
||||
def test_output_param_memoryview(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = memoryview(bytearray(128))
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
def test_output_param_neg(self):
|
||||
LEN_PT = 128
|
||||
|
||||
pt = b'5' * LEN_PT
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT)
|
||||
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT)
|
||||
|
||||
shorter_output = bytearray(LEN_PT - 1)
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
cipher = AES.new(b'4'*16, self.aes_mode, iv=self.iv_128)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
class CbcTests(BlockChainingTests):
|
||||
aes_mode = AES.MODE_CBC
|
||||
des3_mode = DES3.MODE_CBC
|
||||
|
||||
|
||||
class NistBlockChainingVectors(unittest.TestCase):
|
||||
|
||||
def _do_kat_aes_test(self, file_name):
|
||||
|
||||
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:
|
||||
|
||||
# The test vector file contains some directive lines
|
||||
if is_string(tv):
|
||||
direction = tv
|
||||
continue
|
||||
|
||||
self.description = tv.desc
|
||||
|
||||
cipher = AES.new(tv.key, self.aes_mode, tv.iv)
|
||||
if direction == "[ENCRYPT]":
|
||||
self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
|
||||
elif direction == "[DECRYPT]":
|
||||
self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
|
||||
else:
|
||||
assert False
|
||||
|
||||
# See Section 6.4.2 in AESAVS
|
||||
def _do_mct_aes_test(self, file_name):
|
||||
|
||||
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:
|
||||
|
||||
# The test vector file contains some directive lines
|
||||
if is_string(tv):
|
||||
direction = tv
|
||||
continue
|
||||
|
||||
self.description = tv.desc
|
||||
cipher = AES.new(tv.key, self.aes_mode, tv.iv)
|
||||
|
||||
if direction == '[ENCRYPT]':
|
||||
cts = [ tv.iv ]
|
||||
for count in range(1000):
|
||||
cts.append(cipher.encrypt(tv.plaintext))
|
||||
tv.plaintext = cts[-2]
|
||||
self.assertEqual(cts[-1], tv.ciphertext)
|
||||
elif direction == '[DECRYPT]':
|
||||
pts = [ tv.iv]
|
||||
for count in range(1000):
|
||||
pts.append(cipher.decrypt(tv.ciphertext))
|
||||
tv.ciphertext = pts[-2]
|
||||
self.assertEqual(pts[-1], tv.plaintext)
|
||||
else:
|
||||
assert False
|
||||
|
||||
def _do_tdes_test(self, file_name):
|
||||
|
||||
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:
|
||||
|
||||
# The test vector file contains some directive lines
|
||||
if is_string(tv):
|
||||
direction = tv
|
||||
continue
|
||||
|
||||
self.description = tv.desc
|
||||
if hasattr(tv, "keys"):
|
||||
cipher = DES.new(tv.keys, self.des_mode, tv.iv)
|
||||
else:
|
||||
if tv.key1 != tv.key3:
|
||||
key = tv.key1 + tv.key2 + tv.key3 # Option 3
|
||||
else:
|
||||
key = tv.key1 + tv.key2 # Option 2
|
||||
cipher = DES3.new(key, self.des3_mode, tv.iv)
|
||||
|
||||
if direction == "[ENCRYPT]":
|
||||
self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
|
||||
elif direction == "[DECRYPT]":
|
||||
self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
|
||||
else:
|
||||
assert False
|
||||
|
||||
|
||||
class NistCbcVectors(NistBlockChainingVectors):
|
||||
aes_mode = AES.MODE_CBC
|
||||
des_mode = DES.MODE_CBC
|
||||
des3_mode = DES3.MODE_CBC
|
||||
|
||||
|
||||
# Create one test method per file
|
||||
nist_aes_kat_mmt_files = (
|
||||
# KAT
|
||||
"CBCGFSbox128.rsp",
|
||||
"CBCGFSbox192.rsp",
|
||||
"CBCGFSbox256.rsp",
|
||||
"CBCKeySbox128.rsp",
|
||||
"CBCKeySbox192.rsp",
|
||||
"CBCKeySbox256.rsp",
|
||||
"CBCVarKey128.rsp",
|
||||
"CBCVarKey192.rsp",
|
||||
"CBCVarKey256.rsp",
|
||||
"CBCVarTxt128.rsp",
|
||||
"CBCVarTxt192.rsp",
|
||||
"CBCVarTxt256.rsp",
|
||||
# MMT
|
||||
"CBCMMT128.rsp",
|
||||
"CBCMMT192.rsp",
|
||||
"CBCMMT256.rsp",
|
||||
)
|
||||
nist_aes_mct_files = (
|
||||
"CBCMCT128.rsp",
|
||||
"CBCMCT192.rsp",
|
||||
"CBCMCT256.rsp",
|
||||
)
|
||||
|
||||
for file_name in nist_aes_kat_mmt_files:
|
||||
def new_func(self, file_name=file_name):
|
||||
self._do_kat_aes_test(file_name)
|
||||
setattr(NistCbcVectors, "test_AES_" + file_name, new_func)
|
||||
|
||||
for file_name in nist_aes_mct_files:
|
||||
def new_func(self, file_name=file_name):
|
||||
self._do_mct_aes_test(file_name)
|
||||
setattr(NistCbcVectors, "test_AES_" + file_name, new_func)
|
||||
del file_name, new_func
|
||||
|
||||
nist_tdes_files = (
|
||||
"TCBCMMT2.rsp", # 2TDES
|
||||
"TCBCMMT3.rsp", # 3TDES
|
||||
"TCBCinvperm.rsp", # Single DES
|
||||
"TCBCpermop.rsp",
|
||||
"TCBCsubtab.rsp",
|
||||
"TCBCvarkey.rsp",
|
||||
"TCBCvartext.rsp",
|
||||
)
|
||||
|
||||
for file_name in nist_tdes_files:
|
||||
def new_func(self, file_name=file_name):
|
||||
self._do_tdes_test(file_name)
|
||||
setattr(NistCbcVectors, "test_TDES_" + file_name, new_func)
|
||||
|
||||
# END OF NIST CBC TEST VECTORS
|
||||
|
||||
|
||||
class SP800TestVectors(unittest.TestCase):
|
||||
"""Class exercising the CBC test vectors found in Section F.2
|
||||
of NIST SP 800-3A"""
|
||||
|
||||
def test_aes_128(self):
|
||||
key = '2b7e151628aed2a6abf7158809cf4f3c'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = '7649abac8119b246cee98e9b12e9197d' +\
|
||||
'5086cb9b507219ee95db113a917678b2' +\
|
||||
'73bed6b8e3c1743b7116e69e22229516' +\
|
||||
'3ff1caa1681fac09120eca307586e1a7'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
def test_aes_192(self):
|
||||
key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = '4f021db243bc633d7178183a9fa071e8' +\
|
||||
'b4d9ada9ad7dedf4e5e738763f69145a' +\
|
||||
'571b242012fb7ae07fa9baac3df102e0' +\
|
||||
'08b0e27988598881d920a9e64f5615cd'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
def test_aes_256(self):
|
||||
key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = 'f58c4c04d6e5f1ba779eabfb5f7bfbd6' +\
|
||||
'9cfc4e967edb808d679f777bc6702c7d' +\
|
||||
'39f23369a9d9bacfa530e26304231461' +\
|
||||
'b2eb05e2c39be9fcda6c19078c6a9d1b'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(CbcTests)
|
||||
if config.get('slow_tests'):
|
||||
tests += list_test_cases(NistCbcVectors)
|
||||
tests += list_test_cases(SP800TestVectors)
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
936
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CCM.py
vendored
Normal file
936
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CCM.py
vendored
Normal file
@ -0,0 +1,936 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
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.strxor import strxor
|
||||
|
||||
|
||||
def get_tag_random(tag, length):
|
||||
return SHAKE128.new(data=tobytes(tag)).read(length)
|
||||
|
||||
|
||||
class CcmTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
nonce_96 = get_tag_random("nonce_128", 12)
|
||||
data = get_tag_random("data", 128)
|
||||
|
||||
def test_loopback_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
pt = get_tag_random("plaintext", 16 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_nonce(self):
|
||||
# If not passed, the nonce is created randomly
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM)
|
||||
nonce1 = cipher.nonce
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM)
|
||||
nonce2 = cipher.nonce
|
||||
self.assertEqual(len(nonce1), 11)
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, self.nonce_96)
|
||||
ct = cipher.encrypt(self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertEqual(ct, cipher.encrypt(self.data))
|
||||
|
||||
def test_nonce_must_be_bytes(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CCM,
|
||||
nonce=u'test12345678')
|
||||
|
||||
def test_nonce_length(self):
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM,
|
||||
nonce=b"")
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM,
|
||||
nonce=bchr(1) * 6)
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM,
|
||||
nonce=bchr(1) * 14)
|
||||
for x in range(7, 13 + 1):
|
||||
AES.new(self.key_128, AES.MODE_CCM, nonce=bchr(1) * x)
|
||||
|
||||
def test_block_size(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.block_size, AES.block_size)
|
||||
|
||||
def test_nonce_attribute(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.nonce, self.nonce_96)
|
||||
|
||||
# By default, a 11 bytes long nonce is randomly generated
|
||||
nonce1 = AES.new(self.key_128, AES.MODE_CCM).nonce
|
||||
nonce2 = AES.new(self.key_128, AES.MODE_CCM).nonce
|
||||
self.assertEqual(len(nonce1), 11)
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
|
||||
def test_unknown_parameters(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CCM,
|
||||
self.nonce_96, 7)
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96, unknown=7)
|
||||
|
||||
# But some are only known by the base cipher
|
||||
# (e.g. use_aesni consumed by the AES module)
|
||||
AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
use_aesni=False)
|
||||
|
||||
def test_null_encryption_decryption(self):
|
||||
for func in "encrypt", "decrypt":
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
result = getattr(cipher, func)(b"")
|
||||
self.assertEqual(result, b"")
|
||||
|
||||
def test_either_encrypt_or_decrypt(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.encrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.decrypt, b"")
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.decrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.encrypt, b"")
|
||||
|
||||
def test_data_must_be_bytes(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*')
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*')
|
||||
|
||||
def test_mac_len(self):
|
||||
# Invalid MAC length
|
||||
for mac_len in range(3, 17 + 1, 2):
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96, mac_len=mac_len)
|
||||
|
||||
# Valid MAC length
|
||||
for mac_len in range(4, 16 + 1, 2):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
mac_len=mac_len)
|
||||
_, mac = cipher.encrypt_and_digest(self.data)
|
||||
self.assertEqual(len(mac), mac_len)
|
||||
|
||||
# Default MAC length
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
_, mac = cipher.encrypt_and_digest(self.data)
|
||||
self.assertEqual(len(mac), 16)
|
||||
|
||||
def test_invalid_mac(self):
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
invalid_mac = strxor_c(mac, 0x01)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt_and_verify, ct,
|
||||
invalid_mac)
|
||||
|
||||
def test_hex_mac(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
mac_hex = cipher.hexdigest()
|
||||
self.assertEqual(cipher.digest(), unhexlify(mac_hex))
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.hexverify(mac_hex)
|
||||
|
||||
def test_longer_assoc_data_than_declared(self):
|
||||
# More than zero
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
assoc_len=0)
|
||||
self.assertRaises(ValueError, cipher.update, b"1")
|
||||
|
||||
# Too large
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
assoc_len=15)
|
||||
self.assertRaises(ValueError, cipher.update, self.data)
|
||||
|
||||
def test_shorter_assoc_data_than_expected(self):
|
||||
DATA_LEN = len(self.data)
|
||||
|
||||
# With plaintext
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
assoc_len=DATA_LEN + 1)
|
||||
cipher.update(self.data)
|
||||
self.assertRaises(ValueError, cipher.encrypt, self.data)
|
||||
|
||||
# With empty plaintext
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
assoc_len=DATA_LEN + 1)
|
||||
cipher.update(self.data)
|
||||
self.assertRaises(ValueError, cipher.digest)
|
||||
|
||||
# With ciphertext
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
assoc_len=DATA_LEN + 1)
|
||||
cipher.update(self.data)
|
||||
self.assertRaises(ValueError, cipher.decrypt, self.data)
|
||||
|
||||
# With empty ciphertext
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
assoc_len=DATA_LEN + 1)
|
||||
cipher.update(self.data)
|
||||
self.assertRaises(ValueError, cipher.verify, mac)
|
||||
|
||||
def test_shorter_and_longer_plaintext_than_declared(self):
|
||||
DATA_LEN = len(self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
msg_len=DATA_LEN + 1)
|
||||
cipher.encrypt(self.data)
|
||||
self.assertRaises(ValueError, cipher.digest)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
msg_len=DATA_LEN - 1)
|
||||
self.assertRaises(ValueError, cipher.encrypt, self.data)
|
||||
|
||||
def test_shorter_ciphertext_than_declared(self):
|
||||
DATA_LEN = len(self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
msg_len=DATA_LEN + 1)
|
||||
cipher.decrypt(ct)
|
||||
self.assertRaises(ValueError, cipher.verify, mac)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
msg_len=DATA_LEN - 1)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct)
|
||||
|
||||
def test_message_chunks(self):
|
||||
# Validate that both associated data and plaintext/ciphertext
|
||||
# can be broken up in chunks of arbitrary length
|
||||
|
||||
auth_data = get_tag_random("authenticated data", 127)
|
||||
plaintext = get_tag_random("plaintext", 127)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.update(auth_data)
|
||||
ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext)
|
||||
|
||||
def break_up(data, chunk_length):
|
||||
return [data[i:i+chunk_length] for i in range(0, len(data),
|
||||
chunk_length)]
|
||||
|
||||
# Encryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
msg_len=127, assoc_len=127)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
pt2 = b""
|
||||
for chunk in break_up(ciphertext, chunk_length):
|
||||
pt2 += cipher.decrypt(chunk)
|
||||
self.assertEqual(plaintext, pt2)
|
||||
cipher.verify(ref_mac)
|
||||
|
||||
# Decryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96,
|
||||
msg_len=127, assoc_len=127)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
ct2 = b""
|
||||
for chunk in break_up(plaintext, chunk_length):
|
||||
ct2 += cipher.encrypt(chunk)
|
||||
self.assertEqual(ciphertext, ct2)
|
||||
self.assertEqual(cipher.digest(), ref_mac)
|
||||
|
||||
def test_bytearray(self):
|
||||
|
||||
# Encrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data)
|
||||
data_ba = bytearray(self.data)
|
||||
|
||||
cipher1 = AES.new(self.key_128,
|
||||
AES.MODE_CCM,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data)
|
||||
ct = cipher1.encrypt(self.data)
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = AES.new(key_ba,
|
||||
AES.MODE_CCM,
|
||||
nonce=nonce_ba)
|
||||
key_ba[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_ba[:3] = b"\xFF\xFF\xFF"
|
||||
cipher2.update(header_ba)
|
||||
header_ba[:3] = b"\xFF\xFF\xFF"
|
||||
ct_test = cipher2.encrypt(data_ba)
|
||||
data_ba[:3] = b"\xFF\xFF\xFF"
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data)
|
||||
del data_ba
|
||||
|
||||
cipher4 = AES.new(key_ba,
|
||||
AES.MODE_CCM,
|
||||
nonce=nonce_ba)
|
||||
key_ba[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_ba[:3] = b"\xFF\xFF\xFF"
|
||||
cipher4.update(header_ba)
|
||||
header_ba[:3] = b"\xFF\xFF\xFF"
|
||||
pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test))
|
||||
|
||||
self.assertEqual(self.data, pt_test)
|
||||
|
||||
def test_memoryview(self):
|
||||
|
||||
# Encrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data))
|
||||
data_mv = memoryview(bytearray(self.data))
|
||||
|
||||
cipher1 = AES.new(self.key_128,
|
||||
AES.MODE_CCM,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data)
|
||||
ct = cipher1.encrypt(self.data)
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = AES.new(key_mv,
|
||||
AES.MODE_CCM,
|
||||
nonce=nonce_mv)
|
||||
key_mv[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_mv[:3] = b"\xFF\xFF\xFF"
|
||||
cipher2.update(header_mv)
|
||||
header_mv[:3] = b"\xFF\xFF\xFF"
|
||||
ct_test = cipher2.encrypt(data_mv)
|
||||
data_mv[:3] = b"\xFF\xFF\xFF"
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data))
|
||||
del data_mv
|
||||
|
||||
cipher4 = AES.new(key_mv,
|
||||
AES.MODE_CCM,
|
||||
nonce=nonce_mv)
|
||||
key_mv[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_mv[:3] = b"\xFF\xFF\xFF"
|
||||
cipher4.update(header_mv)
|
||||
header_mv[:3] = b"\xFF\xFF\xFF"
|
||||
pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test))
|
||||
|
||||
self.assertEqual(self.data, pt_test)
|
||||
|
||||
def test_output_param(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(pt)
|
||||
tag = cipher.digest()
|
||||
|
||||
output = bytearray(128)
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
res, tag_out = cipher.encrypt_and_digest(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
self.assertEqual(tag, tag_out)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
res = cipher.decrypt_and_verify(ct, tag, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
def test_output_param_memoryview(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = memoryview(bytearray(128))
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
def test_output_param_neg(self):
|
||||
|
||||
pt = b'5' * 16
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16)
|
||||
|
||||
shorter_output = bytearray(15)
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
class CcmFSMTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
nonce_96 = get_tag_random("nonce_128", 12)
|
||||
data = get_tag_random("data", 16)
|
||||
|
||||
def test_valid_init_encrypt_decrypt_digest_verify(self):
|
||||
# No authenticated data, fixed plaintext
|
||||
for assoc_len in (None, 0):
|
||||
for msg_len in (None, len(self.data)):
|
||||
# Verify path INIT->ENCRYPT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96,
|
||||
assoc_len=assoc_len,
|
||||
msg_len=msg_len)
|
||||
ct = cipher.encrypt(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->DECRYPT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96,
|
||||
assoc_len=assoc_len,
|
||||
msg_len=msg_len)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_init_update_digest_verify(self):
|
||||
# No plaintext, fixed authenticated data
|
||||
for assoc_len in (None, len(self.data)):
|
||||
for msg_len in (None, 0):
|
||||
# Verify path INIT->UPDATE->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96,
|
||||
assoc_len=assoc_len,
|
||||
msg_len=msg_len)
|
||||
cipher.update(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96,
|
||||
assoc_len=assoc_len,
|
||||
msg_len=msg_len)
|
||||
cipher.update(self.data)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_full_path(self):
|
||||
# Fixed authenticated data, fixed plaintext
|
||||
for assoc_len in (None, len(self.data)):
|
||||
for msg_len in (None, len(self.data)):
|
||||
# Verify path INIT->UPDATE->ENCRYPT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96,
|
||||
assoc_len=assoc_len,
|
||||
msg_len=msg_len)
|
||||
cipher.update(self.data)
|
||||
ct = cipher.encrypt(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->DECRYPT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96,
|
||||
assoc_len=assoc_len,
|
||||
msg_len=msg_len)
|
||||
cipher.update(self.data)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_init_digest(self):
|
||||
# Verify path INIT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.digest()
|
||||
|
||||
def test_valid_init_verify(self):
|
||||
# Verify path INIT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
mac = cipher.digest()
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_multiple_encrypt_or_decrypt(self):
|
||||
# Only possible if msg_len is declared in advance
|
||||
for method_name in "encrypt", "decrypt":
|
||||
for auth_data in (None, b"333", self.data,
|
||||
self.data + b"3"):
|
||||
if auth_data is None:
|
||||
assoc_len = None
|
||||
else:
|
||||
assoc_len = len(auth_data)
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96,
|
||||
msg_len=64,
|
||||
assoc_len=assoc_len)
|
||||
if auth_data is not None:
|
||||
cipher.update(auth_data)
|
||||
method = getattr(cipher, method_name)
|
||||
method(self.data)
|
||||
method(self.data)
|
||||
method(self.data)
|
||||
method(self.data)
|
||||
|
||||
def test_valid_multiple_digest_or_verify(self):
|
||||
# Multiple calls to digest
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
first_mac = cipher.digest()
|
||||
for x in range(4):
|
||||
self.assertEqual(first_mac, cipher.digest())
|
||||
|
||||
# Multiple calls to verify
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
for x in range(5):
|
||||
cipher.verify(first_mac)
|
||||
|
||||
def test_valid_encrypt_and_digest_decrypt_and_verify(self):
|
||||
# encrypt_and_digest
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
# decrypt_and_verify
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
pt = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(self.data, pt)
|
||||
|
||||
def test_invalid_multiple_encrypt_decrypt_without_msg_len(self):
|
||||
# Once per method, with or without assoc. data
|
||||
for method_name in "encrypt", "decrypt":
|
||||
for assoc_data_present in (True, False):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96)
|
||||
if assoc_data_present:
|
||||
cipher.update(self.data)
|
||||
method = getattr(cipher, method_name)
|
||||
method(self.data)
|
||||
self.assertRaises(TypeError, method, self.data)
|
||||
|
||||
def test_invalid_mixing_encrypt_decrypt(self):
|
||||
# Once per method, with or without assoc. data
|
||||
for method1_name, method2_name in (("encrypt", "decrypt"),
|
||||
("decrypt", "encrypt")):
|
||||
for assoc_data_present in (True, False):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM,
|
||||
nonce=self.nonce_96,
|
||||
msg_len=32)
|
||||
if assoc_data_present:
|
||||
cipher.update(self.data)
|
||||
getattr(cipher, method1_name)(self.data)
|
||||
self.assertRaises(TypeError, getattr(cipher, method2_name),
|
||||
self.data)
|
||||
|
||||
def test_invalid_encrypt_or_update_after_digest(self):
|
||||
for method_name in "encrypt", "update":
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.encrypt(self.data)
|
||||
cipher.digest()
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.encrypt_and_digest(self.data)
|
||||
|
||||
def test_invalid_decrypt_or_update_after_verify(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
for method_name in "decrypt", "update":
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CCM, nonce=self.nonce_96)
|
||||
cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data)
|
||||
|
||||
|
||||
class TestVectors(unittest.TestCase):
|
||||
"""Class exercising the CCM test vectors found in Appendix C
|
||||
of NIST SP 800-38C and in RFC 3610"""
|
||||
|
||||
# List of test vectors, each made up of:
|
||||
# - authenticated data
|
||||
# - plaintext
|
||||
# - ciphertext
|
||||
# - MAC
|
||||
# - AES key
|
||||
# - nonce
|
||||
test_vectors_hex = [
|
||||
# NIST SP 800 38C
|
||||
( '0001020304050607',
|
||||
'20212223',
|
||||
'7162015b',
|
||||
'4dac255d',
|
||||
'404142434445464748494a4b4c4d4e4f',
|
||||
'10111213141516'),
|
||||
( '000102030405060708090a0b0c0d0e0f',
|
||||
'202122232425262728292a2b2c2d2e2f',
|
||||
'd2a1f0e051ea5f62081a7792073d593d',
|
||||
'1fc64fbfaccd',
|
||||
'404142434445464748494a4b4c4d4e4f',
|
||||
'1011121314151617'),
|
||||
( '000102030405060708090a0b0c0d0e0f10111213',
|
||||
'202122232425262728292a2b2c2d2e2f3031323334353637',
|
||||
'e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5',
|
||||
'484392fbc1b09951',
|
||||
'404142434445464748494a4b4c4d4e4f',
|
||||
'101112131415161718191a1b'),
|
||||
( (''.join(["%02X" % (x*16+y) for x in range(0,16) for y in range(0,16)]))*256,
|
||||
'202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f',
|
||||
'69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72',
|
||||
'b4ac6bec93e8598e7f0dadbcea5b',
|
||||
'404142434445464748494a4b4c4d4e4f',
|
||||
'101112131415161718191a1b1c'),
|
||||
# RFC3610
|
||||
( '0001020304050607',
|
||||
'08090a0b0c0d0e0f101112131415161718191a1b1c1d1e',
|
||||
'588c979a61c663d2f066d0c2c0f989806d5f6b61dac384',
|
||||
'17e8d12cfdf926e0',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'00000003020100a0a1a2a3a4a5'),
|
||||
(
|
||||
'0001020304050607',
|
||||
'08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b',
|
||||
'a091d56e10400916',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'00000004030201a0a1a2a3a4a5'),
|
||||
( '0001020304050607',
|
||||
'08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
'51b1e5f44a197d1da46b0f8e2d282ae871e838bb64da859657',
|
||||
'4adaa76fbd9fb0c5',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'00000005040302A0A1A2A3A4A5'),
|
||||
( '000102030405060708090a0b',
|
||||
'0c0d0e0f101112131415161718191a1b1c1d1e',
|
||||
'a28c6865939a9a79faaa5c4c2a9d4a91cdac8c',
|
||||
'96c861b9c9e61ef1',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'00000006050403a0a1a2a3a4a5'),
|
||||
( '000102030405060708090a0b',
|
||||
'0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'dcf1fb7b5d9e23fb9d4e131253658ad86ebdca3e',
|
||||
'51e83f077d9c2d93',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'00000007060504a0a1a2a3a4a5'),
|
||||
( '000102030405060708090a0b',
|
||||
'0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
'6fc1b011f006568b5171a42d953d469b2570a4bd87',
|
||||
'405a0443ac91cb94',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'00000008070605a0a1a2a3a4a5'),
|
||||
( '0001020304050607',
|
||||
'08090a0b0c0d0e0f101112131415161718191a1b1c1d1e',
|
||||
'0135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c',
|
||||
'048c56602c97acbb7490',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'00000009080706a0a1a2a3a4a5'),
|
||||
( '0001020304050607',
|
||||
'08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'7b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24',
|
||||
'c17b4433f434963f34b4',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'0000000a090807a0a1a2a3a4a5'),
|
||||
( '0001020304050607',
|
||||
'08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
'82531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197',
|
||||
'ea9c07e56b5eb17e5f4e',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'0000000b0a0908a0a1a2a3a4a5'),
|
||||
( '000102030405060708090a0b',
|
||||
'0c0d0e0f101112131415161718191a1b1c1d1e',
|
||||
'07342594157785152b074098330abb141b947b',
|
||||
'566aa9406b4d999988dd',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'0000000c0b0a09a0a1a2a3a4a5'),
|
||||
( '000102030405060708090a0b',
|
||||
'0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'676bb20380b0e301e8ab79590a396da78b834934',
|
||||
'f53aa2e9107a8b6c022c',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'0000000d0c0b0aa0a1a2a3a4a5'),
|
||||
( '000102030405060708090a0b',
|
||||
'0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
'c0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43',
|
||||
'cd1aa31662e7ad65d6db',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'0000000e0d0c0ba0a1a2a3a4a5'),
|
||||
( '0be1a88bace018b1',
|
||||
'08e8cf97d820ea258460e96ad9cf5289054d895ceac47c',
|
||||
'4cb97f86a2a4689a877947ab8091ef5386a6ffbdd080f8',
|
||||
'e78cf7cb0cddd7b3',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'00412b4ea9cdbe3c9696766cfa'),
|
||||
( '63018f76dc8a1bcb',
|
||||
'9020ea6f91bdd85afa0039ba4baff9bfb79c7028949cd0ec',
|
||||
'4ccb1e7ca981befaa0726c55d378061298c85c92814abc33',
|
||||
'c52ee81d7d77c08a',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'0033568ef7b2633c9696766cfa'),
|
||||
( 'aa6cfa36cae86b40',
|
||||
'b916e0eacc1c00d7dcec68ec0b3bbb1a02de8a2d1aa346132e',
|
||||
'b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708',
|
||||
'a776796edb723506',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'00103fe41336713c9696766cfa'),
|
||||
( 'd0d0735c531e1becf049c244',
|
||||
'12daac5630efa5396f770ce1a66b21f7b2101c',
|
||||
'14d253c3967b70609b7cbb7c49916028324526',
|
||||
'9a6f49975bcadeaf',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'00764c63b8058e3c9696766cfa'),
|
||||
( '77b60f011c03e1525899bcae',
|
||||
'e88b6a46c78d63e52eb8c546efb5de6f75e9cc0d',
|
||||
'5545ff1a085ee2efbf52b2e04bee1e2336c73e3f',
|
||||
'762c0c7744fe7e3c',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'00f8b678094e3b3c9696766cfa'),
|
||||
( 'cd9044d2b71fdb8120ea60c0',
|
||||
'6435acbafb11a82e2f071d7ca4a5ebd93a803ba87f',
|
||||
'009769ecabdf48625594c59251e6035722675e04c8',
|
||||
'47099e5ae0704551',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'00d560912d3f703c9696766cfa'),
|
||||
( 'd85bc7e69f944fb8',
|
||||
'8a19b950bcf71a018e5e6701c91787659809d67dbedd18',
|
||||
'bc218daa947427b6db386a99ac1aef23ade0b52939cb6a',
|
||||
'637cf9bec2408897c6ba',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'0042fff8f1951c3c9696766cfa'),
|
||||
( '74a0ebc9069f5b37',
|
||||
'1761433c37c5a35fc1f39f406302eb907c6163be38c98437',
|
||||
'5810e6fd25874022e80361a478e3e9cf484ab04f447efff6',
|
||||
'f0a477cc2fc9bf548944',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'00920f40e56cdc3c9696766cfa'),
|
||||
( '44a3aa3aae6475ca',
|
||||
'a434a8e58500c6e41530538862d686ea9e81301b5ae4226bfa',
|
||||
'f2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f154',
|
||||
'4d4151a4ed3a8b87b9ce',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'0027ca0c7120bc3c9696766cfa'),
|
||||
( 'ec46bb63b02520c33c49fd70',
|
||||
'b96b49e21d621741632875db7f6c9243d2d7c2',
|
||||
'31d750a09da3ed7fddd49a2032aabf17ec8ebf',
|
||||
'7d22c8088c666be5c197',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'005b8ccbcd9af83c9696766cfa'),
|
||||
( '47a65ac78b3d594227e85e71',
|
||||
'e2fcfbb880442c731bf95167c8ffd7895e337076',
|
||||
'e882f1dbd38ce3eda7c23f04dd65071eb41342ac',
|
||||
'df7e00dccec7ae52987d',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'003ebe94044b9a3c9696766cfa'),
|
||||
( '6e37a6ef546d955d34ab6059',
|
||||
'abf21c0b02feb88f856df4a37381bce3cc128517d4',
|
||||
'f32905b88a641b04b9c9ffb58cc390900f3da12ab1',
|
||||
'6dce9e82efa16da62059',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'008d493b30ae8b3c9696766cfa'),
|
||||
]
|
||||
|
||||
test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex]
|
||||
|
||||
def runTest(self):
|
||||
for assoc_data, pt, ct, mac, key, nonce in self.test_vectors:
|
||||
# Encrypt
|
||||
cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac))
|
||||
cipher.update(assoc_data)
|
||||
ct2, mac2 = cipher.encrypt_and_digest(pt)
|
||||
self.assertEqual(ct, ct2)
|
||||
self.assertEqual(mac, mac2)
|
||||
|
||||
# Decrypt
|
||||
cipher = AES.new(key, AES.MODE_CCM, nonce, mac_len=len(mac))
|
||||
cipher.update(assoc_data)
|
||||
pt2 = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
|
||||
class TestVectorsWycheproof(unittest.TestCase):
|
||||
|
||||
def __init__(self, wycheproof_warnings, **extra_params):
|
||||
unittest.TestCase.__init__(self)
|
||||
self._wycheproof_warnings = wycheproof_warnings
|
||||
self._extra_params = extra_params
|
||||
self._id = "None"
|
||||
|
||||
def setUp(self):
|
||||
|
||||
def filter_tag(group):
|
||||
return group['tagSize'] // 8
|
||||
|
||||
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
|
||||
|
||||
def warn(self, tv):
|
||||
if tv.warning and self._wycheproof_warnings:
|
||||
import warnings
|
||||
warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment))
|
||||
|
||||
def test_encrypt(self, tv):
|
||||
self._id = "Wycheproof Encrypt CCM Test #" + str(tv.id)
|
||||
|
||||
try:
|
||||
cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size,
|
||||
**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
|
||||
return
|
||||
if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e):
|
||||
assert not tv.valid
|
||||
return
|
||||
raise e
|
||||
|
||||
cipher.update(tv.aad)
|
||||
ct, tag = cipher.encrypt_and_digest(tv.msg)
|
||||
if tv.valid:
|
||||
self.assertEqual(ct, tv.ct)
|
||||
self.assertEqual(tag, tv.tag)
|
||||
self.warn(tv)
|
||||
|
||||
def test_decrypt(self, tv):
|
||||
self._id = "Wycheproof Decrypt CCM Test #" + str(tv.id)
|
||||
|
||||
try:
|
||||
cipher = AES.new(tv.key, AES.MODE_CCM, tv.iv, mac_len=tv.tag_size,
|
||||
**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
|
||||
return
|
||||
if tv.tag_size not in range(4, 16 + 1, 2) and "Parameter 'mac_len'" in str(e):
|
||||
assert not tv.valid
|
||||
return
|
||||
raise e
|
||||
|
||||
cipher.update(tv.aad)
|
||||
try:
|
||||
pt = cipher.decrypt_and_verify(tv.ct, tv.tag)
|
||||
except ValueError:
|
||||
assert not tv.valid
|
||||
else:
|
||||
assert tv.valid
|
||||
self.assertEqual(pt, tv.msg)
|
||||
self.warn(tv)
|
||||
|
||||
def test_corrupt_decrypt(self, tv):
|
||||
self._id = "Wycheproof Corrupt Decrypt CCM Test #" + str(tv.id)
|
||||
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)
|
||||
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)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
for tv in self.tv:
|
||||
self.test_encrypt(tv)
|
||||
self.test_decrypt(tv)
|
||||
self.test_corrupt_decrypt(tv)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
wycheproof_warnings = config.get('wycheproof_warnings')
|
||||
|
||||
tests = []
|
||||
tests += list_test_cases(CcmTests)
|
||||
tests += list_test_cases(CcmFSMTests)
|
||||
tests += [TestVectors()]
|
||||
tests += [TestVectorsWycheproof(wycheproof_warnings)]
|
||||
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def suite():
|
||||
unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
411
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CFB.py
vendored
Normal file
411
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CFB.py
vendored
Normal file
@ -0,0 +1,411 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
import unittest
|
||||
from binascii import unhexlify
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class CfbTests(BlockChainingTests):
|
||||
|
||||
aes_mode = AES.MODE_CFB
|
||||
des3_mode = DES3.MODE_CFB
|
||||
|
||||
# Redefine test_unaligned_data_128/64
|
||||
|
||||
def test_unaligned_data_128(self):
|
||||
plaintexts = [ b"7777777" ] * 100
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
def test_unaligned_data_64(self):
|
||||
plaintexts = [ b"7777777" ] * 100
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
# Extra
|
||||
|
||||
def test_segment_size_128(self):
|
||||
for bits in range(8, 129, 8):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128,
|
||||
segment_size=bits)
|
||||
|
||||
for bits in 0, 7, 9, 127, 129:
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CFB,
|
||||
self.iv_128,
|
||||
segment_size=bits)
|
||||
|
||||
def test_segment_size_64(self):
|
||||
for bits in range(8, 65, 8):
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64,
|
||||
segment_size=bits)
|
||||
|
||||
for bits in 0, 7, 9, 63, 65:
|
||||
self.assertRaises(ValueError, DES3.new, self.key_192, AES.MODE_CFB,
|
||||
self.iv_64,
|
||||
segment_size=bits)
|
||||
|
||||
|
||||
class NistCfbVectors(unittest.TestCase):
|
||||
|
||||
def _do_kat_aes_test(self, file_name, segment_size):
|
||||
|
||||
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:
|
||||
|
||||
# The test vector file contains some directive lines
|
||||
if is_string(tv):
|
||||
direction = tv
|
||||
continue
|
||||
|
||||
self.description = tv.desc
|
||||
cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv,
|
||||
segment_size=segment_size)
|
||||
if direction == "[ENCRYPT]":
|
||||
self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
|
||||
elif direction == "[DECRYPT]":
|
||||
self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
|
||||
else:
|
||||
assert False
|
||||
|
||||
# See Section 6.4.5 in AESAVS
|
||||
def _do_mct_aes_test(self, file_name, segment_size):
|
||||
|
||||
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
|
||||
for tv in test_vectors:
|
||||
|
||||
# The test vector file contains some directive lines
|
||||
if is_string(tv):
|
||||
direction = tv
|
||||
continue
|
||||
|
||||
self.description = tv.desc
|
||||
cipher = AES.new(tv.key, AES.MODE_CFB, tv.iv,
|
||||
segment_size=segment_size)
|
||||
|
||||
def get_input(input_text, output_seq, j):
|
||||
# CFB128
|
||||
if segment_size == 128:
|
||||
if j >= 2:
|
||||
return output_seq[-2]
|
||||
return [input_text, tv.iv][j]
|
||||
# CFB8
|
||||
if j == 0:
|
||||
return input_text
|
||||
elif j <= 16:
|
||||
return tv.iv[j - 1:j]
|
||||
return output_seq[j - 17]
|
||||
|
||||
if direction == '[ENCRYPT]':
|
||||
cts = []
|
||||
for j in range(1000):
|
||||
plaintext = get_input(tv.plaintext, cts, j)
|
||||
cts.append(cipher.encrypt(plaintext))
|
||||
self.assertEqual(cts[-1], tv.ciphertext)
|
||||
elif direction == '[DECRYPT]':
|
||||
pts = []
|
||||
for j in range(1000):
|
||||
ciphertext = get_input(tv.ciphertext, pts, j)
|
||||
pts.append(cipher.decrypt(ciphertext))
|
||||
self.assertEqual(pts[-1], tv.plaintext)
|
||||
else:
|
||||
assert False
|
||||
|
||||
def _do_tdes_test(self, file_name, segment_size):
|
||||
|
||||
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:
|
||||
|
||||
# The test vector file contains some directive lines
|
||||
if is_string(tv):
|
||||
direction = tv
|
||||
continue
|
||||
|
||||
self.description = tv.desc
|
||||
if hasattr(tv, "keys"):
|
||||
cipher = DES.new(tv.keys, DES.MODE_CFB, tv.iv,
|
||||
segment_size=segment_size)
|
||||
else:
|
||||
if tv.key1 != tv.key3:
|
||||
key = tv.key1 + tv.key2 + tv.key3 # Option 3
|
||||
else:
|
||||
key = tv.key1 + tv.key2 # Option 2
|
||||
cipher = DES3.new(key, DES3.MODE_CFB, tv.iv,
|
||||
segment_size=segment_size)
|
||||
if direction == "[ENCRYPT]":
|
||||
self.assertEqual(cipher.encrypt(tv.plaintext), tv.ciphertext)
|
||||
elif direction == "[DECRYPT]":
|
||||
self.assertEqual(cipher.decrypt(tv.ciphertext), tv.plaintext)
|
||||
else:
|
||||
assert False
|
||||
|
||||
|
||||
# Create one test method per file
|
||||
nist_aes_kat_mmt_files = (
|
||||
# KAT
|
||||
"CFB?GFSbox128.rsp",
|
||||
"CFB?GFSbox192.rsp",
|
||||
"CFB?GFSbox256.rsp",
|
||||
"CFB?KeySbox128.rsp",
|
||||
"CFB?KeySbox192.rsp",
|
||||
"CFB?KeySbox256.rsp",
|
||||
"CFB?VarKey128.rsp",
|
||||
"CFB?VarKey192.rsp",
|
||||
"CFB?VarKey256.rsp",
|
||||
"CFB?VarTxt128.rsp",
|
||||
"CFB?VarTxt192.rsp",
|
||||
"CFB?VarTxt256.rsp",
|
||||
# MMT
|
||||
"CFB?MMT128.rsp",
|
||||
"CFB?MMT192.rsp",
|
||||
"CFB?MMT256.rsp",
|
||||
)
|
||||
nist_aes_mct_files = (
|
||||
"CFB?MCT128.rsp",
|
||||
"CFB?MCT192.rsp",
|
||||
"CFB?MCT256.rsp",
|
||||
)
|
||||
|
||||
for file_gen_name in nist_aes_kat_mmt_files:
|
||||
for bits in "8", "128":
|
||||
file_name = file_gen_name.replace("?", bits)
|
||||
def new_func(self, file_name=file_name, bits=bits):
|
||||
self._do_kat_aes_test(file_name, int(bits))
|
||||
setattr(NistCfbVectors, "test_AES_" + file_name, new_func)
|
||||
|
||||
for file_gen_name in nist_aes_mct_files:
|
||||
for bits in "8", "128":
|
||||
file_name = file_gen_name.replace("?", bits)
|
||||
def new_func(self, file_name=file_name, bits=bits):
|
||||
self._do_mct_aes_test(file_name, int(bits))
|
||||
setattr(NistCfbVectors, "test_AES_" + file_name, new_func)
|
||||
del file_name, new_func
|
||||
|
||||
nist_tdes_files = (
|
||||
"TCFB?MMT2.rsp", # 2TDES
|
||||
"TCFB?MMT3.rsp", # 3TDES
|
||||
"TCFB?invperm.rsp", # Single DES
|
||||
"TCFB?permop.rsp",
|
||||
"TCFB?subtab.rsp",
|
||||
"TCFB?varkey.rsp",
|
||||
"TCFB?vartext.rsp",
|
||||
)
|
||||
|
||||
for file_gen_name in nist_tdes_files:
|
||||
for bits in "8", "64":
|
||||
file_name = file_gen_name.replace("?", bits)
|
||||
def new_func(self, file_name=file_name, bits=bits):
|
||||
self._do_tdes_test(file_name, int(bits))
|
||||
setattr(NistCfbVectors, "test_TDES_" + file_name, new_func)
|
||||
|
||||
# END OF NIST CBC TEST VECTORS
|
||||
|
||||
|
||||
class SP800TestVectors(unittest.TestCase):
|
||||
"""Class exercising the CFB test vectors found in Section F.3
|
||||
of NIST SP 800-3A"""
|
||||
|
||||
def test_aes_128_cfb8(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172aae2d'
|
||||
ciphertext = '3b79424c9c0dd436bace9e0ed4586a4f32b9'
|
||||
key = '2b7e151628aed2a6abf7158809cf4f3c'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
def test_aes_192_cfb8(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172aae2d'
|
||||
ciphertext = 'cda2521ef0a905ca44cd057cbf0d47a0678a'
|
||||
key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
def test_aes_256_cfb8(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172aae2d'
|
||||
ciphertext = 'dc1f1a8520a64db55fcc8ac554844e889700'
|
||||
key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
def test_aes_128_cfb128(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = '3b3fd92eb72dad20333449f8e83cfb4a' +\
|
||||
'c8a64537a0b3a93fcde3cdad9f1ce58b' +\
|
||||
'26751f67a3cbb140b1808cf187a4f4df' +\
|
||||
'c04b05357c5d1c0eeac4c66f9ff7f2e6'
|
||||
key = '2b7e151628aed2a6abf7158809cf4f3c'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
def test_aes_192_cfb128(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = 'cdc80d6fddf18cab34c25909c99a4174' +\
|
||||
'67ce7f7f81173621961a2b70171d3d7a' +\
|
||||
'2e1e8a1dd59b88b1c8e60fed1efac4c9' +\
|
||||
'c05f9f9ca9834fa042ae8fba584b09ff'
|
||||
key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
def test_aes_256_cfb128(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
|
||||
ciphertext = 'dc7e84bfda79164b7ecd8486985d3860' +\
|
||||
'39ffed143b28b1c832113c6331e5407b' +\
|
||||
'df10132415e54b92a13ed0a8267ae2f9' +\
|
||||
'75a385741ab9cef82031623d55b1e471'
|
||||
key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(CfbTests)
|
||||
if config.get('slow_tests'):
|
||||
tests += list_test_cases(NistCfbVectors)
|
||||
tests += list_test_cases(SP800TestVectors)
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
472
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CTR.py
vendored
Normal file
472
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_CTR.py
vendored
Normal file
@ -0,0 +1,472 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
import unittest
|
||||
from binascii import hexlify, unhexlify
|
||||
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
from Crypto.Util.py3compat import tobytes, bchr
|
||||
from Crypto.Cipher import AES, DES3
|
||||
from Crypto.Hash import SHAKE128, SHA256
|
||||
from Crypto.Util import Counter
|
||||
|
||||
def get_tag_random(tag, length):
|
||||
return SHAKE128.new(data=tobytes(tag)).read(length)
|
||||
|
||||
class CtrTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
key_192 = get_tag_random("key_192", 24)
|
||||
nonce_32 = get_tag_random("nonce_32", 4)
|
||||
nonce_64 = get_tag_random("nonce_64", 8)
|
||||
ctr_64 = Counter.new(32, prefix=nonce_32)
|
||||
ctr_128 = Counter.new(64, prefix=nonce_64)
|
||||
|
||||
def test_loopback_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
pt = get_tag_random("plaintext", 16 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_loopback_64(self):
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64)
|
||||
pt = get_tag_random("plaintext", 8 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_invalid_counter_parameter(self):
|
||||
# Counter object is required for ciphers with short block size
|
||||
self.assertRaises(TypeError, DES3.new, self.key_192, AES.MODE_CTR)
|
||||
# Positional arguments are not allowed (Counter must be passed as
|
||||
# keyword)
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR, self.ctr_128)
|
||||
|
||||
def test_nonce_attribute(self):
|
||||
# Nonce attribute is the prefix passed to Counter (DES3)
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64)
|
||||
self.assertEqual(cipher.nonce, self.nonce_32)
|
||||
|
||||
# Nonce attribute is the prefix passed to Counter (AES)
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
self.assertEqual(cipher.nonce, self.nonce_64)
|
||||
|
||||
# Nonce attribute is not defined if suffix is used in Counter
|
||||
counter = Counter.new(64, prefix=self.nonce_32, suffix=self.nonce_32)
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter)
|
||||
self.assertFalse(hasattr(cipher, "nonce"))
|
||||
|
||||
def test_nonce_parameter(self):
|
||||
# Nonce parameter becomes nonce attribute
|
||||
cipher1 = AES.new(self.key_128, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
self.assertEqual(cipher1.nonce, self.nonce_64)
|
||||
|
||||
counter = Counter.new(64, prefix=self.nonce_64, initial_value=0)
|
||||
cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
pt = get_tag_random("plaintext", 65536)
|
||||
self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt))
|
||||
|
||||
# Nonce is implicitly created (for AES) when no parameters are passed
|
||||
nonce1 = AES.new(self.key_128, AES.MODE_CTR).nonce
|
||||
nonce2 = AES.new(self.key_128, AES.MODE_CTR).nonce
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
self.assertEqual(len(nonce1), 8)
|
||||
|
||||
# Nonce can be zero-length
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, nonce=b"")
|
||||
self.assertEqual(b"", cipher.nonce)
|
||||
cipher.encrypt(b'0'*300)
|
||||
|
||||
# Nonce and Counter are mutually exclusive
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
counter=self.ctr_128, nonce=self.nonce_64)
|
||||
|
||||
def test_initial_value_parameter(self):
|
||||
# Test with nonce parameter
|
||||
cipher1 = AES.new(self.key_128, AES.MODE_CTR,
|
||||
nonce=self.nonce_64, initial_value=0xFFFF)
|
||||
counter = Counter.new(64, prefix=self.nonce_64, initial_value=0xFFFF)
|
||||
cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter)
|
||||
pt = get_tag_random("plaintext", 65536)
|
||||
self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt))
|
||||
|
||||
# Test without nonce parameter
|
||||
cipher1 = AES.new(self.key_128, AES.MODE_CTR,
|
||||
initial_value=0xFFFF)
|
||||
counter = Counter.new(64, prefix=cipher1.nonce, initial_value=0xFFFF)
|
||||
cipher2 = AES.new(self.key_128, AES.MODE_CTR, counter=counter)
|
||||
pt = get_tag_random("plaintext", 65536)
|
||||
self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt))
|
||||
|
||||
# Initial_value and Counter are mutually exclusive
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
counter=self.ctr_128, initial_value=0)
|
||||
|
||||
def test_initial_value_bytes_parameter(self):
|
||||
# Same result as when passing an integer
|
||||
cipher1 = AES.new(self.key_128, AES.MODE_CTR,
|
||||
nonce=self.nonce_64,
|
||||
initial_value=b"\x00"*6+b"\xFF\xFF")
|
||||
cipher2 = AES.new(self.key_128, AES.MODE_CTR,
|
||||
nonce=self.nonce_64, initial_value=0xFFFF)
|
||||
pt = get_tag_random("plaintext", 65536)
|
||||
self.assertEqual(cipher1.encrypt(pt), cipher2.encrypt(pt))
|
||||
|
||||
# Fail if the iv is too large
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
initial_value=b"5"*17)
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
nonce=self.nonce_64, initial_value=b"5"*9)
|
||||
|
||||
# Fail if the iv is too short
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
initial_value=b"5"*15)
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
nonce=self.nonce_64, initial_value=b"5"*7)
|
||||
|
||||
def test_iv_with_matching_length(self):
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
counter=Counter.new(120))
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
counter=Counter.new(136))
|
||||
|
||||
def test_block_size_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
self.assertEqual(cipher.block_size, AES.block_size)
|
||||
|
||||
def test_block_size_64(self):
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CTR, counter=self.ctr_64)
|
||||
self.assertEqual(cipher.block_size, DES3.block_size)
|
||||
|
||||
def test_unaligned_data_128(self):
|
||||
plaintexts = [ b"7777777" ] * 100
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
def test_unaligned_data_64(self):
|
||||
plaintexts = [ b"7777777" ] * 100
|
||||
cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = DES3.new(self.key_192, AES.MODE_CTR, counter=self.ctr_64)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
def test_unknown_parameters(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
7, counter=self.ctr_128)
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_CTR,
|
||||
counter=self.ctr_128, unknown=7)
|
||||
# But some are only known by the base cipher (e.g. use_aesni consumed by the AES module)
|
||||
AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128, use_aesni=False)
|
||||
|
||||
def test_null_encryption_decryption(self):
|
||||
for func in "encrypt", "decrypt":
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
result = getattr(cipher, func)(b"")
|
||||
self.assertEqual(result, b"")
|
||||
|
||||
def test_either_encrypt_or_decrypt(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
cipher.encrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.decrypt, b"")
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=self.ctr_128)
|
||||
cipher.decrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.encrypt, b"")
|
||||
|
||||
def test_wrap_around(self):
|
||||
# Counter is only 8 bits, so we can only encrypt/decrypt 256 blocks (=4096 bytes)
|
||||
counter = Counter.new(8, prefix=bchr(9) * 15)
|
||||
max_bytes = 4096
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter)
|
||||
cipher.encrypt(b'9' * max_bytes)
|
||||
self.assertRaises(OverflowError, cipher.encrypt, b'9')
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter)
|
||||
self.assertRaises(OverflowError, cipher.encrypt, b'9' * (max_bytes + 1))
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter)
|
||||
cipher.decrypt(b'9' * max_bytes)
|
||||
self.assertRaises(OverflowError, cipher.decrypt, b'9')
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CTR, counter=counter)
|
||||
self.assertRaises(OverflowError, cipher.decrypt, b'9' * (max_bytes + 1))
|
||||
|
||||
def test_bytearray(self):
|
||||
data = b"1" * 16
|
||||
iv = b"\x00" * 6 + b"\xFF\xFF"
|
||||
|
||||
# Encrypt
|
||||
cipher1 = AES.new(self.key_128, AES.MODE_CTR,
|
||||
nonce=self.nonce_64,
|
||||
initial_value=iv)
|
||||
ref1 = cipher1.encrypt(data)
|
||||
|
||||
cipher2 = AES.new(self.key_128, AES.MODE_CTR,
|
||||
nonce=bytearray(self.nonce_64),
|
||||
initial_value=bytearray(iv))
|
||||
ref2 = cipher2.encrypt(bytearray(data))
|
||||
|
||||
self.assertEqual(ref1, ref2)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
cipher3 = AES.new(self.key_128, AES.MODE_CTR,
|
||||
nonce=self.nonce_64,
|
||||
initial_value=iv)
|
||||
ref3 = cipher3.decrypt(data)
|
||||
|
||||
cipher4 = AES.new(self.key_128, AES.MODE_CTR,
|
||||
nonce=bytearray(self.nonce_64),
|
||||
initial_value=bytearray(iv))
|
||||
ref4 = cipher4.decrypt(bytearray(data))
|
||||
|
||||
self.assertEqual(ref3, ref4)
|
||||
|
||||
def test_very_long_data(self):
|
||||
cipher = AES.new(b'A' * 32, AES.MODE_CTR, nonce=b'')
|
||||
ct = cipher.encrypt(b'B' * 1000000)
|
||||
digest = SHA256.new(ct).hexdigest()
|
||||
self.assertEqual(digest, "96204fc470476561a3a8f3b6fe6d24be85c87510b638142d1d0fb90989f8a6a6")
|
||||
|
||||
def test_output_param(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(128)
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
def test_output_param_memoryview(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = memoryview(bytearray(128))
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
def test_output_param_neg(self):
|
||||
LEN_PT = 128
|
||||
|
||||
pt = b'5' * LEN_PT
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT)
|
||||
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT)
|
||||
|
||||
shorter_output = bytearray(LEN_PT - 1)
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
cipher = AES.new(b'4'*16, AES.MODE_CTR, nonce=self.nonce_64)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
class SP800TestVectors(unittest.TestCase):
|
||||
"""Class exercising the CTR test vectors found in Section F.5
|
||||
of NIST SP 800-38A"""
|
||||
|
||||
def test_aes_128(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = '874d6191b620e3261bef6864990db6ce' +\
|
||||
'9806f66b7970fdff8617187bb9fffdff' +\
|
||||
'5ae4df3edbd5d35e5b4f09020db03eab' +\
|
||||
'1e031dda2fbe03d1792170a0f3009cee'
|
||||
key = '2b7e151628aed2a6abf7158809cf4f3c'
|
||||
counter = Counter.new(nbits=16,
|
||||
prefix=unhexlify('f0f1f2f3f4f5f6f7f8f9fafbfcfd'),
|
||||
initial_value=0xfeff)
|
||||
|
||||
key = unhexlify(key)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
def test_aes_192(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = '1abc932417521ca24f2b0459fe7e6e0b' +\
|
||||
'090339ec0aa6faefd5ccc2c6f4ce8e94' +\
|
||||
'1e36b26bd1ebc670d1bd1d665620abf7' +\
|
||||
'4f78a7f6d29809585a97daec58c6b050'
|
||||
key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'
|
||||
counter = Counter.new(nbits=16,
|
||||
prefix=unhexlify('f0f1f2f3f4f5f6f7f8f9fafbfcfd'),
|
||||
initial_value=0xfeff)
|
||||
|
||||
key = unhexlify(key)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
def test_aes_256(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = '601ec313775789a5b7a7f504bbf3d228' +\
|
||||
'f443e3ca4d62b59aca84e990cacaf5c5' +\
|
||||
'2b0930daa23de94ce87017ba2d84988d' +\
|
||||
'dfc9c58db67aada613c2dd08457941a6'
|
||||
key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'
|
||||
counter = Counter.new(nbits=16,
|
||||
prefix=unhexlify('f0f1f2f3f4f5f6f7f8f9fafbfcfd'),
|
||||
initial_value=0xfeff)
|
||||
key = unhexlify(key)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
|
||||
class RFC3686TestVectors(unittest.TestCase):
|
||||
|
||||
# Each item is a test vector with:
|
||||
# - plaintext
|
||||
# - ciphertext
|
||||
# - key (AES 128, 192 or 256 bits)
|
||||
# - counter prefix (4 byte nonce + 8 byte nonce)
|
||||
data = (
|
||||
('53696e676c6520626c6f636b206d7367',
|
||||
'e4095d4fb7a7b3792d6175a3261311b8',
|
||||
'ae6852f8121067cc4bf7a5765577f39e',
|
||||
'000000300000000000000000'),
|
||||
('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'5104a106168a72d9790d41ee8edad388eb2e1efc46da57c8fce630df9141be28',
|
||||
'7e24067817fae0d743d6ce1f32539163',
|
||||
'006cb6dbc0543b59da48d90b'),
|
||||
('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223',
|
||||
'c1cf48a89f2ffdd9cf4652e9efdb72d74540a42bde6d7836d59a5ceaaef3105325b2072f',
|
||||
'7691be035e5020a8ac6e618529f9a0dc',
|
||||
'00e0017b27777f3f4a1786f0'),
|
||||
('53696e676c6520626c6f636b206d7367',
|
||||
'4b55384fe259c9c84e7935a003cbe928',
|
||||
'16af5b145fc9f579c175f93e3bfb0eed863d06ccfdb78515',
|
||||
'0000004836733c147d6d93cb'),
|
||||
('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'453243fc609b23327edfaafa7131cd9f8490701c5ad4a79cfc1fe0ff42f4fb00',
|
||||
'7c5cb2401b3dc33c19e7340819e0f69c678c3db8e6f6a91a',
|
||||
'0096b03b020c6eadc2cb500d'),
|
||||
('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223',
|
||||
'96893fc55e5c722f540b7dd1ddf7e758d288bc95c69165884536c811662f2188abee0935',
|
||||
'02bf391ee8ecb159b959617b0965279bf59b60a786d3e0fe',
|
||||
'0007bdfd5cbd60278dcc0912'),
|
||||
('53696e676c6520626c6f636b206d7367',
|
||||
'145ad01dbf824ec7560863dc71e3e0c0',
|
||||
'776beff2851db06f4c8a0542c8696f6c6a81af1eec96b4d37fc1d689e6c1c104',
|
||||
'00000060db5672c97aa8f0b2'),
|
||||
('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'f05e231b3894612c49ee000b804eb2a9b8306b508f839d6a5530831d9344af1c',
|
||||
'f6d66d6bd52d59bb0796365879eff886c66dd51a5b6a99744b50590c87a23884',
|
||||
'00faac24c1585ef15a43d875'),
|
||||
('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223',
|
||||
'eb6c52821d0bbbf7ce7594462aca4faab407df866569fd07f48cc0b583d6071f1ec0e6b8',
|
||||
'ff7a617ce69148e4f1726e2f43581de2aa62d9f805532edff1eed687fb54153d',
|
||||
'001cc5b751a51d70a1c11148')
|
||||
)
|
||||
|
||||
bindata = []
|
||||
for tv in data:
|
||||
bindata.append([unhexlify(x) for x in tv])
|
||||
|
||||
def runTest(self):
|
||||
for pt, ct, key, prefix in self.bindata:
|
||||
counter = Counter.new(32, prefix=prefix)
|
||||
cipher = AES.new(key, AES.MODE_CTR, counter=counter)
|
||||
result = cipher.encrypt(pt)
|
||||
self.assertEqual(hexlify(ct), hexlify(result))
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(CtrTests)
|
||||
tests += list_test_cases(SP800TestVectors)
|
||||
tests += [ RFC3686TestVectors() ]
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
529
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_ChaCha20.py
vendored
Normal file
529
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_ChaCha20.py
vendored
Normal file
@ -0,0 +1,529 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
import os
|
||||
import re
|
||||
import unittest
|
||||
from binascii import hexlify, unhexlify
|
||||
|
||||
from Crypto.Util.py3compat import b, tobytes, bchr
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
|
||||
from Crypto.Cipher import ChaCha20
|
||||
|
||||
|
||||
class ChaCha20Test(unittest.TestCase):
|
||||
|
||||
def test_new_positive(self):
|
||||
cipher = ChaCha20.new(key=b("0")*32, nonce=b"0"*8)
|
||||
self.assertEqual(cipher.nonce, b"0" * 8)
|
||||
cipher = ChaCha20.new(key=b("0")*32, nonce=b"0"*12)
|
||||
self.assertEqual(cipher.nonce, b"0" * 12)
|
||||
|
||||
def test_new_negative(self):
|
||||
new = ChaCha20.new
|
||||
self.assertRaises(TypeError, new)
|
||||
self.assertRaises(TypeError, new, nonce=b("0"))
|
||||
self.assertRaises(ValueError, new, nonce=b("0")*8, key=b("0"))
|
||||
self.assertRaises(ValueError, new, nonce=b("0"), key=b("0")*32)
|
||||
|
||||
def test_default_nonce(self):
|
||||
cipher1 = ChaCha20.new(key=bchr(1) * 32)
|
||||
cipher2 = ChaCha20.new(key=bchr(1) * 32)
|
||||
self.assertEqual(len(cipher1.nonce), 8)
|
||||
self.assertNotEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
def test_nonce(self):
|
||||
key = b'A' * 32
|
||||
|
||||
nonce1 = b'P' * 8
|
||||
cipher1 = ChaCha20.new(key=key, nonce=nonce1)
|
||||
self.assertEqual(nonce1, cipher1.nonce)
|
||||
|
||||
nonce2 = b'Q' * 12
|
||||
cipher2 = ChaCha20.new(key=key, nonce=nonce2)
|
||||
self.assertEqual(nonce2, cipher2.nonce)
|
||||
|
||||
def test_eiter_encrypt_or_decrypt(self):
|
||||
"""Verify that a cipher cannot be used for both decrypting and encrypting"""
|
||||
|
||||
c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8)
|
||||
c1.encrypt(b("8"))
|
||||
self.assertRaises(TypeError, c1.decrypt, b("9"))
|
||||
|
||||
c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8)
|
||||
c2.decrypt(b("8"))
|
||||
self.assertRaises(TypeError, c2.encrypt, b("9"))
|
||||
|
||||
def test_round_trip(self):
|
||||
pt = b("A") * 1024
|
||||
c1 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8)
|
||||
c2 = ChaCha20.new(key=b("5") * 32, nonce=b("6") * 8)
|
||||
ct = c1.encrypt(pt)
|
||||
self.assertEqual(c2.decrypt(ct), pt)
|
||||
|
||||
self.assertEqual(c1.encrypt(b("")), b(""))
|
||||
self.assertEqual(c2.decrypt(b("")), b(""))
|
||||
|
||||
def test_streaming(self):
|
||||
"""Verify that an arbitrary number of bytes can be encrypted/decrypted"""
|
||||
from Crypto.Hash import SHA1
|
||||
|
||||
segments = (1, 3, 5, 7, 11, 17, 23)
|
||||
total = sum(segments)
|
||||
|
||||
pt = b("")
|
||||
while len(pt) < total:
|
||||
pt += SHA1.new(pt).digest()
|
||||
|
||||
cipher1 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8)
|
||||
ct = cipher1.encrypt(pt)
|
||||
|
||||
cipher2 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8)
|
||||
cipher3 = ChaCha20.new(key=b("7") * 32, nonce=b("t") * 8)
|
||||
idx = 0
|
||||
for segment in segments:
|
||||
self.assertEqual(cipher2.decrypt(ct[idx:idx+segment]), pt[idx:idx+segment])
|
||||
self.assertEqual(cipher3.encrypt(pt[idx:idx+segment]), ct[idx:idx+segment])
|
||||
idx += segment
|
||||
|
||||
def test_seek(self):
|
||||
cipher1 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8)
|
||||
|
||||
offset = 64 * 900 + 7
|
||||
pt = b("1") * 64
|
||||
|
||||
cipher1.encrypt(b("0") * offset)
|
||||
ct1 = cipher1.encrypt(pt)
|
||||
|
||||
cipher2 = ChaCha20.new(key=b("9") * 32, nonce=b("e") * 8)
|
||||
cipher2.seek(offset)
|
||||
ct2 = cipher2.encrypt(pt)
|
||||
|
||||
self.assertEqual(ct1, ct2)
|
||||
|
||||
def test_seek_tv(self):
|
||||
# Test Vector #4, A.1 from
|
||||
# http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04
|
||||
key = bchr(0) + bchr(255) + bchr(0) * 30
|
||||
nonce = bchr(0) * 8
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
cipher.seek(64 * 2)
|
||||
expected_key_stream = unhexlify(b(
|
||||
"72d54dfbf12ec44b362692df94137f32"
|
||||
"8fea8da73990265ec1bbbea1ae9af0ca"
|
||||
"13b25aa26cb4a648cb9b9d1be65b2c09"
|
||||
"24a66c54d545ec1b7374f4872e99f096"
|
||||
))
|
||||
ct = cipher.encrypt(bchr(0) * len(expected_key_stream))
|
||||
self.assertEqual(expected_key_stream, ct)
|
||||
|
||||
def test_rfc7539(self):
|
||||
# from https://tools.ietf.org/html/rfc7539 Annex A.1
|
||||
# Each item is: key, nonce, block #, plaintext, ciphertext
|
||||
tvs = [
|
||||
# Test Vector #1
|
||||
(
|
||||
"00"*32,
|
||||
"00"*12,
|
||||
0,
|
||||
"00"*16*4,
|
||||
"76b8e0ada0f13d90405d6ae55386bd28"
|
||||
"bdd219b8a08ded1aa836efcc8b770dc7"
|
||||
"da41597c5157488d7724e03fb8d84a37"
|
||||
"6a43b8f41518a11cc387b669b2ee6586"
|
||||
),
|
||||
# Test Vector #2
|
||||
(
|
||||
"00"*31 + "01",
|
||||
"00"*11 + "02",
|
||||
1,
|
||||
"416e79207375626d697373696f6e2074"
|
||||
"6f20746865204945544620696e74656e"
|
||||
"6465642062792074686520436f6e7472"
|
||||
"696275746f7220666f72207075626c69"
|
||||
"636174696f6e20617320616c6c206f72"
|
||||
"2070617274206f6620616e2049455446"
|
||||
"20496e7465726e65742d447261667420"
|
||||
"6f722052464320616e6420616e792073"
|
||||
"746174656d656e74206d616465207769"
|
||||
"7468696e2074686520636f6e74657874"
|
||||
"206f6620616e20494554462061637469"
|
||||
"7669747920697320636f6e7369646572"
|
||||
"656420616e20224945544620436f6e74"
|
||||
"7269627574696f6e222e205375636820"
|
||||
"73746174656d656e747320696e636c75"
|
||||
"6465206f72616c2073746174656d656e"
|
||||
"747320696e2049455446207365737369"
|
||||
"6f6e732c2061732077656c6c20617320"
|
||||
"7772697474656e20616e6420656c6563"
|
||||
"74726f6e696320636f6d6d756e696361"
|
||||
"74696f6e73206d61646520617420616e"
|
||||
"792074696d65206f7220706c6163652c"
|
||||
"20776869636820617265206164647265"
|
||||
"7373656420746f",
|
||||
"a3fbf07df3fa2fde4f376ca23e827370"
|
||||
"41605d9f4f4f57bd8cff2c1d4b7955ec"
|
||||
"2a97948bd3722915c8f3d337f7d37005"
|
||||
"0e9e96d647b7c39f56e031ca5eb6250d"
|
||||
"4042e02785ececfa4b4bb5e8ead0440e"
|
||||
"20b6e8db09d881a7c6132f420e527950"
|
||||
"42bdfa7773d8a9051447b3291ce1411c"
|
||||
"680465552aa6c405b7764d5e87bea85a"
|
||||
"d00f8449ed8f72d0d662ab052691ca66"
|
||||
"424bc86d2df80ea41f43abf937d3259d"
|
||||
"c4b2d0dfb48a6c9139ddd7f76966e928"
|
||||
"e635553ba76c5c879d7b35d49eb2e62b"
|
||||
"0871cdac638939e25e8a1e0ef9d5280f"
|
||||
"a8ca328b351c3c765989cbcf3daa8b6c"
|
||||
"cc3aaf9f3979c92b3720fc88dc95ed84"
|
||||
"a1be059c6499b9fda236e7e818b04b0b"
|
||||
"c39c1e876b193bfe5569753f88128cc0"
|
||||
"8aaa9b63d1a16f80ef2554d7189c411f"
|
||||
"5869ca52c5b83fa36ff216b9c1d30062"
|
||||
"bebcfd2dc5bce0911934fda79a86f6e6"
|
||||
"98ced759c3ff9b6477338f3da4f9cd85"
|
||||
"14ea9982ccafb341b2384dd902f3d1ab"
|
||||
"7ac61dd29c6f21ba5b862f3730e37cfd"
|
||||
"c4fd806c22f221"
|
||||
),
|
||||
# Test Vector #3
|
||||
(
|
||||
"1c9240a5eb55d38af333888604f6b5f0"
|
||||
"473917c1402b80099dca5cbc207075c0",
|
||||
"00"*11 + "02",
|
||||
42,
|
||||
"2754776173206272696c6c69672c2061"
|
||||
"6e642074686520736c6974687920746f"
|
||||
"7665730a446964206779726520616e64"
|
||||
"2067696d626c6520696e207468652077"
|
||||
"6162653a0a416c6c206d696d73792077"
|
||||
"6572652074686520626f726f676f7665"
|
||||
"732c0a416e6420746865206d6f6d6520"
|
||||
"7261746873206f757467726162652e",
|
||||
"62e6347f95ed87a45ffae7426f27a1df"
|
||||
"5fb69110044c0d73118effa95b01e5cf"
|
||||
"166d3df2d721caf9b21e5fb14c616871"
|
||||
"fd84c54f9d65b283196c7fe4f60553eb"
|
||||
"f39c6402c42234e32a356b3e764312a6"
|
||||
"1a5532055716ead6962568f87d3f3f77"
|
||||
"04c6a8d1bcd1bf4d50d6154b6da731b1"
|
||||
"87b58dfd728afa36757a797ac188d1"
|
||||
)
|
||||
]
|
||||
|
||||
for tv in tvs:
|
||||
key = unhexlify(tv[0])
|
||||
nonce = unhexlify(tv[1])
|
||||
offset = tv[2] * 64
|
||||
pt = unhexlify(tv[3])
|
||||
ct_expect = unhexlify(tv[4])
|
||||
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
if offset != 0:
|
||||
cipher.seek(offset)
|
||||
ct = cipher.encrypt(pt)
|
||||
assert(ct == ct_expect)
|
||||
|
||||
|
||||
class XChaCha20Test(unittest.TestCase):
|
||||
|
||||
# From https://tools.ietf.org/html/draft-arciszewski-xchacha-03
|
||||
|
||||
def test_hchacha20(self):
|
||||
# Section 2.2.1
|
||||
|
||||
from Crypto.Cipher.ChaCha20 import _HChaCha20
|
||||
|
||||
key = b"00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f"
|
||||
key = unhexlify(key.replace(b":", b""))
|
||||
|
||||
nonce = b"00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27"
|
||||
nonce = unhexlify(nonce.replace(b":", b""))
|
||||
|
||||
subkey = _HChaCha20(key, nonce)
|
||||
|
||||
expected = b"82413b42 27b27bfe d30e4250 8a877d73 a0f9e4d5 8a74a853 c12ec413 26d3ecdc"
|
||||
expected = unhexlify(expected.replace(b" ", b""))
|
||||
|
||||
self.assertEqual(subkey, expected)
|
||||
|
||||
def test_nonce(self):
|
||||
key = b'A' * 32
|
||||
nonce = b'P' * 24
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
self.assertEqual(nonce, cipher.nonce)
|
||||
|
||||
def test_encrypt(self):
|
||||
# Section A.3.2
|
||||
|
||||
pt = b"""
|
||||
5468652064686f6c65202870726f6e6f756e6365642022646f6c652229206973
|
||||
20616c736f206b6e6f776e2061732074686520417369617469632077696c6420
|
||||
646f672c2072656420646f672c20616e642077686973746c696e6720646f672e
|
||||
2049742069732061626f7574207468652073697a65206f662061204765726d61
|
||||
6e20736865706865726420627574206c6f6f6b73206d6f7265206c696b652061
|
||||
206c6f6e672d6c656767656420666f782e205468697320686967686c7920656c
|
||||
757369766520616e6420736b696c6c6564206a756d70657220697320636c6173
|
||||
736966696564207769746820776f6c7665732c20636f796f7465732c206a6163
|
||||
6b616c732c20616e6420666f78657320696e20746865207461786f6e6f6d6963
|
||||
2066616d696c792043616e696461652e"""
|
||||
pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b""))
|
||||
|
||||
key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f")
|
||||
iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555658")
|
||||
|
||||
ct = b"""
|
||||
7d0a2e6b7f7c65a236542630294e063b7ab9b555a5d5149aa21e4ae1e4fbce87
|
||||
ecc8e08a8b5e350abe622b2ffa617b202cfad72032a3037e76ffdcdc4376ee05
|
||||
3a190d7e46ca1de04144850381b9cb29f051915386b8a710b8ac4d027b8b050f
|
||||
7cba5854e028d564e453b8a968824173fc16488b8970cac828f11ae53cabd201
|
||||
12f87107df24ee6183d2274fe4c8b1485534ef2c5fbc1ec24bfc3663efaa08bc
|
||||
047d29d25043532db8391a8a3d776bf4372a6955827ccb0cdd4af403a7ce4c63
|
||||
d595c75a43e045f0cce1f29c8b93bd65afc5974922f214a40b7c402cdb91ae73
|
||||
c0b63615cdad0480680f16515a7ace9d39236464328a37743ffc28f4ddb324f4
|
||||
d0f5bbdc270c65b1749a6efff1fbaa09536175ccd29fb9e6057b307320d31683
|
||||
8a9c71f70b5b5907a66f7ea49aadc409"""
|
||||
ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b""))
|
||||
|
||||
cipher = ChaCha20.new(key=key, nonce=iv)
|
||||
cipher.seek(64) # Counter = 1
|
||||
ct_test = cipher.encrypt(pt)
|
||||
self.assertEqual(ct, ct_test)
|
||||
|
||||
|
||||
class ByteArrayTest(unittest.TestCase):
|
||||
"""Verify we can encrypt or decrypt bytearrays"""
|
||||
|
||||
def runTest(self):
|
||||
|
||||
data = b"0123"
|
||||
key = b"9" * 32
|
||||
nonce = b"t" * 8
|
||||
|
||||
# Encryption
|
||||
data_ba = bytearray(data)
|
||||
key_ba = bytearray(key)
|
||||
nonce_ba = bytearray(nonce)
|
||||
|
||||
cipher1 = ChaCha20.new(key=key, nonce=nonce)
|
||||
ct = cipher1.encrypt(data)
|
||||
|
||||
cipher2 = ChaCha20.new(key=key_ba, nonce=nonce_ba)
|
||||
key_ba[:1] = b'\xFF'
|
||||
nonce_ba[:1] = b'\xFF'
|
||||
ct_test = cipher2.encrypt(data_ba)
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decryption
|
||||
key_ba = bytearray(key)
|
||||
nonce_ba = bytearray(nonce)
|
||||
ct_ba = bytearray(ct)
|
||||
|
||||
cipher3 = ChaCha20.new(key=key_ba, nonce=nonce_ba)
|
||||
key_ba[:1] = b'\xFF'
|
||||
nonce_ba[:1] = b'\xFF'
|
||||
pt_test = cipher3.decrypt(ct_ba)
|
||||
|
||||
self.assertEqual(data, pt_test)
|
||||
|
||||
|
||||
class MemoryviewTest(unittest.TestCase):
|
||||
"""Verify we can encrypt or decrypt bytearrays"""
|
||||
|
||||
def runTest(self):
|
||||
|
||||
data = b"0123"
|
||||
key = b"9" * 32
|
||||
nonce = b"t" * 8
|
||||
|
||||
# Encryption
|
||||
data_mv = memoryview(bytearray(data))
|
||||
key_mv = memoryview(bytearray(key))
|
||||
nonce_mv = memoryview(bytearray(nonce))
|
||||
|
||||
cipher1 = ChaCha20.new(key=key, nonce=nonce)
|
||||
ct = cipher1.encrypt(data)
|
||||
|
||||
cipher2 = ChaCha20.new(key=key_mv, nonce=nonce_mv)
|
||||
key_mv[:1] = b'\xFF'
|
||||
nonce_mv[:1] = b'\xFF'
|
||||
ct_test = cipher2.encrypt(data_mv)
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decryption
|
||||
key_mv = memoryview(bytearray(key))
|
||||
nonce_mv = memoryview(bytearray(nonce))
|
||||
ct_mv = memoryview(bytearray(ct))
|
||||
|
||||
cipher3 = ChaCha20.new(key=key_mv, nonce=nonce_mv)
|
||||
key_mv[:1] = b'\xFF'
|
||||
nonce_mv[:1] = b'\xFF'
|
||||
pt_test = cipher3.decrypt(ct_mv)
|
||||
|
||||
self.assertEqual(data, pt_test)
|
||||
|
||||
|
||||
class ChaCha20_AGL_NIR(unittest.TestCase):
|
||||
|
||||
# From http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
|
||||
# and http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04
|
||||
tv = [
|
||||
( "00" * 32,
|
||||
"00" * 8,
|
||||
"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc"
|
||||
"8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11c"
|
||||
"c387b669b2ee6586"
|
||||
"9f07e7be5551387a98ba977c732d080d"
|
||||
"cb0f29a048e3656912c6533e32ee7aed"
|
||||
"29b721769ce64e43d57133b074d839d5"
|
||||
"31ed1f28510afb45ace10a1f4b794d6f"
|
||||
),
|
||||
( "00" * 31 + "01",
|
||||
"00" * 8,
|
||||
"4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952"
|
||||
"ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea81"
|
||||
"7e9ad275ae546963"
|
||||
"3aeb5224ecf849929b9d828db1ced4dd"
|
||||
"832025e8018b8160b82284f3c949aa5a"
|
||||
"8eca00bbb4a73bdad192b5c42f73f2fd"
|
||||
"4e273644c8b36125a64addeb006c13a0"
|
||||
),
|
||||
( "00" * 32,
|
||||
"00" * 7 + "01",
|
||||
"de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df1"
|
||||
"37821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e"
|
||||
"445f41e3"
|
||||
),
|
||||
( "00" * 32,
|
||||
"01" + "00" * 7,
|
||||
"ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd1"
|
||||
"38e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d"
|
||||
"6bbdb0041b2f586b"
|
||||
),
|
||||
( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b"
|
||||
"1c1d1e1f",
|
||||
"0001020304050607",
|
||||
"f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56"
|
||||
"f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f1"
|
||||
"5916155c2be8241a38008b9a26bc35941e2444177c8ade6689de9526"
|
||||
"4986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e"
|
||||
"09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a4750"
|
||||
"32b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c5"
|
||||
"07b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f7"
|
||||
"6dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2"
|
||||
"ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab7"
|
||||
"8fab78c9"
|
||||
),
|
||||
( "00" * 32,
|
||||
"00" * 7 + "02",
|
||||
"c2c64d378cd536374ae204b9ef933fcd"
|
||||
"1a8b2288b3dfa49672ab765b54ee27c7"
|
||||
"8a970e0e955c14f3a88e741b97c286f7"
|
||||
"5f8fc299e8148362fa198a39531bed6d"
|
||||
),
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
for (key, nonce, stream) in self.tv:
|
||||
c = ChaCha20.new(key=unhexlify(b(key)), nonce=unhexlify(b(nonce)))
|
||||
ct = unhexlify(b(stream))
|
||||
pt = b("\x00") * len(ct)
|
||||
self.assertEqual(c.encrypt(pt), ct)
|
||||
|
||||
|
||||
class TestOutput(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
# Encrypt/Decrypt data and test output parameter
|
||||
|
||||
key = b'4' * 32
|
||||
nonce = b'5' * 8
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
|
||||
pt = b'5' * 300
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(len(pt))
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
output = memoryview(bytearray(len(pt)))
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*len(pt))
|
||||
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*len(pt))
|
||||
|
||||
shorter_output = bytearray(len(pt) - 1)
|
||||
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
|
||||
cipher = ChaCha20.new(key=key, nonce=nonce)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(ChaCha20Test)
|
||||
tests += list_test_cases(XChaCha20Test)
|
||||
tests.append(ChaCha20_AGL_NIR())
|
||||
tests.append(ByteArrayTest())
|
||||
tests.append(MemoryviewTest())
|
||||
tests.append(TestOutput())
|
||||
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
776
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_ChaCha20_Poly1305.py
vendored
Normal file
776
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_ChaCha20_Poly1305.py
vendored
Normal file
@ -0,0 +1,776 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
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
|
||||
|
||||
from Crypto.Util.strxor import strxor
|
||||
|
||||
|
||||
def get_tag_random(tag, length):
|
||||
return SHAKE128.new(data=tobytes(tag)).read(length)
|
||||
|
||||
|
||||
class ChaCha20Poly1305Tests(unittest.TestCase):
|
||||
|
||||
key_256 = get_tag_random("key_256", 32)
|
||||
nonce_96 = get_tag_random("nonce_96", 12)
|
||||
data_128 = get_tag_random("data_128", 16)
|
||||
|
||||
def test_loopback(self):
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
pt = get_tag_random("plaintext", 16 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_nonce(self):
|
||||
# Nonce can only be 8 or 12 bytes
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=b'H' * 8)
|
||||
self.assertEqual(len(cipher.nonce), 8)
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=b'H' * 12)
|
||||
self.assertEqual(len(cipher.nonce), 12)
|
||||
|
||||
# If not passed, the nonce is created randomly
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256)
|
||||
nonce1 = cipher.nonce
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256)
|
||||
nonce2 = cipher.nonce
|
||||
self.assertEqual(len(nonce1), 12)
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data_128)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
self.assertEqual(ct, cipher.encrypt(self.data_128))
|
||||
|
||||
def test_nonce_must_be_bytes(self):
|
||||
self.assertRaises(TypeError,
|
||||
ChaCha20_Poly1305.new,
|
||||
key=self.key_256,
|
||||
nonce=u'test12345678')
|
||||
|
||||
def test_nonce_length(self):
|
||||
# nonce can only be 8 or 12 bytes long
|
||||
self.assertRaises(ValueError,
|
||||
ChaCha20_Poly1305.new,
|
||||
key=self.key_256,
|
||||
nonce=b'0' * 7)
|
||||
self.assertRaises(ValueError,
|
||||
ChaCha20_Poly1305.new,
|
||||
key=self.key_256,
|
||||
nonce=b'')
|
||||
|
||||
def test_block_size(self):
|
||||
# Not based on block ciphers
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
self.assertFalse(hasattr(cipher, 'block_size'))
|
||||
|
||||
def test_nonce_attribute(self):
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.nonce, self.nonce_96)
|
||||
|
||||
# By default, a 12 bytes long nonce is randomly generated
|
||||
nonce1 = ChaCha20_Poly1305.new(key=self.key_256).nonce
|
||||
nonce2 = ChaCha20_Poly1305.new(key=self.key_256).nonce
|
||||
self.assertEqual(len(nonce1), 12)
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
|
||||
def test_unknown_parameters(self):
|
||||
self.assertRaises(TypeError,
|
||||
ChaCha20_Poly1305.new,
|
||||
key=self.key_256,
|
||||
param=9)
|
||||
|
||||
def test_null_encryption_decryption(self):
|
||||
for func in "encrypt", "decrypt":
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
result = getattr(cipher, func)(b"")
|
||||
self.assertEqual(result, b"")
|
||||
|
||||
def test_either_encrypt_or_decrypt(self):
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.encrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.decrypt, b"")
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.decrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.encrypt, b"")
|
||||
|
||||
def test_data_must_be_bytes(self):
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*')
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*')
|
||||
|
||||
def test_mac_len(self):
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
_, mac = cipher.encrypt_and_digest(self.data_128)
|
||||
self.assertEqual(len(mac), 16)
|
||||
|
||||
def test_invalid_mac(self):
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data_128)
|
||||
|
||||
invalid_mac = strxor_c(mac, 0x01)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt_and_verify, ct,
|
||||
invalid_mac)
|
||||
|
||||
def test_hex_mac(self):
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
mac_hex = cipher.hexdigest()
|
||||
self.assertEqual(cipher.digest(), unhexlify(mac_hex))
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.hexverify(mac_hex)
|
||||
|
||||
def test_message_chunks(self):
|
||||
# Validate that both associated data and plaintext/ciphertext
|
||||
# can be broken up in chunks of arbitrary length
|
||||
|
||||
auth_data = get_tag_random("authenticated data", 127)
|
||||
plaintext = get_tag_random("plaintext", 127)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(auth_data)
|
||||
ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext)
|
||||
|
||||
def break_up(data, chunk_length):
|
||||
return [data[i:i+chunk_length] for i in range(0, len(data),
|
||||
chunk_length)]
|
||||
|
||||
# Encryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
pt2 = b""
|
||||
for chunk in break_up(ciphertext, chunk_length):
|
||||
pt2 += cipher.decrypt(chunk)
|
||||
self.assertEqual(plaintext, pt2)
|
||||
cipher.verify(ref_mac)
|
||||
|
||||
# Decryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
ct2 = b""
|
||||
for chunk in break_up(plaintext, chunk_length):
|
||||
ct2 += cipher.encrypt(chunk)
|
||||
self.assertEqual(ciphertext, ct2)
|
||||
self.assertEqual(cipher.digest(), ref_mac)
|
||||
|
||||
def test_bytearray(self):
|
||||
|
||||
# Encrypt
|
||||
key_ba = bytearray(self.key_256)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data_128)
|
||||
data_ba = bytearray(self.data_128)
|
||||
|
||||
cipher1 = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data_128)
|
||||
ct = cipher1.encrypt(self.data_128)
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
key_ba[:3] = b'\xFF\xFF\xFF'
|
||||
nonce_ba[:3] = b'\xFF\xFF\xFF'
|
||||
cipher2.update(header_ba)
|
||||
header_ba[:3] = b'\xFF\xFF\xFF'
|
||||
ct_test = cipher2.encrypt(data_ba)
|
||||
data_ba[:3] = b'\x99\x99\x99'
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_ba = bytearray(self.key_256)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data_128)
|
||||
ct_ba = bytearray(ct)
|
||||
tag_ba = bytearray(tag)
|
||||
del data_ba
|
||||
|
||||
cipher3 = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
key_ba[:3] = b'\xFF\xFF\xFF'
|
||||
nonce_ba[:3] = b'\xFF\xFF\xFF'
|
||||
cipher3.update(header_ba)
|
||||
header_ba[:3] = b'\xFF\xFF\xFF'
|
||||
pt_test = cipher3.decrypt(ct_ba)
|
||||
ct_ba[:3] = b'\xFF\xFF\xFF'
|
||||
cipher3.verify(tag_ba)
|
||||
|
||||
self.assertEqual(pt_test, self.data_128)
|
||||
|
||||
def test_memoryview(self):
|
||||
|
||||
# Encrypt
|
||||
key_mv = memoryview(bytearray(self.key_256))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data_128))
|
||||
data_mv = memoryview(bytearray(self.data_128))
|
||||
|
||||
cipher1 = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data_128)
|
||||
ct = cipher1.encrypt(self.data_128)
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
key_mv[:3] = b'\xFF\xFF\xFF'
|
||||
nonce_mv[:3] = b'\xFF\xFF\xFF'
|
||||
cipher2.update(header_mv)
|
||||
header_mv[:3] = b'\xFF\xFF\xFF'
|
||||
ct_test = cipher2.encrypt(data_mv)
|
||||
data_mv[:3] = b'\x99\x99\x99'
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_mv = memoryview(bytearray(self.key_256))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data_128))
|
||||
ct_mv = memoryview(bytearray(ct))
|
||||
tag_mv = memoryview(bytearray(tag))
|
||||
del data_mv
|
||||
|
||||
cipher3 = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
key_mv[:3] = b'\xFF\xFF\xFF'
|
||||
nonce_mv[:3] = b'\xFF\xFF\xFF'
|
||||
cipher3.update(header_mv)
|
||||
header_mv[:3] = b'\xFF\xFF\xFF'
|
||||
pt_test = cipher3.decrypt(ct_mv)
|
||||
ct_mv[:3] = b'\x99\x99\x99'
|
||||
cipher3.verify(tag_mv)
|
||||
|
||||
self.assertEqual(pt_test, self.data_128)
|
||||
|
||||
|
||||
class XChaCha20Poly1305Tests(unittest.TestCase):
|
||||
|
||||
def test_nonce(self):
|
||||
# Nonce can only be 24 bytes
|
||||
cipher = ChaCha20_Poly1305.new(key=b'Y' * 32,
|
||||
nonce=b'H' * 24)
|
||||
self.assertEqual(len(cipher.nonce), 24)
|
||||
self.assertEqual(cipher.nonce, b'H' * 24)
|
||||
|
||||
def test_encrypt(self):
|
||||
# From https://tools.ietf.org/html/draft-arciszewski-xchacha-03
|
||||
# Section A.3.1
|
||||
|
||||
pt = b"""
|
||||
4c616469657320616e642047656e746c656d656e206f662074686520636c6173
|
||||
73206f66202739393a204966204920636f756c64206f6666657220796f75206f
|
||||
6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73
|
||||
637265656e20776f756c642062652069742e"""
|
||||
pt = unhexlify(pt.replace(b"\n", b"").replace(b" ", b""))
|
||||
|
||||
aad = unhexlify(b"50515253c0c1c2c3c4c5c6c7")
|
||||
key = unhexlify(b"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f")
|
||||
iv = unhexlify(b"404142434445464748494a4b4c4d4e4f5051525354555657")
|
||||
|
||||
ct = b"""
|
||||
bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb
|
||||
731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b452
|
||||
2f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff9
|
||||
21f9664c97637da9768812f615c68b13b52e"""
|
||||
ct = unhexlify(ct.replace(b"\n", b"").replace(b" ", b""))
|
||||
|
||||
tag = unhexlify(b"c0875924c1c7987947deafd8780acf49")
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=iv)
|
||||
cipher.update(aad)
|
||||
ct_test, tag_test = cipher.encrypt_and_digest(pt)
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=iv)
|
||||
cipher.update(aad)
|
||||
cipher.decrypt_and_verify(ct, tag)
|
||||
|
||||
|
||||
class ChaCha20Poly1305FSMTests(unittest.TestCase):
|
||||
|
||||
key_256 = get_tag_random("key_256", 32)
|
||||
nonce_96 = get_tag_random("nonce_96", 12)
|
||||
data_128 = get_tag_random("data_128", 16)
|
||||
|
||||
def test_valid_init_encrypt_decrypt_digest_verify(self):
|
||||
# No authenticated data, fixed plaintext
|
||||
# Verify path INIT->ENCRYPT->DIGEST
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data_128)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->DECRYPT->VERIFY
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_init_update_digest_verify(self):
|
||||
# No plaintext, fixed authenticated data
|
||||
# Verify path INIT->UPDATE->DIGEST
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->VERIFY
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_full_path(self):
|
||||
# Fixed authenticated data, fixed plaintext
|
||||
# Verify path INIT->UPDATE->ENCRYPT->DIGEST
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
ct = cipher.encrypt(self.data_128)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->DECRYPT->VERIFY
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_init_digest(self):
|
||||
# Verify path INIT->DIGEST
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.digest()
|
||||
|
||||
def test_valid_init_verify(self):
|
||||
# Verify path INIT->VERIFY
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
mac = cipher.digest()
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_multiple_encrypt_or_decrypt(self):
|
||||
for method_name in "encrypt", "decrypt":
|
||||
for auth_data in (None, b"333", self.data_128,
|
||||
self.data_128 + b"3"):
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
if auth_data is not None:
|
||||
cipher.update(auth_data)
|
||||
method = getattr(cipher, method_name)
|
||||
method(self.data_128)
|
||||
method(self.data_128)
|
||||
method(self.data_128)
|
||||
method(self.data_128)
|
||||
|
||||
def test_valid_multiple_digest_or_verify(self):
|
||||
# Multiple calls to digest
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
first_mac = cipher.digest()
|
||||
for x in range(4):
|
||||
self.assertEqual(first_mac, cipher.digest())
|
||||
|
||||
# Multiple calls to verify
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
for x in range(5):
|
||||
cipher.verify(first_mac)
|
||||
|
||||
def test_valid_encrypt_and_digest_decrypt_and_verify(self):
|
||||
# encrypt_and_digest
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data_128)
|
||||
|
||||
# decrypt_and_verify
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
pt = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(self.data_128, pt)
|
||||
|
||||
def test_invalid_mixing_encrypt_decrypt(self):
|
||||
# Once per method, with or without assoc. data
|
||||
for method1_name, method2_name in (("encrypt", "decrypt"),
|
||||
("decrypt", "encrypt")):
|
||||
for assoc_data_present in (True, False):
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
if assoc_data_present:
|
||||
cipher.update(self.data_128)
|
||||
getattr(cipher, method1_name)(self.data_128)
|
||||
self.assertRaises(TypeError, getattr(cipher, method2_name),
|
||||
self.data_128)
|
||||
|
||||
def test_invalid_encrypt_or_update_after_digest(self):
|
||||
for method_name in "encrypt", "update":
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.encrypt(self.data_128)
|
||||
cipher.digest()
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data_128)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.encrypt_and_digest(self.data_128)
|
||||
|
||||
def test_invalid_decrypt_or_update_after_verify(self):
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data_128)
|
||||
mac = cipher.digest()
|
||||
|
||||
for method_name in "decrypt", "update":
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data_128)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data_128)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=self.key_256,
|
||||
nonce=self.nonce_96)
|
||||
cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data_128)
|
||||
|
||||
|
||||
def compact(x):
|
||||
return unhexlify(x.replace(" ", "").replace(":", ""))
|
||||
|
||||
|
||||
class TestVectorsRFC(unittest.TestCase):
|
||||
"""Test cases from RFC7539"""
|
||||
|
||||
# AAD, PT, CT, MAC, KEY, NONCE
|
||||
test_vectors_hex = [
|
||||
( '50 51 52 53 c0 c1 c2 c3 c4 c5 c6 c7',
|
||||
'4c 61 64 69 65 73 20 61 6e 64 20 47 65 6e 74 6c'
|
||||
'65 6d 65 6e 20 6f 66 20 74 68 65 20 63 6c 61 73'
|
||||
'73 20 6f 66 20 27 39 39 3a 20 49 66 20 49 20 63'
|
||||
'6f 75 6c 64 20 6f 66 66 65 72 20 79 6f 75 20 6f'
|
||||
'6e 6c 79 20 6f 6e 65 20 74 69 70 20 66 6f 72 20'
|
||||
'74 68 65 20 66 75 74 75 72 65 2c 20 73 75 6e 73'
|
||||
'63 72 65 65 6e 20 77 6f 75 6c 64 20 62 65 20 69'
|
||||
'74 2e',
|
||||
'd3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2'
|
||||
'a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6'
|
||||
'3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b'
|
||||
'1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36'
|
||||
'92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58'
|
||||
'fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc'
|
||||
'3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b'
|
||||
'61 16',
|
||||
'1a:e1:0b:59:4f:09:e2:6a:7e:90:2e:cb:d0:60:06:91',
|
||||
'80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f'
|
||||
'90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f',
|
||||
'07 00 00 00' + '40 41 42 43 44 45 46 47',
|
||||
),
|
||||
( 'f3 33 88 86 00 00 00 00 00 00 4e 91',
|
||||
'49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 73 20'
|
||||
'61 72 65 20 64 72 61 66 74 20 64 6f 63 75 6d 65'
|
||||
'6e 74 73 20 76 61 6c 69 64 20 66 6f 72 20 61 20'
|
||||
'6d 61 78 69 6d 75 6d 20 6f 66 20 73 69 78 20 6d'
|
||||
'6f 6e 74 68 73 20 61 6e 64 20 6d 61 79 20 62 65'
|
||||
'20 75 70 64 61 74 65 64 2c 20 72 65 70 6c 61 63'
|
||||
'65 64 2c 20 6f 72 20 6f 62 73 6f 6c 65 74 65 64'
|
||||
'20 62 79 20 6f 74 68 65 72 20 64 6f 63 75 6d 65'
|
||||
'6e 74 73 20 61 74 20 61 6e 79 20 74 69 6d 65 2e'
|
||||
'20 49 74 20 69 73 20 69 6e 61 70 70 72 6f 70 72'
|
||||
'69 61 74 65 20 74 6f 20 75 73 65 20 49 6e 74 65'
|
||||
'72 6e 65 74 2d 44 72 61 66 74 73 20 61 73 20 72'
|
||||
'65 66 65 72 65 6e 63 65 20 6d 61 74 65 72 69 61'
|
||||
'6c 20 6f 72 20 74 6f 20 63 69 74 65 20 74 68 65'
|
||||
'6d 20 6f 74 68 65 72 20 74 68 61 6e 20 61 73 20'
|
||||
'2f e2 80 9c 77 6f 72 6b 20 69 6e 20 70 72 6f 67'
|
||||
'72 65 73 73 2e 2f e2 80 9d',
|
||||
'64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd'
|
||||
'5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2'
|
||||
'4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0'
|
||||
'bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf'
|
||||
'33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81'
|
||||
'14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55'
|
||||
'97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38'
|
||||
'36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4'
|
||||
'b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9'
|
||||
'90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e'
|
||||
'af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a'
|
||||
'0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a'
|
||||
'0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e'
|
||||
'ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10'
|
||||
'49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30'
|
||||
'30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29'
|
||||
'a6 ad 5c b4 02 2b 02 70 9b',
|
||||
'ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38',
|
||||
'1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0'
|
||||
'47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0',
|
||||
'00 00 00 00 01 02 03 04 05 06 07 08',
|
||||
)
|
||||
]
|
||||
|
||||
test_vectors = [[unhexlify(x.replace(" ", "").replace(":", "")) for x in tv] for tv in test_vectors_hex]
|
||||
|
||||
def runTest(self):
|
||||
for assoc_data, pt, ct, mac, key, nonce in self.test_vectors:
|
||||
# Encrypt
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
cipher.update(assoc_data)
|
||||
ct2, mac2 = cipher.encrypt_and_digest(pt)
|
||||
self.assertEqual(ct, ct2)
|
||||
self.assertEqual(mac, mac2)
|
||||
|
||||
# Decrypt
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
cipher.update(assoc_data)
|
||||
pt2 = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
|
||||
class TestVectorsWycheproof(unittest.TestCase):
|
||||
|
||||
def __init__(self, wycheproof_warnings):
|
||||
unittest.TestCase.__init__(self)
|
||||
self._wycheproof_warnings = wycheproof_warnings
|
||||
self._id = "None"
|
||||
|
||||
def load_tests(self, filename):
|
||||
|
||||
def filter_tag(group):
|
||||
return group['tagSize'] // 8
|
||||
|
||||
def filter_algo(root):
|
||||
return root['algorithm']
|
||||
|
||||
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):
|
||||
self.tv = []
|
||||
self.tv.extend(self.load_tests("chacha20_poly1305_test.json"))
|
||||
self.tv.extend(self.load_tests("xchacha20_poly1305_test.json"))
|
||||
|
||||
def shortDescription(self):
|
||||
return self._id
|
||||
|
||||
def warn(self, tv):
|
||||
if tv.warning and self._wycheproof_warnings:
|
||||
import warnings
|
||||
warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment))
|
||||
|
||||
def test_encrypt(self, tv):
|
||||
self._id = "Wycheproof Encrypt %s Test #%s" % (tv.algo, tv.id)
|
||||
|
||||
try:
|
||||
cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv)
|
||||
except ValueError as e:
|
||||
assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e)
|
||||
return
|
||||
|
||||
cipher.update(tv.aad)
|
||||
ct, tag = cipher.encrypt_and_digest(tv.msg)
|
||||
if tv.valid:
|
||||
self.assertEqual(ct, tv.ct)
|
||||
self.assertEqual(tag, tv.tag)
|
||||
self.warn(tv)
|
||||
|
||||
def test_decrypt(self, tv):
|
||||
self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id)
|
||||
|
||||
try:
|
||||
cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv)
|
||||
except ValueError as e:
|
||||
assert len(tv.iv) not in (8, 12) and "Nonce must be" in str(e)
|
||||
return
|
||||
|
||||
cipher.update(tv.aad)
|
||||
try:
|
||||
pt = cipher.decrypt_and_verify(tv.ct, tv.tag)
|
||||
except ValueError:
|
||||
assert not tv.valid
|
||||
else:
|
||||
assert tv.valid
|
||||
self.assertEqual(pt, tv.msg)
|
||||
self.warn(tv)
|
||||
|
||||
def test_corrupt_decrypt(self, tv):
|
||||
self._id = "Wycheproof Corrupt Decrypt ChaCha20-Poly1305 Test #" + str(tv.id)
|
||||
if len(tv.iv) == 0 or len(tv.ct) < 1:
|
||||
return
|
||||
cipher = ChaCha20_Poly1305.new(key=tv.key, nonce=tv.iv)
|
||||
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)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
for tv in self.tv:
|
||||
self.test_encrypt(tv)
|
||||
self.test_decrypt(tv)
|
||||
self.test_corrupt_decrypt(tv)
|
||||
|
||||
|
||||
class TestOutput(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
# Encrypt/Decrypt data and test output parameter
|
||||
|
||||
key = b'4' * 32
|
||||
nonce = b'5' * 12
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
|
||||
pt = b'5' * 16
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(16)
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
output = memoryview(bytearray(16))
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16)
|
||||
|
||||
shorter_output = bytearray(7)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
|
||||
cipher = ChaCha20_Poly1305.new(key=key, nonce=nonce)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
wycheproof_warnings = config.get('wycheproof_warnings')
|
||||
|
||||
tests = []
|
||||
tests += list_test_cases(ChaCha20Poly1305Tests)
|
||||
tests += list_test_cases(XChaCha20Poly1305Tests)
|
||||
tests += list_test_cases(ChaCha20Poly1305FSMTests)
|
||||
tests += [TestVectorsRFC()]
|
||||
tests += [TestVectorsWycheproof(wycheproof_warnings)]
|
||||
tests += [TestOutput()]
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def suite():
|
||||
unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
374
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_DES.py
vendored
Normal file
374
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_DES.py
vendored
Normal file
@ -0,0 +1,374 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/DES.py: Self-test for the (Single) DES cipher
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-test suite for Crypto.Cipher.DES"""
|
||||
|
||||
import unittest
|
||||
|
||||
from Crypto.Cipher import DES
|
||||
|
||||
# This is a list of (plaintext, ciphertext, key, description) tuples.
|
||||
SP800_17_B1_KEY = '01' * 8
|
||||
SP800_17_B2_PT = '00' * 8
|
||||
test_data = [
|
||||
# Test vectors from Appendix A of NIST SP 800-17
|
||||
# "Modes of Operation Validation System (MOVS): Requirements and Procedures"
|
||||
# http://csrc.nist.gov/publications/nistpubs/800-17/800-17.pdf
|
||||
|
||||
# Appendix A - "Sample Round Outputs for the DES"
|
||||
('0000000000000000', '82dcbafbdeab6602', '10316e028c8f3b4a',
|
||||
"NIST SP800-17 A"),
|
||||
|
||||
# Table B.1 - Variable Plaintext Known Answer Test
|
||||
('8000000000000000', '95f8a5e5dd31d900', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #0'),
|
||||
('4000000000000000', 'dd7f121ca5015619', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #1'),
|
||||
('2000000000000000', '2e8653104f3834ea', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #2'),
|
||||
('1000000000000000', '4bd388ff6cd81d4f', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #3'),
|
||||
('0800000000000000', '20b9e767b2fb1456', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #4'),
|
||||
('0400000000000000', '55579380d77138ef', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #5'),
|
||||
('0200000000000000', '6cc5defaaf04512f', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #6'),
|
||||
('0100000000000000', '0d9f279ba5d87260', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #7'),
|
||||
('0080000000000000', 'd9031b0271bd5a0a', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #8'),
|
||||
('0040000000000000', '424250b37c3dd951', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #9'),
|
||||
('0020000000000000', 'b8061b7ecd9a21e5', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #10'),
|
||||
('0010000000000000', 'f15d0f286b65bd28', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #11'),
|
||||
('0008000000000000', 'add0cc8d6e5deba1', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #12'),
|
||||
('0004000000000000', 'e6d5f82752ad63d1', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #13'),
|
||||
('0002000000000000', 'ecbfe3bd3f591a5e', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #14'),
|
||||
('0001000000000000', 'f356834379d165cd', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #15'),
|
||||
('0000800000000000', '2b9f982f20037fa9', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #16'),
|
||||
('0000400000000000', '889de068a16f0be6', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #17'),
|
||||
('0000200000000000', 'e19e275d846a1298', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #18'),
|
||||
('0000100000000000', '329a8ed523d71aec', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #19'),
|
||||
('0000080000000000', 'e7fce22557d23c97', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #20'),
|
||||
('0000040000000000', '12a9f5817ff2d65d', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #21'),
|
||||
('0000020000000000', 'a484c3ad38dc9c19', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #22'),
|
||||
('0000010000000000', 'fbe00a8a1ef8ad72', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #23'),
|
||||
('0000008000000000', '750d079407521363', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #24'),
|
||||
('0000004000000000', '64feed9c724c2faf', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #25'),
|
||||
('0000002000000000', 'f02b263b328e2b60', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #26'),
|
||||
('0000001000000000', '9d64555a9a10b852', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #27'),
|
||||
('0000000800000000', 'd106ff0bed5255d7', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #28'),
|
||||
('0000000400000000', 'e1652c6b138c64a5', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #29'),
|
||||
('0000000200000000', 'e428581186ec8f46', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #30'),
|
||||
('0000000100000000', 'aeb5f5ede22d1a36', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #31'),
|
||||
('0000000080000000', 'e943d7568aec0c5c', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #32'),
|
||||
('0000000040000000', 'df98c8276f54b04b', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #33'),
|
||||
('0000000020000000', 'b160e4680f6c696f', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #34'),
|
||||
('0000000010000000', 'fa0752b07d9c4ab8', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #35'),
|
||||
('0000000008000000', 'ca3a2b036dbc8502', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #36'),
|
||||
('0000000004000000', '5e0905517bb59bcf', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #37'),
|
||||
('0000000002000000', '814eeb3b91d90726', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #38'),
|
||||
('0000000001000000', '4d49db1532919c9f', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #39'),
|
||||
('0000000000800000', '25eb5fc3f8cf0621', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #40'),
|
||||
('0000000000400000', 'ab6a20c0620d1c6f', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #41'),
|
||||
('0000000000200000', '79e90dbc98f92cca', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #42'),
|
||||
('0000000000100000', '866ecedd8072bb0e', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #43'),
|
||||
('0000000000080000', '8b54536f2f3e64a8', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #44'),
|
||||
('0000000000040000', 'ea51d3975595b86b', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #45'),
|
||||
('0000000000020000', 'caffc6ac4542de31', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #46'),
|
||||
('0000000000010000', '8dd45a2ddf90796c', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #47'),
|
||||
('0000000000008000', '1029d55e880ec2d0', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #48'),
|
||||
('0000000000004000', '5d86cb23639dbea9', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #49'),
|
||||
('0000000000002000', '1d1ca853ae7c0c5f', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #50'),
|
||||
('0000000000001000', 'ce332329248f3228', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #51'),
|
||||
('0000000000000800', '8405d1abe24fb942', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #52'),
|
||||
('0000000000000400', 'e643d78090ca4207', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #53'),
|
||||
('0000000000000200', '48221b9937748a23', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #54'),
|
||||
('0000000000000100', 'dd7c0bbd61fafd54', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #55'),
|
||||
('0000000000000080', '2fbc291a570db5c4', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #56'),
|
||||
('0000000000000040', 'e07c30d7e4e26e12', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #57'),
|
||||
('0000000000000020', '0953e2258e8e90a1', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #58'),
|
||||
('0000000000000010', '5b711bc4ceebf2ee', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #59'),
|
||||
('0000000000000008', 'cc083f1e6d9e85f6', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #60'),
|
||||
('0000000000000004', 'd2fd8867d50d2dfe', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #61'),
|
||||
('0000000000000002', '06e7ea22ce92708f', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #62'),
|
||||
('0000000000000001', '166b40b44aba4bd6', SP800_17_B1_KEY,
|
||||
'NIST SP800-17 B.1 #63'),
|
||||
|
||||
# Table B.2 - Variable Key Known Answer Test
|
||||
(SP800_17_B2_PT, '95a8d72813daa94d', '8001010101010101',
|
||||
'NIST SP800-17 B.2 #0'),
|
||||
(SP800_17_B2_PT, '0eec1487dd8c26d5', '4001010101010101',
|
||||
'NIST SP800-17 B.2 #1'),
|
||||
(SP800_17_B2_PT, '7ad16ffb79c45926', '2001010101010101',
|
||||
'NIST SP800-17 B.2 #2'),
|
||||
(SP800_17_B2_PT, 'd3746294ca6a6cf3', '1001010101010101',
|
||||
'NIST SP800-17 B.2 #3'),
|
||||
(SP800_17_B2_PT, '809f5f873c1fd761', '0801010101010101',
|
||||
'NIST SP800-17 B.2 #4'),
|
||||
(SP800_17_B2_PT, 'c02faffec989d1fc', '0401010101010101',
|
||||
'NIST SP800-17 B.2 #5'),
|
||||
(SP800_17_B2_PT, '4615aa1d33e72f10', '0201010101010101',
|
||||
'NIST SP800-17 B.2 #6'),
|
||||
(SP800_17_B2_PT, '2055123350c00858', '0180010101010101',
|
||||
'NIST SP800-17 B.2 #7'),
|
||||
(SP800_17_B2_PT, 'df3b99d6577397c8', '0140010101010101',
|
||||
'NIST SP800-17 B.2 #8'),
|
||||
(SP800_17_B2_PT, '31fe17369b5288c9', '0120010101010101',
|
||||
'NIST SP800-17 B.2 #9'),
|
||||
(SP800_17_B2_PT, 'dfdd3cc64dae1642', '0110010101010101',
|
||||
'NIST SP800-17 B.2 #10'),
|
||||
(SP800_17_B2_PT, '178c83ce2b399d94', '0108010101010101',
|
||||
'NIST SP800-17 B.2 #11'),
|
||||
(SP800_17_B2_PT, '50f636324a9b7f80', '0104010101010101',
|
||||
'NIST SP800-17 B.2 #12'),
|
||||
(SP800_17_B2_PT, 'a8468ee3bc18f06d', '0102010101010101',
|
||||
'NIST SP800-17 B.2 #13'),
|
||||
(SP800_17_B2_PT, 'a2dc9e92fd3cde92', '0101800101010101',
|
||||
'NIST SP800-17 B.2 #14'),
|
||||
(SP800_17_B2_PT, 'cac09f797d031287', '0101400101010101',
|
||||
'NIST SP800-17 B.2 #15'),
|
||||
(SP800_17_B2_PT, '90ba680b22aeb525', '0101200101010101',
|
||||
'NIST SP800-17 B.2 #16'),
|
||||
(SP800_17_B2_PT, 'ce7a24f350e280b6', '0101100101010101',
|
||||
'NIST SP800-17 B.2 #17'),
|
||||
(SP800_17_B2_PT, '882bff0aa01a0b87', '0101080101010101',
|
||||
'NIST SP800-17 B.2 #18'),
|
||||
(SP800_17_B2_PT, '25610288924511c2', '0101040101010101',
|
||||
'NIST SP800-17 B.2 #19'),
|
||||
(SP800_17_B2_PT, 'c71516c29c75d170', '0101020101010101',
|
||||
'NIST SP800-17 B.2 #20'),
|
||||
(SP800_17_B2_PT, '5199c29a52c9f059', '0101018001010101',
|
||||
'NIST SP800-17 B.2 #21'),
|
||||
(SP800_17_B2_PT, 'c22f0a294a71f29f', '0101014001010101',
|
||||
'NIST SP800-17 B.2 #22'),
|
||||
(SP800_17_B2_PT, 'ee371483714c02ea', '0101012001010101',
|
||||
'NIST SP800-17 B.2 #23'),
|
||||
(SP800_17_B2_PT, 'a81fbd448f9e522f', '0101011001010101',
|
||||
'NIST SP800-17 B.2 #24'),
|
||||
(SP800_17_B2_PT, '4f644c92e192dfed', '0101010801010101',
|
||||
'NIST SP800-17 B.2 #25'),
|
||||
(SP800_17_B2_PT, '1afa9a66a6df92ae', '0101010401010101',
|
||||
'NIST SP800-17 B.2 #26'),
|
||||
(SP800_17_B2_PT, 'b3c1cc715cb879d8', '0101010201010101',
|
||||
'NIST SP800-17 B.2 #27'),
|
||||
(SP800_17_B2_PT, '19d032e64ab0bd8b', '0101010180010101',
|
||||
'NIST SP800-17 B.2 #28'),
|
||||
(SP800_17_B2_PT, '3cfaa7a7dc8720dc', '0101010140010101',
|
||||
'NIST SP800-17 B.2 #29'),
|
||||
(SP800_17_B2_PT, 'b7265f7f447ac6f3', '0101010120010101',
|
||||
'NIST SP800-17 B.2 #30'),
|
||||
(SP800_17_B2_PT, '9db73b3c0d163f54', '0101010110010101',
|
||||
'NIST SP800-17 B.2 #31'),
|
||||
(SP800_17_B2_PT, '8181b65babf4a975', '0101010108010101',
|
||||
'NIST SP800-17 B.2 #32'),
|
||||
(SP800_17_B2_PT, '93c9b64042eaa240', '0101010104010101',
|
||||
'NIST SP800-17 B.2 #33'),
|
||||
(SP800_17_B2_PT, '5570530829705592', '0101010102010101',
|
||||
'NIST SP800-17 B.2 #34'),
|
||||
(SP800_17_B2_PT, '8638809e878787a0', '0101010101800101',
|
||||
'NIST SP800-17 B.2 #35'),
|
||||
(SP800_17_B2_PT, '41b9a79af79ac208', '0101010101400101',
|
||||
'NIST SP800-17 B.2 #36'),
|
||||
(SP800_17_B2_PT, '7a9be42f2009a892', '0101010101200101',
|
||||
'NIST SP800-17 B.2 #37'),
|
||||
(SP800_17_B2_PT, '29038d56ba6d2745', '0101010101100101',
|
||||
'NIST SP800-17 B.2 #38'),
|
||||
(SP800_17_B2_PT, '5495c6abf1e5df51', '0101010101080101',
|
||||
'NIST SP800-17 B.2 #39'),
|
||||
(SP800_17_B2_PT, 'ae13dbd561488933', '0101010101040101',
|
||||
'NIST SP800-17 B.2 #40'),
|
||||
(SP800_17_B2_PT, '024d1ffa8904e389', '0101010101020101',
|
||||
'NIST SP800-17 B.2 #41'),
|
||||
(SP800_17_B2_PT, 'd1399712f99bf02e', '0101010101018001',
|
||||
'NIST SP800-17 B.2 #42'),
|
||||
(SP800_17_B2_PT, '14c1d7c1cffec79e', '0101010101014001',
|
||||
'NIST SP800-17 B.2 #43'),
|
||||
(SP800_17_B2_PT, '1de5279dae3bed6f', '0101010101012001',
|
||||
'NIST SP800-17 B.2 #44'),
|
||||
(SP800_17_B2_PT, 'e941a33f85501303', '0101010101011001',
|
||||
'NIST SP800-17 B.2 #45'),
|
||||
(SP800_17_B2_PT, 'da99dbbc9a03f379', '0101010101010801',
|
||||
'NIST SP800-17 B.2 #46'),
|
||||
(SP800_17_B2_PT, 'b7fc92f91d8e92e9', '0101010101010401',
|
||||
'NIST SP800-17 B.2 #47'),
|
||||
(SP800_17_B2_PT, 'ae8e5caa3ca04e85', '0101010101010201',
|
||||
'NIST SP800-17 B.2 #48'),
|
||||
(SP800_17_B2_PT, '9cc62df43b6eed74', '0101010101010180',
|
||||
'NIST SP800-17 B.2 #49'),
|
||||
(SP800_17_B2_PT, 'd863dbb5c59a91a0', '0101010101010140',
|
||||
'NIST SP800-17 B.2 #50'),
|
||||
(SP800_17_B2_PT, 'a1ab2190545b91d7', '0101010101010120',
|
||||
'NIST SP800-17 B.2 #51'),
|
||||
(SP800_17_B2_PT, '0875041e64c570f7', '0101010101010110',
|
||||
'NIST SP800-17 B.2 #52'),
|
||||
(SP800_17_B2_PT, '5a594528bebef1cc', '0101010101010108',
|
||||
'NIST SP800-17 B.2 #53'),
|
||||
(SP800_17_B2_PT, 'fcdb3291de21f0c0', '0101010101010104',
|
||||
'NIST SP800-17 B.2 #54'),
|
||||
(SP800_17_B2_PT, '869efd7f9f265a09', '0101010101010102',
|
||||
'NIST SP800-17 B.2 #55'),
|
||||
]
|
||||
|
||||
class RonRivestTest(unittest.TestCase):
|
||||
""" Ronald L. Rivest's DES test, see
|
||||
http://people.csail.mit.edu/rivest/Destest.txt
|
||||
ABSTRACT
|
||||
--------
|
||||
|
||||
We present a simple way to test the correctness of a DES implementation:
|
||||
Use the recurrence relation:
|
||||
|
||||
X0 = 9474B8E8C73BCA7D (hexadecimal)
|
||||
|
||||
X(i+1) = IF (i is even) THEN E(Xi,Xi) ELSE D(Xi,Xi)
|
||||
|
||||
to compute a sequence of 64-bit values: X0, X1, X2, ..., X16. Here
|
||||
E(X,K) denotes the DES encryption of X using key K, and D(X,K) denotes
|
||||
the DES decryption of X using key K. If you obtain
|
||||
|
||||
X16 = 1B1A2DDB4C642438
|
||||
|
||||
your implementation does not have any of the 36,568 possible single-fault
|
||||
errors described herein.
|
||||
"""
|
||||
def runTest(self):
|
||||
from binascii import b2a_hex
|
||||
|
||||
X = []
|
||||
X[0:] = [b'\x94\x74\xB8\xE8\xC7\x3B\xCA\x7D']
|
||||
|
||||
for i in range(16):
|
||||
c = DES.new(X[i],DES.MODE_ECB)
|
||||
if not (i&1): # (num&1) returns 1 for odd numbers
|
||||
X[i+1:] = [c.encrypt(X[i])] # even
|
||||
else:
|
||||
X[i+1:] = [c.decrypt(X[i])] # odd
|
||||
|
||||
self.assertEqual(b2a_hex(X[16]),
|
||||
b2a_hex(b'\x1B\x1A\x2D\xDB\x4C\x64\x24\x38'))
|
||||
|
||||
|
||||
class TestOutput(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
# Encrypt/Decrypt data and test output parameter
|
||||
|
||||
cipher = DES.new(b'4'*8, DES.MODE_ECB)
|
||||
|
||||
pt = b'5' * 8
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(8)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
output = memoryview(bytearray(8))
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*8)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*8)
|
||||
|
||||
shorter_output = bytearray(7)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
from .common import make_block_tests
|
||||
tests = make_block_tests(DES, "DES", test_data)
|
||||
tests += [RonRivestTest()]
|
||||
tests += [TestOutput()]
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
195
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_DES3.py
vendored
Normal file
195
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_DES3.py
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/DES3.py: Self-test for the Triple-DES cipher
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-test suite for Crypto.Cipher.DES3"""
|
||||
|
||||
import unittest
|
||||
from binascii import hexlify, unhexlify
|
||||
|
||||
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_test_vectors
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
|
||||
# This is a list of (plaintext, ciphertext, key, description) tuples.
|
||||
test_data = [
|
||||
# Test vector from Appendix B of NIST SP 800-67
|
||||
# "Recommendation for the Triple Data Encryption Algorithm (TDEA) Block
|
||||
# Cipher"
|
||||
# http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf
|
||||
('54686520717566636b2062726f776e20666f78206a756d70',
|
||||
'a826fd8ce53b855fcce21c8112256fe668d5c05dd9b6b900',
|
||||
'0123456789abcdef23456789abcdef01456789abcdef0123',
|
||||
'NIST SP800-67 B.1'),
|
||||
|
||||
# This test is designed to test the DES3 API, not the correctness of the
|
||||
# output.
|
||||
('21e81b7ade88a259', '5c577d4d9b20c0f8',
|
||||
'9b397ebf81b1181e282f4bb8adbadc6b', 'Two-key 3DES'),
|
||||
]
|
||||
|
||||
# NIST CAVP test vectors
|
||||
|
||||
nist_tdes_mmt_files = ("TECBMMT2.rsp", "TECBMMT3.rsp")
|
||||
|
||||
for tdes_file in nist_tdes_mmt_files:
|
||||
|
||||
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
|
||||
if isinstance(tv, str):
|
||||
continue
|
||||
|
||||
key = tv.key1 + tv.key2 + tv.key3
|
||||
test_data_item = (tostr(hexlify(tv.plaintext)),
|
||||
tostr(hexlify(tv.ciphertext)),
|
||||
tostr(hexlify(key)),
|
||||
"%s (%s)" % (tdes_file, index))
|
||||
test_data.append(test_data_item)
|
||||
|
||||
|
||||
class CheckParity(unittest.TestCase):
|
||||
|
||||
def test_parity_option2(self):
|
||||
before_2k = unhexlify("CABF326FA56734324FFCCABCDEFACABF")
|
||||
after_2k = DES3.adjust_key_parity(before_2k)
|
||||
self.assertEqual(after_2k,
|
||||
unhexlify("CBBF326EA46734324FFDCBBCDFFBCBBF"))
|
||||
|
||||
def test_parity_option3(self):
|
||||
before_3k = unhexlify("AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC")
|
||||
after_3k = DES3.adjust_key_parity(before_3k)
|
||||
self.assertEqual(after_3k,
|
||||
unhexlify("ABABABABABABABABBABABABABABABABACDCDCDCDCDCDCDCD"))
|
||||
|
||||
def test_degradation(self):
|
||||
sub_key1 = bchr(1) * 8
|
||||
sub_key2 = bchr(255) * 8
|
||||
|
||||
# K1 == K2
|
||||
self.assertRaises(ValueError, DES3.adjust_key_parity,
|
||||
sub_key1 * 2 + sub_key2)
|
||||
|
||||
# K2 == K3
|
||||
self.assertRaises(ValueError, DES3.adjust_key_parity,
|
||||
sub_key1 + sub_key2 * 2)
|
||||
|
||||
# K1 == K2 == K3
|
||||
self.assertRaises(ValueError, DES3.adjust_key_parity,
|
||||
sub_key1 * 3)
|
||||
|
||||
# K1 == K2 (with different parity)
|
||||
self.assertRaises(ValueError, DES3.adjust_key_parity,
|
||||
sub_key1 + strxor_c(sub_key1, 1) + sub_key2)
|
||||
|
||||
|
||||
class DegenerateToDESTest(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
sub_key1 = bchr(1) * 8
|
||||
sub_key2 = bchr(255) * 8
|
||||
|
||||
# K1 == K2
|
||||
self.assertRaises(ValueError, DES3.new,
|
||||
sub_key1 * 2 + sub_key2,
|
||||
DES3.MODE_ECB)
|
||||
|
||||
# K2 == K3
|
||||
self.assertRaises(ValueError, DES3.new,
|
||||
sub_key1 + sub_key2 * 2,
|
||||
DES3.MODE_ECB)
|
||||
|
||||
# K1 == K2 == K3
|
||||
self.assertRaises(ValueError, DES3.new,
|
||||
sub_key1 * 3,
|
||||
DES3.MODE_ECB)
|
||||
|
||||
# K2 == K3 (parity is ignored)
|
||||
self.assertRaises(ValueError, DES3.new,
|
||||
sub_key1 + sub_key2 + strxor_c(sub_key2, 0x1),
|
||||
DES3.MODE_ECB)
|
||||
|
||||
|
||||
class TestOutput(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
# Encrypt/Decrypt data and test output parameter
|
||||
|
||||
cipher = DES3.new(b'4'*8 + b'G'*8 + b'T'*8, DES3.MODE_ECB)
|
||||
|
||||
pt = b'5' * 16
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(16)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
output = memoryview(bytearray(16))
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*16)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*16)
|
||||
|
||||
shorter_output = bytearray(7)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
from .common import make_block_tests
|
||||
|
||||
tests = []
|
||||
tests = make_block_tests(DES3, "DES3", test_data)
|
||||
tests.append(DegenerateToDESTest())
|
||||
tests += list_test_cases(CheckParity)
|
||||
tests += [TestOutput()]
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
def suite():
|
||||
unittest.TestSuite(get_tests())
|
||||
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
773
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_EAX.py
vendored
Normal file
773
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_EAX.py
vendored
Normal file
@ -0,0 +1,773 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
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.strxor import strxor
|
||||
|
||||
|
||||
def get_tag_random(tag, length):
|
||||
return SHAKE128.new(data=tobytes(tag)).read(length)
|
||||
|
||||
|
||||
class EaxTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
key_192 = get_tag_random("key_192", 16)
|
||||
nonce_96 = get_tag_random("nonce_128", 12)
|
||||
data_128 = get_tag_random("data_128", 16)
|
||||
|
||||
def test_loopback_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
pt = get_tag_random("plaintext", 16 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_loopback_64(self):
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96)
|
||||
pt = get_tag_random("plaintext", 8 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_EAX, nonce=self.nonce_96)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_nonce(self):
|
||||
# If not passed, the nonce is created randomly
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX)
|
||||
nonce1 = cipher.nonce
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX)
|
||||
nonce2 = cipher.nonce
|
||||
self.assertEqual(len(nonce1), 16)
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, self.nonce_96)
|
||||
ct = cipher.encrypt(self.data_128)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertEqual(ct, cipher.encrypt(self.data_128))
|
||||
|
||||
def test_nonce_must_be_bytes(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_EAX,
|
||||
nonce=u'test12345678')
|
||||
|
||||
def test_nonce_length(self):
|
||||
# nonce can be of any length (but not empty)
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_EAX,
|
||||
nonce=b"")
|
||||
|
||||
for x in range(1, 128):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=bchr(1) * x)
|
||||
cipher.encrypt(bchr(1))
|
||||
|
||||
def test_block_size_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.block_size, AES.block_size)
|
||||
|
||||
def test_block_size_64(self):
|
||||
cipher = DES3.new(self.key_192, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.block_size, DES3.block_size)
|
||||
|
||||
def test_nonce_attribute(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.nonce, self.nonce_96)
|
||||
|
||||
# By default, a 16 bytes long nonce is randomly generated
|
||||
nonce1 = AES.new(self.key_128, AES.MODE_EAX).nonce
|
||||
nonce2 = AES.new(self.key_128, AES.MODE_EAX).nonce
|
||||
self.assertEqual(len(nonce1), 16)
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
|
||||
def test_unknown_parameters(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_EAX,
|
||||
self.nonce_96, 7)
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96, unknown=7)
|
||||
|
||||
# But some are only known by the base cipher
|
||||
# (e.g. use_aesni consumed by the AES module)
|
||||
AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96,
|
||||
use_aesni=False)
|
||||
|
||||
def test_null_encryption_decryption(self):
|
||||
for func in "encrypt", "decrypt":
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
result = getattr(cipher, func)(b"")
|
||||
self.assertEqual(result, b"")
|
||||
|
||||
def test_either_encrypt_or_decrypt(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.encrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.decrypt, b"")
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.decrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.encrypt, b"")
|
||||
|
||||
def test_data_must_be_bytes(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*')
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*')
|
||||
|
||||
def test_mac_len(self):
|
||||
# Invalid MAC length
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96, mac_len=2-1)
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96, mac_len=16+1)
|
||||
|
||||
# Valid MAC length
|
||||
for mac_len in range(2, 16 + 1):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96,
|
||||
mac_len=mac_len)
|
||||
_, mac = cipher.encrypt_and_digest(self.data_128)
|
||||
self.assertEqual(len(mac), mac_len)
|
||||
|
||||
# Default MAC length
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
_, mac = cipher.encrypt_and_digest(self.data_128)
|
||||
self.assertEqual(len(mac), 16)
|
||||
|
||||
def test_invalid_mac(self):
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data_128)
|
||||
|
||||
invalid_mac = strxor_c(mac, 0x01)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt_and_verify, ct,
|
||||
invalid_mac)
|
||||
|
||||
def test_hex_mac(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
mac_hex = cipher.hexdigest()
|
||||
self.assertEqual(cipher.digest(), unhexlify(mac_hex))
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.hexverify(mac_hex)
|
||||
|
||||
def test_message_chunks(self):
|
||||
# Validate that both associated data and plaintext/ciphertext
|
||||
# can be broken up in chunks of arbitrary length
|
||||
|
||||
auth_data = get_tag_random("authenticated data", 127)
|
||||
plaintext = get_tag_random("plaintext", 127)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.update(auth_data)
|
||||
ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext)
|
||||
|
||||
def break_up(data, chunk_length):
|
||||
return [data[i:i+chunk_length] for i in range(0, len(data),
|
||||
chunk_length)]
|
||||
|
||||
# Encryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
pt2 = b""
|
||||
for chunk in break_up(ciphertext, chunk_length):
|
||||
pt2 += cipher.decrypt(chunk)
|
||||
self.assertEqual(plaintext, pt2)
|
||||
cipher.verify(ref_mac)
|
||||
|
||||
# Decryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
ct2 = b""
|
||||
for chunk in break_up(plaintext, chunk_length):
|
||||
ct2 += cipher.encrypt(chunk)
|
||||
self.assertEqual(ciphertext, ct2)
|
||||
self.assertEqual(cipher.digest(), ref_mac)
|
||||
|
||||
def test_bytearray(self):
|
||||
|
||||
# Encrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data_128)
|
||||
data_ba = bytearray(self.data_128)
|
||||
|
||||
cipher1 = AES.new(self.key_128,
|
||||
AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data_128)
|
||||
ct = cipher1.encrypt(self.data_128)
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = AES.new(key_ba,
|
||||
AES.MODE_EAX,
|
||||
nonce=nonce_ba)
|
||||
key_ba[:3] = b'\xFF\xFF\xFF'
|
||||
nonce_ba[:3] = b'\xFF\xFF\xFF'
|
||||
cipher2.update(header_ba)
|
||||
header_ba[:3] = b'\xFF\xFF\xFF'
|
||||
ct_test = cipher2.encrypt(data_ba)
|
||||
data_ba[:3] = b'\x99\x99\x99'
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data_128)
|
||||
ct_ba = bytearray(ct)
|
||||
tag_ba = bytearray(tag)
|
||||
del data_ba
|
||||
|
||||
cipher3 = AES.new(key_ba,
|
||||
AES.MODE_EAX,
|
||||
nonce=nonce_ba)
|
||||
key_ba[:3] = b'\xFF\xFF\xFF'
|
||||
nonce_ba[:3] = b'\xFF\xFF\xFF'
|
||||
cipher3.update(header_ba)
|
||||
header_ba[:3] = b'\xFF\xFF\xFF'
|
||||
pt_test = cipher3.decrypt(ct_ba)
|
||||
ct_ba[:3] = b'\xFF\xFF\xFF'
|
||||
cipher3.verify(tag_ba)
|
||||
|
||||
self.assertEqual(pt_test, self.data_128)
|
||||
|
||||
def test_memoryview(self):
|
||||
|
||||
# Encrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data_128))
|
||||
data_mv = memoryview(bytearray(self.data_128))
|
||||
|
||||
cipher1 = AES.new(self.key_128,
|
||||
AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data_128)
|
||||
ct = cipher1.encrypt(self.data_128)
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = AES.new(key_mv,
|
||||
AES.MODE_EAX,
|
||||
nonce=nonce_mv)
|
||||
key_mv[:3] = b'\xFF\xFF\xFF'
|
||||
nonce_mv[:3] = b'\xFF\xFF\xFF'
|
||||
cipher2.update(header_mv)
|
||||
header_mv[:3] = b'\xFF\xFF\xFF'
|
||||
ct_test = cipher2.encrypt(data_mv)
|
||||
data_mv[:3] = b'\x99\x99\x99'
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data_128))
|
||||
ct_mv = memoryview(bytearray(ct))
|
||||
tag_mv = memoryview(bytearray(tag))
|
||||
del data_mv
|
||||
|
||||
cipher3 = AES.new(key_mv,
|
||||
AES.MODE_EAX,
|
||||
nonce=nonce_mv)
|
||||
key_mv[:3] = b'\xFF\xFF\xFF'
|
||||
nonce_mv[:3] = b'\xFF\xFF\xFF'
|
||||
cipher3.update(header_mv)
|
||||
header_mv[:3] = b'\xFF\xFF\xFF'
|
||||
pt_test = cipher3.decrypt(ct_mv)
|
||||
ct_mv[:3] = b'\x99\x99\x99'
|
||||
cipher3.verify(tag_mv)
|
||||
|
||||
self.assertEqual(pt_test, self.data_128)
|
||||
|
||||
def test_output_param(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(pt)
|
||||
tag = cipher.digest()
|
||||
|
||||
output = bytearray(128)
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
res, tag_out = cipher.encrypt_and_digest(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
self.assertEqual(tag, tag_out)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
res = cipher.decrypt_and_verify(ct, tag, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
def test_output_param_memoryview(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = memoryview(bytearray(128))
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
def test_output_param_neg(self):
|
||||
LEN_PT = 16
|
||||
|
||||
pt = b'5' * LEN_PT
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT)
|
||||
|
||||
shorter_output = bytearray(LEN_PT - 1)
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
class EaxFSMTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
nonce_96 = get_tag_random("nonce_128", 12)
|
||||
data_128 = get_tag_random("data_128", 16)
|
||||
|
||||
def test_valid_init_encrypt_decrypt_digest_verify(self):
|
||||
# No authenticated data, fixed plaintext
|
||||
# Verify path INIT->ENCRYPT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data_128)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->DECRYPT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_init_update_digest_verify(self):
|
||||
# No plaintext, fixed authenticated data
|
||||
# Verify path INIT->UPDATE->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_full_path(self):
|
||||
# Fixed authenticated data, fixed plaintext
|
||||
# Verify path INIT->UPDATE->ENCRYPT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
ct = cipher.encrypt(self.data_128)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->DECRYPT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_init_digest(self):
|
||||
# Verify path INIT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.digest()
|
||||
|
||||
def test_valid_init_verify(self):
|
||||
# Verify path INIT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
mac = cipher.digest()
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_multiple_encrypt_or_decrypt(self):
|
||||
for method_name in "encrypt", "decrypt":
|
||||
for auth_data in (None, b"333", self.data_128,
|
||||
self.data_128 + b"3"):
|
||||
if auth_data is None:
|
||||
assoc_len = None
|
||||
else:
|
||||
assoc_len = len(auth_data)
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
if auth_data is not None:
|
||||
cipher.update(auth_data)
|
||||
method = getattr(cipher, method_name)
|
||||
method(self.data_128)
|
||||
method(self.data_128)
|
||||
method(self.data_128)
|
||||
method(self.data_128)
|
||||
|
||||
def test_valid_multiple_digest_or_verify(self):
|
||||
# Multiple calls to digest
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
first_mac = cipher.digest()
|
||||
for x in range(4):
|
||||
self.assertEqual(first_mac, cipher.digest())
|
||||
|
||||
# Multiple calls to verify
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
for x in range(5):
|
||||
cipher.verify(first_mac)
|
||||
|
||||
def test_valid_encrypt_and_digest_decrypt_and_verify(self):
|
||||
# encrypt_and_digest
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data_128)
|
||||
|
||||
# decrypt_and_verify
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.update(self.data_128)
|
||||
pt = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(self.data_128, pt)
|
||||
|
||||
def test_invalid_mixing_encrypt_decrypt(self):
|
||||
# Once per method, with or without assoc. data
|
||||
for method1_name, method2_name in (("encrypt", "decrypt"),
|
||||
("decrypt", "encrypt")):
|
||||
for assoc_data_present in (True, False):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX,
|
||||
nonce=self.nonce_96)
|
||||
if assoc_data_present:
|
||||
cipher.update(self.data_128)
|
||||
getattr(cipher, method1_name)(self.data_128)
|
||||
self.assertRaises(TypeError, getattr(cipher, method2_name),
|
||||
self.data_128)
|
||||
|
||||
def test_invalid_encrypt_or_update_after_digest(self):
|
||||
for method_name in "encrypt", "update":
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.encrypt(self.data_128)
|
||||
cipher.digest()
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data_128)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.encrypt_and_digest(self.data_128)
|
||||
|
||||
def test_invalid_decrypt_or_update_after_verify(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data_128)
|
||||
mac = cipher.digest()
|
||||
|
||||
for method_name in "decrypt", "update":
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data_128)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_EAX, nonce=self.nonce_96)
|
||||
cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data_128)
|
||||
|
||||
|
||||
class TestVectorsPaper(unittest.TestCase):
|
||||
"""Class exercising the EAX test vectors found in
|
||||
http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf"""
|
||||
|
||||
test_vectors_hex = [
|
||||
( '6bfb914fd07eae6b',
|
||||
'',
|
||||
'',
|
||||
'e037830e8389f27b025a2d6527e79d01',
|
||||
'233952dee4d5ed5f9b9c6d6ff80ff478',
|
||||
'62EC67F9C3A4A407FCB2A8C49031A8B3'
|
||||
),
|
||||
(
|
||||
'fa3bfd4806eb53fa',
|
||||
'f7fb',
|
||||
'19dd',
|
||||
'5c4c9331049d0bdab0277408f67967e5',
|
||||
'91945d3f4dcbee0bf45ef52255f095a4',
|
||||
'BECAF043B0A23D843194BA972C66DEBD'
|
||||
),
|
||||
( '234a3463c1264ac6',
|
||||
'1a47cb4933',
|
||||
'd851d5bae0',
|
||||
'3a59f238a23e39199dc9266626c40f80',
|
||||
'01f74ad64077f2e704c0f60ada3dd523',
|
||||
'70C3DB4F0D26368400A10ED05D2BFF5E'
|
||||
),
|
||||
(
|
||||
'33cce2eabff5a79d',
|
||||
'481c9e39b1',
|
||||
'632a9d131a',
|
||||
'd4c168a4225d8e1ff755939974a7bede',
|
||||
'd07cf6cbb7f313bdde66b727afd3c5e8',
|
||||
'8408DFFF3C1A2B1292DC199E46B7D617'
|
||||
),
|
||||
(
|
||||
'aeb96eaebe2970e9',
|
||||
'40d0c07da5e4',
|
||||
'071dfe16c675',
|
||||
'cb0677e536f73afe6a14b74ee49844dd',
|
||||
'35b6d0580005bbc12b0587124557d2c2',
|
||||
'FDB6B06676EEDC5C61D74276E1F8E816'
|
||||
),
|
||||
(
|
||||
'd4482d1ca78dce0f',
|
||||
'4de3b35c3fc039245bd1fb7d',
|
||||
'835bb4f15d743e350e728414',
|
||||
'abb8644fd6ccb86947c5e10590210a4f',
|
||||
'bd8e6e11475e60b268784c38c62feb22',
|
||||
'6EAC5C93072D8E8513F750935E46DA1B'
|
||||
),
|
||||
(
|
||||
'65d2017990d62528',
|
||||
'8b0a79306c9ce7ed99dae4f87f8dd61636',
|
||||
'02083e3979da014812f59f11d52630da30',
|
||||
'137327d10649b0aa6e1c181db617d7f2',
|
||||
'7c77d6e813bed5ac98baa417477a2e7d',
|
||||
'1A8C98DCD73D38393B2BF1569DEEFC19'
|
||||
),
|
||||
(
|
||||
'54b9f04e6a09189a',
|
||||
'1bda122bce8a8dbaf1877d962b8592dd2d56',
|
||||
'2ec47b2c4954a489afc7ba4897edcdae8cc3',
|
||||
'3b60450599bd02c96382902aef7f832a',
|
||||
'5fff20cafab119ca2fc73549e20f5b0d',
|
||||
'DDE59B97D722156D4D9AFF2BC7559826'
|
||||
),
|
||||
(
|
||||
'899a175897561d7e',
|
||||
'6cf36720872b8513f6eab1a8a44438d5ef11',
|
||||
'0de18fd0fdd91e7af19f1d8ee8733938b1e8',
|
||||
'e7f6d2231618102fdb7fe55ff1991700',
|
||||
'a4a4782bcffd3ec5e7ef6d8c34a56123',
|
||||
'B781FCF2F75FA5A8DE97A9CA48E522EC'
|
||||
),
|
||||
(
|
||||
'126735fcc320d25a',
|
||||
'ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7',
|
||||
'cb8920f87a6c75cff39627b56e3ed197c552d295a7',
|
||||
'cfc46afc253b4652b1af3795b124ab6e',
|
||||
'8395fcf1e95bebd697bd010bc766aac3',
|
||||
'22E7ADD93CFC6393C57EC0B3C17D6B44'
|
||||
),
|
||||
]
|
||||
|
||||
test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex]
|
||||
|
||||
def runTest(self):
|
||||
for assoc_data, pt, ct, mac, key, nonce in self.test_vectors:
|
||||
# Encrypt
|
||||
cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac))
|
||||
cipher.update(assoc_data)
|
||||
ct2, mac2 = cipher.encrypt_and_digest(pt)
|
||||
self.assertEqual(ct, ct2)
|
||||
self.assertEqual(mac, mac2)
|
||||
|
||||
# Decrypt
|
||||
cipher = AES.new(key, AES.MODE_EAX, nonce, mac_len=len(mac))
|
||||
cipher.update(assoc_data)
|
||||
pt2 = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
|
||||
class TestVectorsWycheproof(unittest.TestCase):
|
||||
|
||||
def __init__(self, wycheproof_warnings):
|
||||
unittest.TestCase.__init__(self)
|
||||
self._wycheproof_warnings = wycheproof_warnings
|
||||
self._id = "None"
|
||||
|
||||
def setUp(self):
|
||||
|
||||
def filter_tag(group):
|
||||
return group['tagSize'] // 8
|
||||
|
||||
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
|
||||
|
||||
def warn(self, tv):
|
||||
if tv.warning and self._wycheproof_warnings:
|
||||
import warnings
|
||||
warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment))
|
||||
|
||||
def test_encrypt(self, tv):
|
||||
self._id = "Wycheproof Encrypt EAX Test #" + str(tv.id)
|
||||
|
||||
try:
|
||||
cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size)
|
||||
except ValueError as e:
|
||||
assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e)
|
||||
return
|
||||
|
||||
cipher.update(tv.aad)
|
||||
ct, tag = cipher.encrypt_and_digest(tv.msg)
|
||||
if tv.valid:
|
||||
self.assertEqual(ct, tv.ct)
|
||||
self.assertEqual(tag, tv.tag)
|
||||
self.warn(tv)
|
||||
|
||||
def test_decrypt(self, tv):
|
||||
self._id = "Wycheproof Decrypt EAX Test #" + str(tv.id)
|
||||
|
||||
try:
|
||||
cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size)
|
||||
except ValueError as e:
|
||||
assert len(tv.iv) == 0 and "Nonce cannot be empty" in str(e)
|
||||
return
|
||||
|
||||
cipher.update(tv.aad)
|
||||
try:
|
||||
pt = cipher.decrypt_and_verify(tv.ct, tv.tag)
|
||||
except ValueError:
|
||||
assert not tv.valid
|
||||
else:
|
||||
assert tv.valid
|
||||
self.assertEqual(pt, tv.msg)
|
||||
self.warn(tv)
|
||||
|
||||
def test_corrupt_decrypt(self, tv):
|
||||
self._id = "Wycheproof Corrupt Decrypt EAX Test #" + str(tv.id)
|
||||
if len(tv.iv) == 0 or len(tv.ct) < 1:
|
||||
return
|
||||
cipher = AES.new(tv.key, AES.MODE_EAX, tv.iv, mac_len=tv.tag_size)
|
||||
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)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
for tv in self.tv:
|
||||
self.test_encrypt(tv)
|
||||
self.test_decrypt(tv)
|
||||
self.test_corrupt_decrypt(tv)
|
||||
|
||||
|
||||
class TestOtherCiphers(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def create_test(cls, name, factory, key_size):
|
||||
|
||||
def test_template(self, factory=factory, key_size=key_size):
|
||||
cipher = factory.new(get_tag_random("cipher", key_size),
|
||||
factory.MODE_EAX,
|
||||
nonce=b"nonce")
|
||||
ct, mac = cipher.encrypt_and_digest(b"plaintext")
|
||||
|
||||
cipher = factory.new(get_tag_random("cipher", key_size),
|
||||
factory.MODE_EAX,
|
||||
nonce=b"nonce")
|
||||
pt2 = cipher.decrypt_and_verify(ct, mac)
|
||||
|
||||
self.assertEqual(b"plaintext", pt2)
|
||||
|
||||
setattr(cls, "test_" + name, test_template)
|
||||
|
||||
|
||||
from Crypto.Cipher import DES, DES3, ARC2, CAST, Blowfish
|
||||
|
||||
TestOtherCiphers.create_test("DES_" + str(DES.key_size), DES, DES.key_size)
|
||||
for ks in DES3.key_size:
|
||||
TestOtherCiphers.create_test("DES3_" + str(ks), DES3, ks)
|
||||
for ks in ARC2.key_size:
|
||||
TestOtherCiphers.create_test("ARC2_" + str(ks), ARC2, ks)
|
||||
for ks in CAST.key_size:
|
||||
TestOtherCiphers.create_test("CAST_" + str(ks), CAST, ks)
|
||||
for ks in Blowfish.key_size:
|
||||
TestOtherCiphers.create_test("Blowfish_" + str(ks), Blowfish, ks)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
wycheproof_warnings = config.get('wycheproof_warnings')
|
||||
|
||||
tests = []
|
||||
tests += list_test_cases(EaxTests)
|
||||
tests += list_test_cases(EaxFSMTests)
|
||||
tests += [ TestVectorsPaper() ]
|
||||
tests += [ TestVectorsWycheproof(wycheproof_warnings) ]
|
||||
tests += list_test_cases(TestOtherCiphers)
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
951
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_GCM.py
vendored
Normal file
951
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_GCM.py
vendored
Normal file
@ -0,0 +1,951 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import unittest
|
||||
from binascii import unhexlify
|
||||
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
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.strxor import strxor
|
||||
|
||||
|
||||
def get_tag_random(tag, length):
|
||||
return SHAKE128.new(data=tobytes(tag)).read(length)
|
||||
|
||||
|
||||
class GcmTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
nonce_96 = get_tag_random("nonce_128", 12)
|
||||
data = get_tag_random("data", 128)
|
||||
|
||||
def test_loopback_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
pt = get_tag_random("plaintext", 16 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_nonce(self):
|
||||
# Nonce is optional (a random one will be created)
|
||||
AES.new(self.key_128, AES.MODE_GCM)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, self.nonce_96)
|
||||
ct = cipher.encrypt(self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertEqual(ct, cipher.encrypt(self.data))
|
||||
|
||||
def test_nonce_must_be_bytes(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_GCM,
|
||||
nonce=u'test12345678')
|
||||
|
||||
def test_nonce_length(self):
|
||||
# nonce can be of any length (but not empty)
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_GCM,
|
||||
nonce=b"")
|
||||
|
||||
for x in range(1, 128):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=bchr(1) * x)
|
||||
cipher.encrypt(bchr(1))
|
||||
|
||||
def test_block_size_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.block_size, AES.block_size)
|
||||
|
||||
def test_nonce_attribute(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.nonce, self.nonce_96)
|
||||
|
||||
# By default, a 15 bytes long nonce is randomly generated
|
||||
nonce1 = AES.new(self.key_128, AES.MODE_GCM).nonce
|
||||
nonce2 = AES.new(self.key_128, AES.MODE_GCM).nonce
|
||||
self.assertEqual(len(nonce1), 16)
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
|
||||
def test_unknown_parameters(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_GCM,
|
||||
self.nonce_96, 7)
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96, unknown=7)
|
||||
|
||||
# But some are only known by the base cipher
|
||||
# (e.g. use_aesni consumed by the AES module)
|
||||
AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96,
|
||||
use_aesni=False)
|
||||
|
||||
def test_null_encryption_decryption(self):
|
||||
for func in "encrypt", "decrypt":
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
result = getattr(cipher, func)(b"")
|
||||
self.assertEqual(result, b"")
|
||||
|
||||
def test_either_encrypt_or_decrypt(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.encrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.decrypt, b"")
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.decrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.encrypt, b"")
|
||||
|
||||
def test_data_must_be_bytes(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*')
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*')
|
||||
|
||||
def test_mac_len(self):
|
||||
# Invalid MAC length
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96, mac_len=3)
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96, mac_len=16+1)
|
||||
|
||||
# Valid MAC length
|
||||
for mac_len in range(5, 16 + 1):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96,
|
||||
mac_len=mac_len)
|
||||
_, mac = cipher.encrypt_and_digest(self.data)
|
||||
self.assertEqual(len(mac), mac_len)
|
||||
|
||||
# Default MAC length
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
_, mac = cipher.encrypt_and_digest(self.data)
|
||||
self.assertEqual(len(mac), 16)
|
||||
|
||||
def test_invalid_mac(self):
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
invalid_mac = strxor_c(mac, 0x01)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt_and_verify, ct,
|
||||
invalid_mac)
|
||||
|
||||
def test_hex_mac(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
mac_hex = cipher.hexdigest()
|
||||
self.assertEqual(cipher.digest(), unhexlify(mac_hex))
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.hexverify(mac_hex)
|
||||
|
||||
def test_message_chunks(self):
|
||||
# Validate that both associated data and plaintext/ciphertext
|
||||
# can be broken up in chunks of arbitrary length
|
||||
|
||||
auth_data = get_tag_random("authenticated data", 127)
|
||||
plaintext = get_tag_random("plaintext", 127)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.update(auth_data)
|
||||
ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext)
|
||||
|
||||
def break_up(data, chunk_length):
|
||||
return [data[i:i+chunk_length] for i in range(0, len(data),
|
||||
chunk_length)]
|
||||
|
||||
# Encryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
pt2 = b""
|
||||
for chunk in break_up(ciphertext, chunk_length):
|
||||
pt2 += cipher.decrypt(chunk)
|
||||
self.assertEqual(plaintext, pt2)
|
||||
cipher.verify(ref_mac)
|
||||
|
||||
# Decryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
ct2 = b""
|
||||
for chunk in break_up(plaintext, chunk_length):
|
||||
ct2 += cipher.encrypt(chunk)
|
||||
self.assertEqual(ciphertext, ct2)
|
||||
self.assertEqual(cipher.digest(), ref_mac)
|
||||
|
||||
def test_bytearray(self):
|
||||
|
||||
# Encrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data)
|
||||
data_ba = bytearray(self.data)
|
||||
|
||||
cipher1 = AES.new(self.key_128,
|
||||
AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data)
|
||||
ct = cipher1.encrypt(self.data)
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = AES.new(key_ba,
|
||||
AES.MODE_GCM,
|
||||
nonce=nonce_ba)
|
||||
key_ba[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_ba[:3] = b"\xFF\xFF\xFF"
|
||||
cipher2.update(header_ba)
|
||||
header_ba[:3] = b"\xFF\xFF\xFF"
|
||||
ct_test = cipher2.encrypt(data_ba)
|
||||
data_ba[:3] = b"\xFF\xFF\xFF"
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data)
|
||||
del data_ba
|
||||
|
||||
cipher4 = AES.new(key_ba,
|
||||
AES.MODE_GCM,
|
||||
nonce=nonce_ba)
|
||||
key_ba[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_ba[:3] = b"\xFF\xFF\xFF"
|
||||
cipher4.update(header_ba)
|
||||
header_ba[:3] = b"\xFF\xFF\xFF"
|
||||
pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test))
|
||||
|
||||
self.assertEqual(self.data, pt_test)
|
||||
|
||||
def test_memoryview(self):
|
||||
|
||||
# Encrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data))
|
||||
data_mv = memoryview(bytearray(self.data))
|
||||
|
||||
cipher1 = AES.new(self.key_128,
|
||||
AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data)
|
||||
ct = cipher1.encrypt(self.data)
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = AES.new(key_mv,
|
||||
AES.MODE_GCM,
|
||||
nonce=nonce_mv)
|
||||
key_mv[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_mv[:3] = b"\xFF\xFF\xFF"
|
||||
cipher2.update(header_mv)
|
||||
header_mv[:3] = b"\xFF\xFF\xFF"
|
||||
ct_test = cipher2.encrypt(data_mv)
|
||||
data_mv[:3] = b"\xFF\xFF\xFF"
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data))
|
||||
del data_mv
|
||||
|
||||
cipher4 = AES.new(key_mv,
|
||||
AES.MODE_GCM,
|
||||
nonce=nonce_mv)
|
||||
key_mv[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_mv[:3] = b"\xFF\xFF\xFF"
|
||||
cipher4.update(header_mv)
|
||||
header_mv[:3] = b"\xFF\xFF\xFF"
|
||||
pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test))
|
||||
|
||||
self.assertEqual(self.data, pt_test)
|
||||
|
||||
def test_output_param(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(pt)
|
||||
tag = cipher.digest()
|
||||
|
||||
output = bytearray(128)
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
res, tag_out = cipher.encrypt_and_digest(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
self.assertEqual(tag, tag_out)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
res = cipher.decrypt_and_verify(ct, tag, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
def test_output_param_memoryview(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = memoryview(bytearray(128))
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
def test_output_param_neg(self):
|
||||
LEN_PT = 128
|
||||
|
||||
pt = b'5' * LEN_PT
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0' * LEN_PT)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0' * LEN_PT)
|
||||
|
||||
shorter_output = bytearray(LEN_PT - 1)
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
class GcmFSMTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
nonce_96 = get_tag_random("nonce_128", 12)
|
||||
data = get_tag_random("data", 128)
|
||||
|
||||
def test_valid_init_encrypt_decrypt_digest_verify(self):
|
||||
# No authenticated data, fixed plaintext
|
||||
# Verify path INIT->ENCRYPT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->DECRYPT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_init_update_digest_verify(self):
|
||||
# No plaintext, fixed authenticated data
|
||||
# Verify path INIT->UPDATE->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_full_path(self):
|
||||
# Fixed authenticated data, fixed plaintext
|
||||
# Verify path INIT->UPDATE->ENCRYPT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
ct = cipher.encrypt(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->DECRYPT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_init_digest(self):
|
||||
# Verify path INIT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.digest()
|
||||
|
||||
def test_valid_init_verify(self):
|
||||
# Verify path INIT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
mac = cipher.digest()
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_multiple_encrypt_or_decrypt(self):
|
||||
for method_name in "encrypt", "decrypt":
|
||||
for auth_data in (None, b"333", self.data,
|
||||
self.data + b"3"):
|
||||
if auth_data is None:
|
||||
assoc_len = None
|
||||
else:
|
||||
assoc_len = len(auth_data)
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
if auth_data is not None:
|
||||
cipher.update(auth_data)
|
||||
method = getattr(cipher, method_name)
|
||||
method(self.data)
|
||||
method(self.data)
|
||||
method(self.data)
|
||||
method(self.data)
|
||||
|
||||
def test_valid_multiple_digest_or_verify(self):
|
||||
# Multiple calls to digest
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
first_mac = cipher.digest()
|
||||
for x in range(4):
|
||||
self.assertEqual(first_mac, cipher.digest())
|
||||
|
||||
# Multiple calls to verify
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
for x in range(5):
|
||||
cipher.verify(first_mac)
|
||||
|
||||
def test_valid_encrypt_and_digest_decrypt_and_verify(self):
|
||||
# encrypt_and_digest
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
# decrypt_and_verify
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
pt = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(self.data, pt)
|
||||
|
||||
def test_invalid_mixing_encrypt_decrypt(self):
|
||||
# Once per method, with or without assoc. data
|
||||
for method1_name, method2_name in (("encrypt", "decrypt"),
|
||||
("decrypt", "encrypt")):
|
||||
for assoc_data_present in (True, False):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM,
|
||||
nonce=self.nonce_96)
|
||||
if assoc_data_present:
|
||||
cipher.update(self.data)
|
||||
getattr(cipher, method1_name)(self.data)
|
||||
self.assertRaises(TypeError, getattr(cipher, method2_name),
|
||||
self.data)
|
||||
|
||||
def test_invalid_encrypt_or_update_after_digest(self):
|
||||
for method_name in "encrypt", "update":
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.encrypt(self.data)
|
||||
cipher.digest()
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.encrypt_and_digest(self.data)
|
||||
|
||||
def test_invalid_decrypt_or_update_after_verify(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
for method_name in "decrypt", "update":
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_GCM, nonce=self.nonce_96)
|
||||
cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data)
|
||||
|
||||
|
||||
class TestVectors(unittest.TestCase):
|
||||
"""Class exercising the GCM test vectors found in
|
||||
http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf"""
|
||||
|
||||
# List of test vectors, each made up of:
|
||||
# - authenticated data
|
||||
# - plaintext
|
||||
# - ciphertext
|
||||
# - MAC
|
||||
# - AES key
|
||||
# - nonce
|
||||
test_vectors_hex = [
|
||||
(
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'58e2fccefa7e3061367f1d57a4e7455a',
|
||||
'00000000000000000000000000000000',
|
||||
'000000000000000000000000'
|
||||
),
|
||||
(
|
||||
'',
|
||||
'00000000000000000000000000000000',
|
||||
'0388dace60b6a392f328c2b971b2fe78',
|
||||
'ab6e47d42cec13bdf53a67b21257bddf',
|
||||
'00000000000000000000000000000000',
|
||||
'000000000000000000000000'
|
||||
),
|
||||
(
|
||||
'',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255',
|
||||
'42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' +
|
||||
'21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985',
|
||||
'4d5c2af327cd64a62cf35abd2ba6fab4',
|
||||
'feffe9928665731c6d6a8f9467308308',
|
||||
'cafebabefacedbaddecaf888'
|
||||
),
|
||||
(
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' +
|
||||
'21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091',
|
||||
'5bc94fbc3221a5db94fae95ae7121a47',
|
||||
'feffe9928665731c6d6a8f9467308308',
|
||||
'cafebabefacedbaddecaf888'
|
||||
),
|
||||
(
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423' +
|
||||
'73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598',
|
||||
'3612d2e79e3b0785561be14aaca2fccb',
|
||||
'feffe9928665731c6d6a8f9467308308',
|
||||
'cafebabefacedbad'
|
||||
),
|
||||
(
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7' +
|
||||
'01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5',
|
||||
'619cc5aefffe0bfa462af43c1699d050',
|
||||
'feffe9928665731c6d6a8f9467308308',
|
||||
'9313225df88406e555909c5aff5269aa' +
|
||||
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' +
|
||||
'16aedbf5a0de6a57a637b39b'
|
||||
),
|
||||
(
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'cd33b28ac773f74ba00ed1f312572435',
|
||||
'000000000000000000000000000000000000000000000000',
|
||||
'000000000000000000000000'
|
||||
),
|
||||
(
|
||||
'',
|
||||
'00000000000000000000000000000000',
|
||||
'98e7247c07f0fe411c267e4384b0f600',
|
||||
'2ff58d80033927ab8ef4d4587514f0fb',
|
||||
'000000000000000000000000000000000000000000000000',
|
||||
'000000000000000000000000'
|
||||
),
|
||||
(
|
||||
'',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255',
|
||||
'3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' +
|
||||
'7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256',
|
||||
'9924a7c8587336bfb118024db8674a14',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c',
|
||||
'cafebabefacedbaddecaf888'
|
||||
),
|
||||
(
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' +
|
||||
'7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710',
|
||||
'2519498e80f1478f37ba55bd6d27618c',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c',
|
||||
'cafebabefacedbaddecaf888'
|
||||
),
|
||||
(
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057' +
|
||||
'fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7',
|
||||
'65dcc57fcf623a24094fcca40d3533f8',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c',
|
||||
'cafebabefacedbad'
|
||||
),
|
||||
(
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'd27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45' +
|
||||
'81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b',
|
||||
'dcf566ff291c25bbb8568fc3d376a6d9',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c',
|
||||
'9313225df88406e555909c5aff5269aa' +
|
||||
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' +
|
||||
'16aedbf5a0de6a57a637b39b'
|
||||
),
|
||||
(
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'530f8afbc74536b9a963b4f1c4cb738b',
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
'000000000000000000000000'
|
||||
),
|
||||
(
|
||||
'',
|
||||
'00000000000000000000000000000000',
|
||||
'cea7403d4d606b6e074ec5d3baf39d18',
|
||||
'd0d1c8a799996bf0265b98b5d48ab919',
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
'000000000000000000000000'
|
||||
),
|
||||
( '',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255',
|
||||
'522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' +
|
||||
'8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad',
|
||||
'b094dac5d93471bdec1a502270e3cc6c',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308',
|
||||
'cafebabefacedbaddecaf888'
|
||||
),
|
||||
(
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' +
|
||||
'8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662',
|
||||
'76fc6ece0f4e1768cddf8853bb2d551b',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308',
|
||||
'cafebabefacedbaddecaf888'
|
||||
),
|
||||
(
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0' +
|
||||
'feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f',
|
||||
'3a337dbf46a792c45e454913fe2ea8f2',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308',
|
||||
'cafebabefacedbad'
|
||||
),
|
||||
(
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2',
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4' +
|
||||
'0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f',
|
||||
'a44a8266ee1c8eb0c8b5d4cf5ae9f19a',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308',
|
||||
'9313225df88406e555909c5aff5269aa' +
|
||||
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254' +
|
||||
'16aedbf5a0de6a57a637b39b'
|
||||
)
|
||||
]
|
||||
|
||||
test_vectors = [[unhexlify(x) for x in tv] for tv in test_vectors_hex]
|
||||
|
||||
def runTest(self):
|
||||
for assoc_data, pt, ct, mac, key, nonce in self.test_vectors:
|
||||
|
||||
# Encrypt
|
||||
cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac))
|
||||
cipher.update(assoc_data)
|
||||
ct2, mac2 = cipher.encrypt_and_digest(pt)
|
||||
self.assertEqual(ct, ct2)
|
||||
self.assertEqual(mac, mac2)
|
||||
|
||||
# Decrypt
|
||||
cipher = AES.new(key, AES.MODE_GCM, nonce, mac_len=len(mac))
|
||||
cipher.update(assoc_data)
|
||||
pt2 = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
|
||||
class TestVectorsGueronKrasnov(unittest.TestCase):
|
||||
"""Class exercising the GCM test vectors found in
|
||||
'The fragility of AES-GCM authentication algorithm', Gueron, Krasnov
|
||||
https://eprint.iacr.org/2013/157.pdf"""
|
||||
|
||||
def test_1(self):
|
||||
key = unhexlify("3da6c536d6295579c0959a7043efb503")
|
||||
iv = unhexlify("2b926197d34e091ef722db94")
|
||||
aad = unhexlify("00000000000000000000000000000000" +
|
||||
"000102030405060708090a0b0c0d0e0f" +
|
||||
"101112131415161718191a1b1c1d1e1f" +
|
||||
"202122232425262728292a2b2c2d2e2f" +
|
||||
"303132333435363738393a3b3c3d3e3f")
|
||||
digest = unhexlify("69dd586555ce3fcc89663801a71d957b")
|
||||
|
||||
cipher = AES.new(key, AES.MODE_GCM, iv).update(aad)
|
||||
self.assertEqual(digest, cipher.digest())
|
||||
|
||||
def test_2(self):
|
||||
key = unhexlify("843ffcf5d2b72694d19ed01d01249412")
|
||||
iv = unhexlify("dbcca32ebf9b804617c3aa9e")
|
||||
aad = unhexlify("00000000000000000000000000000000" +
|
||||
"101112131415161718191a1b1c1d1e1f")
|
||||
pt = unhexlify("000102030405060708090a0b0c0d0e0f" +
|
||||
"101112131415161718191a1b1c1d1e1f" +
|
||||
"202122232425262728292a2b2c2d2e2f" +
|
||||
"303132333435363738393a3b3c3d3e3f" +
|
||||
"404142434445464748494a4b4c4d4e4f")
|
||||
ct = unhexlify("6268c6fa2a80b2d137467f092f657ac0" +
|
||||
"4d89be2beaa623d61b5a868c8f03ff95" +
|
||||
"d3dcee23ad2f1ab3a6c80eaf4b140eb0" +
|
||||
"5de3457f0fbc111a6b43d0763aa422a3" +
|
||||
"013cf1dc37fe417d1fbfc449b75d4cc5")
|
||||
digest = unhexlify("3b629ccfbc1119b7319e1dce2cd6fd6d")
|
||||
|
||||
cipher = AES.new(key, AES.MODE_GCM, iv).update(aad)
|
||||
ct2, digest2 = cipher.encrypt_and_digest(pt)
|
||||
|
||||
self.assertEqual(ct, ct2)
|
||||
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):
|
||||
self.use_clmul = False
|
||||
unittest.TestCase.__init__(self, a)
|
||||
|
||||
|
||||
test_vectors_nist = load_test_vectors(
|
||||
("Cipher", "AES"),
|
||||
"gcmDecrypt128.rsp",
|
||||
"GCM decrypt",
|
||||
{"count": lambda x: int(x)}) or []
|
||||
|
||||
test_vectors_nist += load_test_vectors(
|
||||
("Cipher", "AES"),
|
||||
"gcmEncryptExtIV128.rsp",
|
||||
"GCM encrypt",
|
||||
{"count": lambda x: int(x)}) or []
|
||||
|
||||
for idx, tv in enumerate(test_vectors_nist):
|
||||
|
||||
# The test vector file contains some directive lines
|
||||
if isinstance(tv, str):
|
||||
continue
|
||||
|
||||
def single_test(self, tv=tv):
|
||||
|
||||
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,
|
||||
tv.ct, tv.tag)
|
||||
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)
|
||||
|
||||
|
||||
class TestVectorsWycheproof(unittest.TestCase):
|
||||
|
||||
def __init__(self, wycheproof_warnings, **extra_params):
|
||||
unittest.TestCase.__init__(self)
|
||||
self._wycheproof_warnings = wycheproof_warnings
|
||||
self._extra_params = extra_params
|
||||
self._id = "None"
|
||||
|
||||
def setUp(self):
|
||||
|
||||
def filter_tag(group):
|
||||
return group['tagSize'] // 8
|
||||
|
||||
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
|
||||
|
||||
def warn(self, tv):
|
||||
if tv.warning and self._wycheproof_warnings:
|
||||
import warnings
|
||||
warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment))
|
||||
|
||||
def test_encrypt(self, tv):
|
||||
self._id = "Wycheproof Encrypt GCM Test #" + str(tv.id)
|
||||
|
||||
try:
|
||||
cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size,
|
||||
**self._extra_params)
|
||||
except ValueError as e:
|
||||
if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e):
|
||||
return
|
||||
raise e
|
||||
|
||||
cipher.update(tv.aad)
|
||||
ct, tag = cipher.encrypt_and_digest(tv.msg)
|
||||
if tv.valid:
|
||||
self.assertEqual(ct, tv.ct)
|
||||
self.assertEqual(tag, tv.tag)
|
||||
self.warn(tv)
|
||||
|
||||
def test_decrypt(self, tv):
|
||||
self._id = "Wycheproof Decrypt GCM Test #" + str(tv.id)
|
||||
|
||||
try:
|
||||
cipher = AES.new(tv.key, AES.MODE_GCM, tv.iv, mac_len=tv.tag_size,
|
||||
**self._extra_params)
|
||||
except ValueError as e:
|
||||
if len(tv.iv) == 0 and "Nonce cannot be empty" in str(e):
|
||||
return
|
||||
raise e
|
||||
|
||||
cipher.update(tv.aad)
|
||||
try:
|
||||
pt = cipher.decrypt_and_verify(tv.ct, tv.tag)
|
||||
except ValueError:
|
||||
assert not tv.valid
|
||||
else:
|
||||
assert tv.valid
|
||||
self.assertEqual(pt, tv.msg)
|
||||
self.warn(tv)
|
||||
|
||||
def test_corrupt_decrypt(self, tv):
|
||||
self._id = "Wycheproof Corrupt Decrypt GCM Test #" + str(tv.id)
|
||||
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)
|
||||
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)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
for tv in self.tv:
|
||||
self.test_encrypt(tv)
|
||||
self.test_decrypt(tv)
|
||||
self.test_corrupt_decrypt(tv)
|
||||
|
||||
|
||||
class TestVariableLength(unittest.TestCase):
|
||||
|
||||
def __init__(self, **extra_params):
|
||||
unittest.TestCase.__init__(self)
|
||||
self._extra_params = extra_params
|
||||
|
||||
def runTest(self):
|
||||
key = b'0' * 16
|
||||
h = SHA256.new()
|
||||
|
||||
for length in range(160):
|
||||
nonce = '{0:04d}'.format(length).encode('utf-8')
|
||||
data = bchr(length) * length
|
||||
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce, **self._extra_params)
|
||||
ct, tag = cipher.encrypt_and_digest(data)
|
||||
h.update(ct)
|
||||
h.update(tag)
|
||||
|
||||
self.assertEqual(h.hexdigest(), "7b7eb1ffbe67a2e53a912067c0ec8e62ebc7ce4d83490ea7426941349811bdf4")
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
from Crypto.Util import _cpu_features
|
||||
|
||||
wycheproof_warnings = config.get('wycheproof_warnings')
|
||||
|
||||
tests = []
|
||||
tests += list_test_cases(GcmTests)
|
||||
tests += list_test_cases(GcmFSMTests)
|
||||
tests += [TestVectors()]
|
||||
tests += [TestVectorsWycheproof(wycheproof_warnings)]
|
||||
tests += list_test_cases(TestVectorsGueronKrasnov)
|
||||
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)]
|
||||
if config.get('slow_tests'):
|
||||
tests += list_test_cases(NISTTestVectorsGCM_no_clmul)
|
||||
else:
|
||||
print("Skipping test of PCLMULDQD in AES GCM")
|
||||
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def suite():
|
||||
unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
845
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_OCB.py
vendored
Normal file
845
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_OCB.py
vendored
Normal file
@ -0,0 +1,845 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
import unittest
|
||||
from binascii import unhexlify
|
||||
|
||||
from Crypto.Util.py3compat import b, tobytes, bchr
|
||||
from Crypto.Util.number import long_to_bytes
|
||||
from Crypto.SelfTest.loader import load_test_vectors
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Hash import SHAKE128
|
||||
|
||||
|
||||
def get_tag_random(tag, length):
|
||||
return SHAKE128.new(data=tobytes(tag)).read(length)
|
||||
|
||||
|
||||
class OcbTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
nonce_96 = get_tag_random("nonce_128", 12)
|
||||
data = get_tag_random("data", 128)
|
||||
|
||||
def test_loopback_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
pt = get_tag_random("plaintext", 16 * 100)
|
||||
ct, mac = cipher.encrypt_and_digest(pt)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
pt2 = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_nonce(self):
|
||||
# Nonce is optional
|
||||
AES.new(self.key_128, AES.MODE_OCB)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, self.nonce_96)
|
||||
ct = cipher.encrypt(self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
self.assertEqual(ct, cipher.encrypt(self.data))
|
||||
|
||||
def test_nonce_must_be_bytes(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_OCB,
|
||||
nonce=u'test12345678')
|
||||
|
||||
def test_nonce_length(self):
|
||||
# nonce cannot be empty
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB,
|
||||
nonce=b(""))
|
||||
|
||||
# nonce can be up to 15 bytes long
|
||||
for length in range(1, 16):
|
||||
AES.new(self.key_128, AES.MODE_OCB, nonce=self.data[:length])
|
||||
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB,
|
||||
nonce=self.data)
|
||||
|
||||
def test_block_size_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.block_size, AES.block_size)
|
||||
|
||||
# By default, a 15 bytes long nonce is randomly generated
|
||||
nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce
|
||||
nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce
|
||||
self.assertEqual(len(nonce1), 15)
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
|
||||
def test_nonce_attribute(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.nonce, self.nonce_96)
|
||||
|
||||
# By default, a 15 bytes long nonce is randomly generated
|
||||
nonce1 = AES.new(self.key_128, AES.MODE_OCB).nonce
|
||||
nonce2 = AES.new(self.key_128, AES.MODE_OCB).nonce
|
||||
self.assertEqual(len(nonce1), 15)
|
||||
self.assertNotEqual(nonce1, nonce2)
|
||||
|
||||
def test_unknown_parameters(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_OCB,
|
||||
self.nonce_96, 7)
|
||||
self.assertRaises(TypeError, AES.new, self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96, unknown=7)
|
||||
|
||||
# But some are only known by the base cipher
|
||||
# (e.g. use_aesni consumed by the AES module)
|
||||
AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96,
|
||||
use_aesni=False)
|
||||
|
||||
def test_null_encryption_decryption(self):
|
||||
for func in "encrypt", "decrypt":
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
result = getattr(cipher, func)(b(""))
|
||||
self.assertEqual(result, b(""))
|
||||
|
||||
def test_either_encrypt_or_decrypt(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.encrypt(b("xyz"))
|
||||
self.assertRaises(TypeError, cipher.decrypt, b("xyz"))
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.decrypt(b("xyz"))
|
||||
self.assertRaises(TypeError, cipher.encrypt, b("xyz"))
|
||||
|
||||
def test_data_must_be_bytes(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*')
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt, u'test1234567890-*')
|
||||
|
||||
def test_mac_len(self):
|
||||
# Invalid MAC length
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96, mac_len=7)
|
||||
self.assertRaises(ValueError, AES.new, self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96, mac_len=16+1)
|
||||
|
||||
# Valid MAC length
|
||||
for mac_len in range(8, 16 + 1):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96,
|
||||
mac_len=mac_len)
|
||||
_, mac = cipher.encrypt_and_digest(self.data)
|
||||
self.assertEqual(len(mac), mac_len)
|
||||
|
||||
# Default MAC length
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
_, mac = cipher.encrypt_and_digest(self.data)
|
||||
self.assertEqual(len(mac), 16)
|
||||
|
||||
def test_invalid_mac(self):
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
invalid_mac = strxor_c(mac, 0x01)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt_and_verify, ct,
|
||||
invalid_mac)
|
||||
|
||||
def test_hex_mac(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
mac_hex = cipher.hexdigest()
|
||||
self.assertEqual(cipher.digest(), unhexlify(mac_hex))
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.hexverify(mac_hex)
|
||||
|
||||
def test_message_chunks(self):
|
||||
# Validate that both associated data and plaintext/ciphertext
|
||||
# can be broken up in chunks of arbitrary length
|
||||
|
||||
auth_data = get_tag_random("authenticated data", 127)
|
||||
plaintext = get_tag_random("plaintext", 127)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.update(auth_data)
|
||||
ciphertext, ref_mac = cipher.encrypt_and_digest(plaintext)
|
||||
|
||||
def break_up(data, chunk_length):
|
||||
return [data[i:i+chunk_length] for i in range(0, len(data),
|
||||
chunk_length)]
|
||||
|
||||
# Encryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
pt2 = b("")
|
||||
for chunk in break_up(ciphertext, chunk_length):
|
||||
pt2 += cipher.decrypt(chunk)
|
||||
pt2 += cipher.decrypt()
|
||||
self.assertEqual(plaintext, pt2)
|
||||
cipher.verify(ref_mac)
|
||||
|
||||
# Decryption
|
||||
for chunk_length in 1, 2, 3, 7, 10, 13, 16, 40, 80, 128:
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
|
||||
for chunk in break_up(auth_data, chunk_length):
|
||||
cipher.update(chunk)
|
||||
ct2 = b("")
|
||||
for chunk in break_up(plaintext, chunk_length):
|
||||
ct2 += cipher.encrypt(chunk)
|
||||
ct2 += cipher.encrypt()
|
||||
self.assertEqual(ciphertext, ct2)
|
||||
self.assertEqual(cipher.digest(), ref_mac)
|
||||
|
||||
def test_bytearray(self):
|
||||
|
||||
# Encrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data)
|
||||
data_ba = bytearray(self.data)
|
||||
|
||||
cipher1 = AES.new(self.key_128,
|
||||
AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data)
|
||||
ct = cipher1.encrypt(self.data) + cipher1.encrypt()
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = AES.new(key_ba,
|
||||
AES.MODE_OCB,
|
||||
nonce=nonce_ba)
|
||||
key_ba[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_ba[:3] = b"\xFF\xFF\xFF"
|
||||
cipher2.update(header_ba)
|
||||
header_ba[:3] = b"\xFF\xFF\xFF"
|
||||
ct_test = cipher2.encrypt(data_ba) + cipher2.encrypt()
|
||||
data_ba[:3] = b"\xFF\xFF\xFF"
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_ba = bytearray(self.key_128)
|
||||
nonce_ba = bytearray(self.nonce_96)
|
||||
header_ba = bytearray(self.data)
|
||||
del data_ba
|
||||
|
||||
cipher4 = AES.new(key_ba,
|
||||
AES.MODE_OCB,
|
||||
nonce=nonce_ba)
|
||||
key_ba[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_ba[:3] = b"\xFF\xFF\xFF"
|
||||
cipher4.update(header_ba)
|
||||
header_ba[:3] = b"\xFF\xFF\xFF"
|
||||
pt_test = cipher4.decrypt_and_verify(bytearray(ct_test), bytearray(tag_test))
|
||||
|
||||
self.assertEqual(self.data, pt_test)
|
||||
|
||||
def test_memoryview(self):
|
||||
|
||||
# Encrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data))
|
||||
data_mv = memoryview(bytearray(self.data))
|
||||
|
||||
cipher1 = AES.new(self.key_128,
|
||||
AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data)
|
||||
ct = cipher1.encrypt(self.data) + cipher1.encrypt()
|
||||
tag = cipher1.digest()
|
||||
|
||||
cipher2 = AES.new(key_mv,
|
||||
AES.MODE_OCB,
|
||||
nonce=nonce_mv)
|
||||
key_mv[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_mv[:3] = b"\xFF\xFF\xFF"
|
||||
cipher2.update(header_mv)
|
||||
header_mv[:3] = b"\xFF\xFF\xFF"
|
||||
ct_test = cipher2.encrypt(data_mv) + cipher2.encrypt()
|
||||
data_mv[:3] = b"\xFF\xFF\xFF"
|
||||
tag_test = cipher2.digest()
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key_mv = memoryview(bytearray(self.key_128))
|
||||
nonce_mv = memoryview(bytearray(self.nonce_96))
|
||||
header_mv = memoryview(bytearray(self.data))
|
||||
del data_mv
|
||||
|
||||
cipher4 = AES.new(key_mv,
|
||||
AES.MODE_OCB,
|
||||
nonce=nonce_mv)
|
||||
key_mv[:3] = b"\xFF\xFF\xFF"
|
||||
nonce_mv[:3] = b"\xFF\xFF\xFF"
|
||||
cipher4.update(header_mv)
|
||||
header_mv[:3] = b"\xFF\xFF\xFF"
|
||||
pt_test = cipher4.decrypt_and_verify(memoryview(ct_test), memoryview(tag_test))
|
||||
|
||||
self.assertEqual(self.data, pt_test)
|
||||
|
||||
|
||||
class OcbFSMTests(unittest.TestCase):
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
nonce_96 = get_tag_random("nonce_128", 12)
|
||||
data = get_tag_random("data", 128)
|
||||
|
||||
def test_valid_init_encrypt_decrypt_digest_verify(self):
|
||||
# No authenticated data, fixed plaintext
|
||||
# Verify path INIT->ENCRYPT->ENCRYPT(NONE)->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data)
|
||||
ct += cipher.encrypt()
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->DECRYPT->DECRYPT(NONCE)->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.decrypt()
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_invalid_init_encrypt_decrypt_digest_verify(self):
|
||||
# No authenticated data, fixed plaintext
|
||||
# Verify path INIT->ENCRYPT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data)
|
||||
self.assertRaises(TypeError, cipher.digest)
|
||||
|
||||
# Verify path INIT->DECRYPT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
self.assertRaises(TypeError, cipher.verify)
|
||||
|
||||
def test_valid_init_update_digest_verify(self):
|
||||
# No plaintext, fixed authenticated data
|
||||
# Verify path INIT->UPDATE->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_full_path(self):
|
||||
# Fixed authenticated data, fixed plaintext
|
||||
# Verify path INIT->UPDATE->ENCRYPT->ENCRYPT(NONE)->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
ct = cipher.encrypt(self.data)
|
||||
ct += cipher.encrypt()
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->DECRYPT->DECRYPT(NONE)->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
cipher.decrypt(ct)
|
||||
cipher.decrypt()
|
||||
cipher.verify(mac)
|
||||
|
||||
# Verify path INIT->UPDATE->ENCRYPT->ENCRYPT_AND_DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
ct1 = cipher.encrypt(self.data[:2])
|
||||
ct2, mac = cipher.encrypt_and_digest(self.data[2:])
|
||||
|
||||
# Verify path INIT->UPDATE->DECRYPT->DECRYPT_AND_VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
cipher.decrypt(ct1)
|
||||
cipher.decrypt_and_verify(ct2, mac)
|
||||
|
||||
def test_invalid_encrypt_after_final(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
cipher.encrypt(self.data)
|
||||
cipher.encrypt()
|
||||
self.assertRaises(TypeError, cipher.encrypt, self.data)
|
||||
|
||||
def test_invalid_decrypt_after_final(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
cipher.decrypt(self.data)
|
||||
cipher.decrypt()
|
||||
self.assertRaises(TypeError, cipher.decrypt, self.data)
|
||||
|
||||
def test_valid_init_digest(self):
|
||||
# Verify path INIT->DIGEST
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.digest()
|
||||
|
||||
def test_valid_init_verify(self):
|
||||
# Verify path INIT->VERIFY
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
mac = cipher.digest()
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_multiple_encrypt_or_decrypt(self):
|
||||
for method_name in "encrypt", "decrypt":
|
||||
for auth_data in (None, b("333"), self.data,
|
||||
self.data + b("3")):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
if auth_data is not None:
|
||||
cipher.update(auth_data)
|
||||
method = getattr(cipher, method_name)
|
||||
method(self.data)
|
||||
method(self.data)
|
||||
method(self.data)
|
||||
method(self.data)
|
||||
method()
|
||||
|
||||
def test_valid_multiple_digest_or_verify(self):
|
||||
# Multiple calls to digest
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
first_mac = cipher.digest()
|
||||
for x in range(4):
|
||||
self.assertEqual(first_mac, cipher.digest())
|
||||
|
||||
# Multiple calls to verify
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
for x in range(5):
|
||||
cipher.verify(first_mac)
|
||||
|
||||
def test_valid_encrypt_and_digest_decrypt_and_verify(self):
|
||||
# encrypt_and_digest
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
# decrypt_and_verify
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
pt = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(self.data, pt)
|
||||
|
||||
def test_invalid_mixing_encrypt_decrypt(self):
|
||||
# Once per method, with or without assoc. data
|
||||
for method1_name, method2_name in (("encrypt", "decrypt"),
|
||||
("decrypt", "encrypt")):
|
||||
for assoc_data_present in (True, False):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB,
|
||||
nonce=self.nonce_96)
|
||||
if assoc_data_present:
|
||||
cipher.update(self.data)
|
||||
getattr(cipher, method1_name)(self.data)
|
||||
self.assertRaises(TypeError, getattr(cipher, method2_name),
|
||||
self.data)
|
||||
|
||||
def test_invalid_encrypt_or_update_after_digest(self):
|
||||
for method_name in "encrypt", "update":
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.encrypt(self.data)
|
||||
cipher.encrypt()
|
||||
cipher.digest()
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.encrypt_and_digest(self.data)
|
||||
|
||||
def test_invalid_decrypt_or_update_after_verify(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
ct = cipher.encrypt(self.data)
|
||||
ct += cipher.encrypt()
|
||||
mac = cipher.digest()
|
||||
|
||||
for method_name in "decrypt", "update":
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.decrypt(ct)
|
||||
cipher.decrypt()
|
||||
cipher.verify(mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OCB, nonce=self.nonce_96)
|
||||
cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertRaises(TypeError, getattr(cipher, method_name),
|
||||
self.data)
|
||||
|
||||
|
||||
def algo_rfc7253(keylen, taglen, noncelen):
|
||||
"""Implement the algorithm at page 18 of RFC 7253"""
|
||||
|
||||
key = bchr(0) * (keylen // 8 - 1) + bchr(taglen)
|
||||
C = b""
|
||||
|
||||
for i in range(128):
|
||||
S = bchr(0) * i
|
||||
|
||||
N = long_to_bytes(3 * i + 1, noncelen // 8)
|
||||
cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8)
|
||||
cipher.update(S)
|
||||
C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest()
|
||||
|
||||
N = long_to_bytes(3 * i + 2, noncelen // 8)
|
||||
cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8)
|
||||
C += cipher.encrypt(S) + cipher.encrypt() + cipher.digest()
|
||||
|
||||
N = long_to_bytes(3 * i + 3, noncelen // 8)
|
||||
cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8)
|
||||
cipher.update(S)
|
||||
C += cipher.encrypt() + cipher.digest()
|
||||
|
||||
N = long_to_bytes(385, noncelen // 8)
|
||||
cipher = AES.new(key, AES.MODE_OCB, nonce=N, mac_len=taglen // 8)
|
||||
cipher.update(C)
|
||||
return cipher.encrypt() + cipher.digest()
|
||||
|
||||
|
||||
class OcbRfc7253Test(unittest.TestCase):
|
||||
|
||||
# Tuple with
|
||||
# - nonce
|
||||
# - authenticated data
|
||||
# - plaintext
|
||||
# - ciphertext and 16 byte MAC tag
|
||||
tv1_key = "000102030405060708090A0B0C0D0E0F"
|
||||
tv1 = (
|
||||
(
|
||||
"BBAA99887766554433221100",
|
||||
"",
|
||||
"",
|
||||
"785407BFFFC8AD9EDCC5520AC9111EE6"
|
||||
),
|
||||
(
|
||||
"BBAA99887766554433221101",
|
||||
"0001020304050607",
|
||||
"0001020304050607",
|
||||
"6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009"
|
||||
),
|
||||
(
|
||||
"BBAA99887766554433221102",
|
||||
"0001020304050607",
|
||||
"",
|
||||
"81017F8203F081277152FADE694A0A00"
|
||||
),
|
||||
(
|
||||
"BBAA99887766554433221103",
|
||||
"",
|
||||
"0001020304050607",
|
||||
"45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9"
|
||||
),
|
||||
(
|
||||
"BBAA99887766554433221104",
|
||||
"000102030405060708090A0B0C0D0E0F",
|
||||
"000102030405060708090A0B0C0D0E0F",
|
||||
"571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5"
|
||||
"701C1CCEC8FC3358"
|
||||
),
|
||||
(
|
||||
"BBAA99887766554433221105",
|
||||
"000102030405060708090A0B0C0D0E0F",
|
||||
"",
|
||||
"8CF761B6902EF764462AD86498CA6B97"
|
||||
),
|
||||
(
|
||||
"BBAA99887766554433221106",
|
||||
"",
|
||||
"000102030405060708090A0B0C0D0E0F",
|
||||
"5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436B"
|
||||
"DF06D8FA1ECA343D"
|
||||
),
|
||||
(
|
||||
"BBAA99887766554433221107",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617",
|
||||
"1CA2207308C87C010756104D8840CE1952F09673A448A122"
|
||||
"C92C62241051F57356D7F3C90BB0E07F"
|
||||
),
|
||||
(
|
||||
"BBAA99887766554433221108",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617",
|
||||
"",
|
||||
"6DC225A071FC1B9F7C69F93B0F1E10DE"
|
||||
),
|
||||
(
|
||||
"BBAA99887766554433221109",
|
||||
"",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617",
|
||||
"221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3C"
|
||||
"E725F32494B9F914D85C0B1EB38357FF"
|
||||
),
|
||||
(
|
||||
"BBAA9988776655443322110A",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F",
|
||||
"BD6F6C496201C69296C11EFD138A467ABD3C707924B964DE"
|
||||
"AFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240"
|
||||
),
|
||||
(
|
||||
"BBAA9988776655443322110B",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F",
|
||||
"",
|
||||
"FE80690BEE8A485D11F32965BC9D2A32"
|
||||
),
|
||||
(
|
||||
"BBAA9988776655443322110C",
|
||||
"",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F",
|
||||
"2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF4"
|
||||
"6040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF"
|
||||
),
|
||||
(
|
||||
"BBAA9988776655443322110D",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F2021222324252627",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F2021222324252627",
|
||||
"D5CA91748410C1751FF8A2F618255B68A0A12E093FF45460"
|
||||
"6E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483"
|
||||
"A7035490C5769E60"
|
||||
),
|
||||
(
|
||||
"BBAA9988776655443322110E",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F2021222324252627",
|
||||
"",
|
||||
"C5CD9D1850C141E358649994EE701B68"
|
||||
),
|
||||
(
|
||||
"BBAA9988776655443322110F",
|
||||
"",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F2021222324252627",
|
||||
"4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15"
|
||||
"A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95"
|
||||
"A98CA5F3000B1479"
|
||||
)
|
||||
)
|
||||
|
||||
# Tuple with
|
||||
# - key
|
||||
# - nonce
|
||||
# - authenticated data
|
||||
# - plaintext
|
||||
# - ciphertext and 12 byte MAC tag
|
||||
tv2 = (
|
||||
"0F0E0D0C0B0A09080706050403020100",
|
||||
"BBAA9988776655443322110D",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F2021222324252627",
|
||||
"000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F2021222324252627",
|
||||
"1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1"
|
||||
"A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD"
|
||||
"AC4F02AA"
|
||||
)
|
||||
|
||||
# Tuple with
|
||||
# - key length
|
||||
# - MAC tag length
|
||||
# - Expected output
|
||||
tv3 = (
|
||||
(128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"),
|
||||
(192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"),
|
||||
(256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"),
|
||||
(128, 96, "77A3D8E73589158D25D01209"),
|
||||
(192, 96, "05D56EAD2752C86BE6932C5E"),
|
||||
(256, 96, "5458359AC23B0CBA9E6330DD"),
|
||||
(128, 64, "192C9B7BD90BA06A"),
|
||||
(192, 64, "0066BC6E0EF34E24"),
|
||||
(256, 64, "7D4EA5D445501CBE"),
|
||||
)
|
||||
|
||||
def test1(self):
|
||||
key = unhexlify(b(self.tv1_key))
|
||||
for tv in self.tv1:
|
||||
nonce, aad, pt, ct = [unhexlify(b(x)) for x in tv]
|
||||
ct, mac_tag = ct[:-16], ct[-16:]
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
|
||||
cipher.update(aad)
|
||||
ct2 = cipher.encrypt(pt) + cipher.encrypt()
|
||||
self.assertEqual(ct, ct2)
|
||||
self.assertEqual(mac_tag, cipher.digest())
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
|
||||
cipher.update(aad)
|
||||
pt2 = cipher.decrypt(ct) + cipher.decrypt()
|
||||
self.assertEqual(pt, pt2)
|
||||
cipher.verify(mac_tag)
|
||||
|
||||
def test2(self):
|
||||
|
||||
key, nonce, aad, pt, ct = [unhexlify(b(x)) for x in self.tv2]
|
||||
ct, mac_tag = ct[:-12], ct[-12:]
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12)
|
||||
cipher.update(aad)
|
||||
ct2 = cipher.encrypt(pt) + cipher.encrypt()
|
||||
self.assertEqual(ct, ct2)
|
||||
self.assertEqual(mac_tag, cipher.digest())
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OCB, nonce=nonce, mac_len=12)
|
||||
cipher.update(aad)
|
||||
pt2 = cipher.decrypt(ct) + cipher.decrypt()
|
||||
self.assertEqual(pt, pt2)
|
||||
cipher.verify(mac_tag)
|
||||
|
||||
def test3(self):
|
||||
for keylen, taglen, result in self.tv3:
|
||||
result2 = algo_rfc7253(keylen, taglen, 96)
|
||||
self.assertEqual(unhexlify(b(result)), result2)
|
||||
|
||||
|
||||
class OcbDkgTest(unittest.TestCase):
|
||||
"""Test vectors from https://gitlab.com/dkg/ocb-test-vectors"""
|
||||
|
||||
def test_1_2(self):
|
||||
tvs = []
|
||||
for fi in (1, 2):
|
||||
for nb in (104, 112, 120):
|
||||
tv_file = load_test_vectors(("Cipher", "AES"),
|
||||
"test-vector-%d-nonce%d.txt" % (fi, nb),
|
||||
"DKG tests, %d, %d bits" % (fi, nb),
|
||||
{})
|
||||
if tv_file is None:
|
||||
break
|
||||
key = tv_file[0].k
|
||||
for tv in tv_file[1:]:
|
||||
tv.k = key
|
||||
tvs.append(tv)
|
||||
|
||||
for tv in tvs:
|
||||
k, n, a, p, c = tv.k, tv.n, tv.a, tv.p, tv.c
|
||||
mac_len = len(c) - len(p)
|
||||
cipher = AES.new(k, AES.MODE_OCB, nonce=n, mac_len=mac_len)
|
||||
cipher.update(a)
|
||||
c_out, tag_out = cipher.encrypt_and_digest(p)
|
||||
self.assertEqual(c, c_out + tag_out)
|
||||
|
||||
def test_3(self):
|
||||
|
||||
def check(keylen, taglen, noncelen, exp):
|
||||
result = algo_rfc7253(keylen, taglen, noncelen)
|
||||
self.assertEqual(result, unhexlify(exp))
|
||||
|
||||
# test-vector-3-nonce104.txt
|
||||
check(128, 128, 104, "C47F5F0341E15326D4D1C46F47F05062")
|
||||
check(192, 128, 104, "95B9167A38EB80495DFC561A8486E109")
|
||||
check(256, 128, 104, "AFE1CDDB97028FD92F8FB3C8CFBA7D83")
|
||||
check(128, 96, 104, "F471B4983BA80946DF217A54")
|
||||
check(192, 96, 104, "5AE828BC51C24D85FA5CC7B2")
|
||||
check(256, 96, 104, "8C8335982E2B734616CAD14C")
|
||||
check(128, 64, 104, "B553F74B85FD1E5B")
|
||||
check(192, 64, 104, "3B49D20E513531F9")
|
||||
check(256, 64, 104, "ED6DA5B1216BF8BB")
|
||||
|
||||
# test-vector-3-nonce112.txt
|
||||
check(128, 128, 112, "CA8AFCA031BAC3F480A583BD6C50A547")
|
||||
check(192, 128, 112, "D170C1DF356308079DA9A3F619147148")
|
||||
check(256, 128, 112, "57F94381F2F9231EFB04AECD323757C3")
|
||||
check(128, 96, 112, "3A618B2531ED39F260C750DC")
|
||||
check(192, 96, 112, "9071EB89FEDBADDA88FD286E")
|
||||
check(256, 96, 112, "FDF0EFB97F21A39AC4BAB5AC")
|
||||
check(128, 64, 112, "FAB2FF3A8DD82A13")
|
||||
check(192, 64, 112, "AC01D912BD0737D3")
|
||||
check(256, 64, 112, "9D1FD0B500EA4ECF")
|
||||
|
||||
# test-vector-3-nonce120.txt
|
||||
check(128, 128, 120, "9E043A7140A25FB91F43BCC9DD7E0F46")
|
||||
check(192, 128, 120, "680000E53908323A7F396B955B8EC641")
|
||||
check(256, 128, 120, "8304B97FAACDA56E676602E1878A7E6F")
|
||||
check(128, 96, 120, "81F978AC9867E825D339847D")
|
||||
check(192, 96, 120, "EFCF2D60B24926ADA48CF5B1")
|
||||
check(256, 96, 120, "84961DC56E917B165E58C174")
|
||||
check(128, 64, 120, "227AEE6C9D905A61")
|
||||
check(192, 64, 120, "541DE691B9E1A2F9")
|
||||
check(256, 64, 120, "B0E761381C7129FC")
|
||||
|
||||
def test_2_bugfix(self):
|
||||
nonce = unhexlify("EEDDCCBBAA9988776655443322110D")
|
||||
key = unhexlify("0F0E0D0C0B0A09080706050403020100")
|
||||
A = unhexlify("000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F2021222324252627")
|
||||
P = unhexlify("000102030405060708090A0B0C0D0E0F1011121314151617"
|
||||
"18191A1B1C1D1E1F2021222324252627")
|
||||
C = unhexlify("07E903BFC49552411ABC865F5ECE60F6FAD1F5A9F14D3070"
|
||||
"FA2F1308A563207FFE14C1EEA44B22059C7484319D8A2C53"
|
||||
"C236A7B3")
|
||||
mac_len = len(C) - len(P)
|
||||
|
||||
# Prior to version 3.17, a nonce of maximum length (15 bytes)
|
||||
# was actually used as a 14 byte nonce. The last byte was erroneously
|
||||
# ignored.
|
||||
buggy_result = unhexlify("BA015C4E5AE54D76C890AE81BD40DC57"
|
||||
"03EDC30E8AC2A58BC5D8FA4D61C5BAE6"
|
||||
"C39BEAC435B2FD56A2A5085C1B135D77"
|
||||
"0C8264B7")
|
||||
cipher = AES.new(key, AES.MODE_OCB, nonce=nonce[:-1], mac_len=mac_len)
|
||||
cipher.update(A)
|
||||
C_out2, tag_out2 = cipher.encrypt_and_digest(P)
|
||||
self.assertEqual(buggy_result, C_out2 + tag_out2)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(OcbTests)
|
||||
tests += list_test_cases(OcbFSMTests)
|
||||
tests += list_test_cases(OcbRfc7253Test)
|
||||
tests += list_test_cases(OcbDkgTest)
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def suite():
|
||||
return unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
238
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_OFB.py
vendored
Normal file
238
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_OFB.py
vendored
Normal file
@ -0,0 +1,238 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
import unittest
|
||||
from binascii import unhexlify
|
||||
|
||||
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)
|
||||
|
||||
from Crypto.SelfTest.Cipher.test_CBC import BlockChainingTests
|
||||
|
||||
class OfbTests(BlockChainingTests):
|
||||
|
||||
aes_mode = AES.MODE_OFB
|
||||
des3_mode = DES3.MODE_OFB
|
||||
|
||||
# Redefine test_unaligned_data_128/64
|
||||
|
||||
def test_unaligned_data_128(self):
|
||||
plaintexts = [ b"7777777" ] * 100
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=8)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = AES.new(self.key_128, AES.MODE_CFB, self.iv_128, segment_size=128)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
def test_unaligned_data_64(self):
|
||||
plaintexts = [ b"7777777" ] * 100
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=8)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_CFB, self.iv_64, segment_size=64)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
|
||||
from Crypto.SelfTest.Cipher.test_CBC import NistBlockChainingVectors
|
||||
|
||||
class NistOfbVectors(NistBlockChainingVectors):
|
||||
aes_mode = AES.MODE_OFB
|
||||
des_mode = DES.MODE_OFB
|
||||
des3_mode = DES3.MODE_OFB
|
||||
|
||||
|
||||
# Create one test method per file
|
||||
nist_aes_kat_mmt_files = (
|
||||
# KAT
|
||||
"OFBGFSbox128.rsp",
|
||||
"OFBGFSbox192.rsp",
|
||||
"OFBGFSbox256.rsp",
|
||||
"OFBKeySbox128.rsp",
|
||||
"OFBKeySbox192.rsp",
|
||||
"OFBKeySbox256.rsp",
|
||||
"OFBVarKey128.rsp",
|
||||
"OFBVarKey192.rsp",
|
||||
"OFBVarKey256.rsp",
|
||||
"OFBVarTxt128.rsp",
|
||||
"OFBVarTxt192.rsp",
|
||||
"OFBVarTxt256.rsp",
|
||||
# MMT
|
||||
"OFBMMT128.rsp",
|
||||
"OFBMMT192.rsp",
|
||||
"OFBMMT256.rsp",
|
||||
)
|
||||
nist_aes_mct_files = (
|
||||
"OFBMCT128.rsp",
|
||||
"OFBMCT192.rsp",
|
||||
"OFBMCT256.rsp",
|
||||
)
|
||||
|
||||
for file_name in nist_aes_kat_mmt_files:
|
||||
def new_func(self, file_name=file_name):
|
||||
self._do_kat_aes_test(file_name)
|
||||
setattr(NistOfbVectors, "test_AES_" + file_name, new_func)
|
||||
|
||||
for file_name in nist_aes_mct_files:
|
||||
def new_func(self, file_name=file_name):
|
||||
self._do_mct_aes_test(file_name)
|
||||
setattr(NistOfbVectors, "test_AES_" + file_name, new_func)
|
||||
del file_name, new_func
|
||||
|
||||
nist_tdes_files = (
|
||||
"TOFBMMT2.rsp", # 2TDES
|
||||
"TOFBMMT3.rsp", # 3TDES
|
||||
"TOFBinvperm.rsp", # Single DES
|
||||
"TOFBpermop.rsp",
|
||||
"TOFBsubtab.rsp",
|
||||
"TOFBvarkey.rsp",
|
||||
"TOFBvartext.rsp",
|
||||
)
|
||||
|
||||
for file_name in nist_tdes_files:
|
||||
def new_func(self, file_name=file_name):
|
||||
self._do_tdes_test(file_name)
|
||||
setattr(NistOfbVectors, "test_TDES_" + file_name, new_func)
|
||||
|
||||
# END OF NIST OFB TEST VECTORS
|
||||
|
||||
|
||||
class SP800TestVectors(unittest.TestCase):
|
||||
"""Class exercising the OFB test vectors found in Section F.4
|
||||
of NIST SP 800-3A"""
|
||||
|
||||
def test_aes_128(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = '3b3fd92eb72dad20333449f8e83cfb4a' +\
|
||||
'7789508d16918f03f53c52dac54ed825' +\
|
||||
'9740051e9c5fecf64344f7a82260edcc' +\
|
||||
'304c6528f659c77866a510d9c1d6ae5e'
|
||||
key = '2b7e151628aed2a6abf7158809cf4f3c'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8])
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8])
|
||||
|
||||
def test_aes_192(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = 'cdc80d6fddf18cab34c25909c99a4174' +\
|
||||
'fcc28b8d4c63837c09e81700c1100401' +\
|
||||
'8d9a9aeac0f6596f559c6d4daf59a5f2' +\
|
||||
'6d9f200857ca6c3e9cac524bd9acc92a'
|
||||
key = '8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8])
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8])
|
||||
|
||||
def test_aes_256(self):
|
||||
plaintext = '6bc1bee22e409f96e93d7e117393172a' +\
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' +\
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' +\
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
ciphertext = 'dc7e84bfda79164b7ecd8486985d3860' +\
|
||||
'4febdc6740d20b3ac88f6ad82a4fb08d' +\
|
||||
'71ab47a086e86eedf39d1c5bba97c408' +\
|
||||
'0126141d67f37be8538f5a8be740e484'
|
||||
key = '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'
|
||||
iv = '000102030405060708090a0b0c0d0e0f'
|
||||
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.encrypt(plaintext), ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.decrypt(ciphertext), plaintext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.encrypt(plaintext[:-8]), ciphertext[:-8])
|
||||
cipher = AES.new(key, AES.MODE_OFB, iv)
|
||||
self.assertEqual(cipher.decrypt(ciphertext[:-8]), plaintext[:-8])
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(OfbTests)
|
||||
if config.get('slow_tests'):
|
||||
tests += list_test_cases(NistOfbVectors)
|
||||
tests += list_test_cases(SP800TestVectors)
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
218
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_OpenPGP.py
vendored
Normal file
218
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_OpenPGP.py
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
import unittest
|
||||
from binascii import unhexlify
|
||||
|
||||
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
|
||||
|
||||
def get_tag_random(tag, length):
|
||||
return SHAKE128.new(data=tobytes(tag)).read(length)
|
||||
|
||||
|
||||
from Crypto.SelfTest.Cipher.test_CBC import BlockChainingTests
|
||||
|
||||
class OpenPGPTests(BlockChainingTests):
|
||||
|
||||
aes_mode = AES.MODE_OPENPGP
|
||||
des3_mode = DES3.MODE_OPENPGP
|
||||
|
||||
# Redefine test_unaligned_data_128/64
|
||||
|
||||
key_128 = get_tag_random("key_128", 16)
|
||||
key_192 = get_tag_random("key_192", 24)
|
||||
iv_128 = get_tag_random("iv_128", 16)
|
||||
iv_64 = get_tag_random("iv_64", 8)
|
||||
data_128 = get_tag_random("data_128", 16)
|
||||
|
||||
def test_loopback_128(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128)
|
||||
pt = get_tag_random("plaintext", 16 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
eiv, ct = ct[:18], ct[18:]
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_loopback_64(self):
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64)
|
||||
pt = get_tag_random("plaintext", 8 * 100)
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
eiv, ct = ct[:10], ct[10:]
|
||||
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, eiv)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_IV_iv_attributes(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128)
|
||||
eiv = cipher.encrypt(b"")
|
||||
self.assertEqual(cipher.iv, self.iv_128)
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv)
|
||||
self.assertEqual(cipher.iv, self.iv_128)
|
||||
|
||||
def test_null_encryption_decryption(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128)
|
||||
eiv = cipher.encrypt(b"")
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv)
|
||||
self.assertEqual(cipher.decrypt(b""), b"")
|
||||
|
||||
def test_either_encrypt_or_decrypt(self):
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128)
|
||||
eiv = cipher.encrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.decrypt, b"")
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, eiv)
|
||||
cipher.decrypt(b"")
|
||||
self.assertRaises(TypeError, cipher.encrypt, b"")
|
||||
|
||||
def test_unaligned_data_128(self):
|
||||
plaintexts = [ b"7777777" ] * 100
|
||||
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = AES.new(self.key_128, AES.MODE_OPENPGP, self.iv_128)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
def test_unaligned_data_64(self):
|
||||
plaintexts = [ b"7777777" ] * 100
|
||||
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64)
|
||||
ciphertexts = [ cipher.encrypt(x) for x in plaintexts ]
|
||||
cipher = DES3.new(self.key_192, DES3.MODE_OPENPGP, self.iv_64)
|
||||
self.assertEqual(b"".join(ciphertexts), cipher.encrypt(b"".join(plaintexts)))
|
||||
|
||||
def test_output_param(self):
|
||||
pass
|
||||
|
||||
def test_output_param_same_buffer(self):
|
||||
pass
|
||||
|
||||
def test_output_param_memoryview(self):
|
||||
pass
|
||||
|
||||
def test_output_param_neg(self):
|
||||
pass
|
||||
|
||||
|
||||
class TestVectors(unittest.TestCase):
|
||||
|
||||
def test_aes(self):
|
||||
# The following test vectors have been generated with gpg v1.4.0.
|
||||
# The command line used was:
|
||||
#
|
||||
# gpg -c -z 0 --cipher-algo AES --passphrase secret_passphrase \
|
||||
# --disable-mdc --s2k-mode 0 --output ct pt
|
||||
#
|
||||
# As result, the content of the file 'pt' is encrypted with a key derived
|
||||
# from 'secret_passphrase' and written to file 'ct'.
|
||||
# Test vectors must be extracted from 'ct', which is a collection of
|
||||
# TLVs (see RFC4880 for all details):
|
||||
# - the encrypted data (with the encrypted IV as prefix) is the payload
|
||||
# of the TLV with tag 9 (Symmetrical Encrypted Data Packet).
|
||||
# This is the ciphertext in the test vector.
|
||||
# - inside the encrypted part, there is a further layer of TLVs. One must
|
||||
# look for tag 11 (Literal Data Packet); in its payload, after a short
|
||||
# but time dependent header, there is the content of file 'pt'.
|
||||
# In the test vector, the plaintext is the complete set of TLVs that gets
|
||||
# encrypted. It is not just the content of 'pt'.
|
||||
# - the key is the leftmost 16 bytes of the SHA1 digest of the password.
|
||||
# The test vector contains such shortened digest.
|
||||
#
|
||||
# Note that encryption uses a clear IV, and decryption an encrypted IV
|
||||
|
||||
plaintext = 'ac18620270744fb4f647426c61636b4361745768697465436174'
|
||||
ciphertext = 'dc6b9e1f095de609765c59983db5956ae4f63aea7405389d2ebb'
|
||||
key = '5baa61e4c9b93f3f0682250b6cf8331b'
|
||||
iv = '3d7d3e62282add7eb203eeba5c800733'
|
||||
encrypted_iv='fd934601ef49cb58b6d9aebca6056bdb96ef'
|
||||
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
encrypted_iv = unhexlify(encrypted_iv)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OPENPGP, iv)
|
||||
ct = cipher.encrypt(plaintext)
|
||||
self.assertEqual(ct[:18], encrypted_iv)
|
||||
self.assertEqual(ct[18:], ciphertext)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_OPENPGP, encrypted_iv)
|
||||
pt = cipher.decrypt(ciphertext)
|
||||
self.assertEqual(pt, plaintext)
|
||||
|
||||
def test_des3(self):
|
||||
# The following test vectors have been generated with gpg v1.4.0.
|
||||
# The command line used was:
|
||||
# gpg -c -z 0 --cipher-algo 3DES --passphrase secret_passphrase \
|
||||
# --disable-mdc --s2k-mode 0 --output ct pt
|
||||
# For an explanation, see test_AES.py .
|
||||
|
||||
plaintext = 'ac1762037074324fb53ba3596f73656d69746556616c6c6579'
|
||||
ciphertext = '9979238528357b90e2e0be549cb0b2d5999b9a4a447e5c5c7d'
|
||||
key = '7ade65b460f5ea9be35f9e14aa883a2048e3824aa616c0b2'
|
||||
iv='cd47e2afb8b7e4b0'
|
||||
encrypted_iv='6a7eef0b58050e8b904a'
|
||||
|
||||
plaintext = unhexlify(plaintext)
|
||||
ciphertext = unhexlify(ciphertext)
|
||||
key = unhexlify(key)
|
||||
iv = unhexlify(iv)
|
||||
encrypted_iv = unhexlify(encrypted_iv)
|
||||
|
||||
cipher = DES3.new(key, DES3.MODE_OPENPGP, iv)
|
||||
ct = cipher.encrypt(plaintext)
|
||||
self.assertEqual(ct[:10], encrypted_iv)
|
||||
self.assertEqual(ct[10:], ciphertext)
|
||||
|
||||
cipher = DES3.new(key, DES3.MODE_OPENPGP, encrypted_iv)
|
||||
pt = cipher.decrypt(ciphertext)
|
||||
self.assertEqual(pt, plaintext)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(OpenPGPTests)
|
||||
tests += list_test_cases(TestVectors)
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
552
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_SIV.py
vendored
Normal file
552
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_SIV.py
vendored
Normal file
@ -0,0 +1,552 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
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.strxor import strxor
|
||||
|
||||
|
||||
def get_tag_random(tag, length):
|
||||
return SHAKE128.new(data=tobytes(tag)).read(length)
|
||||
|
||||
|
||||
class SivTests(unittest.TestCase):
|
||||
|
||||
key_256 = get_tag_random("key_256", 32)
|
||||
key_384 = get_tag_random("key_384", 48)
|
||||
key_512 = get_tag_random("key_512", 64)
|
||||
nonce_96 = get_tag_random("nonce_128", 12)
|
||||
data = get_tag_random("data", 128)
|
||||
|
||||
def test_loopback_128(self):
|
||||
for key in self.key_256, self.key_384, self.key_512:
|
||||
cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
pt = get_tag_random("plaintext", 16 * 100)
|
||||
ct, mac = cipher.encrypt_and_digest(pt)
|
||||
|
||||
cipher = AES.new(key, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
pt2 = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_nonce(self):
|
||||
# Deterministic encryption
|
||||
AES.new(self.key_256, AES.MODE_SIV)
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, self.nonce_96)
|
||||
ct1, tag1 = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
ct2, tag2 = cipher.encrypt_and_digest(self.data)
|
||||
self.assertEqual(ct1 + tag1, ct2 + tag2)
|
||||
|
||||
def test_nonce_must_be_bytes(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_256, AES.MODE_SIV,
|
||||
nonce=u'test12345678')
|
||||
|
||||
def test_nonce_length(self):
|
||||
# nonce can be of any length (but not empty)
|
||||
self.assertRaises(ValueError, AES.new, self.key_256, AES.MODE_SIV,
|
||||
nonce=b"")
|
||||
|
||||
for x in range(1, 128):
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=bchr(1) * x)
|
||||
cipher.encrypt_and_digest(b'\x01')
|
||||
|
||||
def test_block_size_128(self):
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.block_size, AES.block_size)
|
||||
|
||||
def test_nonce_attribute(self):
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
self.assertEqual(cipher.nonce, self.nonce_96)
|
||||
|
||||
# By default, no nonce is randomly generated
|
||||
self.assertFalse(hasattr(AES.new(self.key_256, AES.MODE_SIV), "nonce"))
|
||||
|
||||
def test_unknown_parameters(self):
|
||||
self.assertRaises(TypeError, AES.new, self.key_256, AES.MODE_SIV,
|
||||
self.nonce_96, 7)
|
||||
self.assertRaises(TypeError, AES.new, self.key_256, AES.MODE_SIV,
|
||||
nonce=self.nonce_96, unknown=7)
|
||||
|
||||
# But some are only known by the base cipher
|
||||
# (e.g. use_aesni consumed by the AES module)
|
||||
AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96,
|
||||
use_aesni=False)
|
||||
|
||||
def test_encrypt_excludes_decrypt(self):
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.encrypt_and_digest(self.data)
|
||||
self.assertRaises(TypeError, cipher.decrypt, self.data)
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.encrypt_and_digest(self.data)
|
||||
self.assertRaises(TypeError, cipher.decrypt_and_verify,
|
||||
self.data, self.data)
|
||||
|
||||
def test_data_must_be_bytes(self):
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, u'test1234567890-*')
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt_and_verify,
|
||||
u'test1234567890-*', b"xxxx")
|
||||
|
||||
def test_mac_len(self):
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
_, mac = cipher.encrypt_and_digest(self.data)
|
||||
self.assertEqual(len(mac), 16)
|
||||
|
||||
def test_invalid_mac(self):
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
invalid_mac = strxor_c(mac, 0x01)
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt_and_verify, ct,
|
||||
invalid_mac)
|
||||
|
||||
def test_hex_mac(self):
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
mac_hex = cipher.hexdigest()
|
||||
self.assertEqual(cipher.digest(), unhexlify(mac_hex))
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.hexverify(mac_hex)
|
||||
|
||||
def test_bytearray(self):
|
||||
|
||||
# Encrypt
|
||||
key = bytearray(self.key_256)
|
||||
nonce = bytearray(self.nonce_96)
|
||||
data = bytearray(self.data)
|
||||
header = bytearray(self.data)
|
||||
|
||||
cipher1 = AES.new(self.key_256,
|
||||
AES.MODE_SIV,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data)
|
||||
ct, tag = cipher1.encrypt_and_digest(self.data)
|
||||
|
||||
cipher2 = AES.new(key,
|
||||
AES.MODE_SIV,
|
||||
nonce=nonce)
|
||||
key[:3] = b'\xFF\xFF\xFF'
|
||||
nonce[:3] = b'\xFF\xFF\xFF'
|
||||
cipher2.update(header)
|
||||
header[:3] = b'\xFF\xFF\xFF'
|
||||
ct_test, tag_test = cipher2.encrypt_and_digest(data)
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key = bytearray(self.key_256)
|
||||
nonce = bytearray(self.nonce_96)
|
||||
header = bytearray(self.data)
|
||||
ct_ba = bytearray(ct)
|
||||
tag_ba = bytearray(tag)
|
||||
|
||||
cipher3 = AES.new(key,
|
||||
AES.MODE_SIV,
|
||||
nonce=nonce)
|
||||
key[:3] = b'\xFF\xFF\xFF'
|
||||
nonce[:3] = b'\xFF\xFF\xFF'
|
||||
cipher3.update(header)
|
||||
header[:3] = b'\xFF\xFF\xFF'
|
||||
pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba)
|
||||
|
||||
self.assertEqual(self.data, pt_test)
|
||||
|
||||
def test_memoryview(self):
|
||||
|
||||
# Encrypt
|
||||
key = memoryview(bytearray(self.key_256))
|
||||
nonce = memoryview(bytearray(self.nonce_96))
|
||||
data = memoryview(bytearray(self.data))
|
||||
header = memoryview(bytearray(self.data))
|
||||
|
||||
cipher1 = AES.new(self.key_256,
|
||||
AES.MODE_SIV,
|
||||
nonce=self.nonce_96)
|
||||
cipher1.update(self.data)
|
||||
ct, tag = cipher1.encrypt_and_digest(self.data)
|
||||
|
||||
cipher2 = AES.new(key,
|
||||
AES.MODE_SIV,
|
||||
nonce=nonce)
|
||||
key[:3] = b'\xFF\xFF\xFF'
|
||||
nonce[:3] = b'\xFF\xFF\xFF'
|
||||
cipher2.update(header)
|
||||
header[:3] = b'\xFF\xFF\xFF'
|
||||
ct_test, tag_test= cipher2.encrypt_and_digest(data)
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(tag, tag_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decrypt
|
||||
key = memoryview(bytearray(self.key_256))
|
||||
nonce = memoryview(bytearray(self.nonce_96))
|
||||
header = memoryview(bytearray(self.data))
|
||||
ct_ba = memoryview(bytearray(ct))
|
||||
tag_ba = memoryview(bytearray(tag))
|
||||
|
||||
cipher3 = AES.new(key,
|
||||
AES.MODE_SIV,
|
||||
nonce=nonce)
|
||||
key[:3] = b'\xFF\xFF\xFF'
|
||||
nonce[:3] = b'\xFF\xFF\xFF'
|
||||
cipher3.update(header)
|
||||
header[:3] = b'\xFF\xFF\xFF'
|
||||
pt_test = cipher3.decrypt_and_verify(ct_ba, tag_ba)
|
||||
|
||||
self.assertEqual(self.data, pt_test)
|
||||
|
||||
def test_output_param(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
ct, tag = cipher.encrypt_and_digest(pt)
|
||||
|
||||
output = bytearray(128)
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
res, tag_out = cipher.encrypt_and_digest(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
self.assertEqual(tag, tag_out)
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
res = cipher.decrypt_and_verify(ct, tag, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
def test_output_param_memoryview(self):
|
||||
|
||||
pt = b'5' * 128
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
ct, tag = cipher.encrypt_and_digest(pt)
|
||||
|
||||
output = memoryview(bytearray(128))
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.encrypt_and_digest(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.decrypt_and_verify(ct, tag, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
def test_output_param_neg(self):
|
||||
LEN_PT = 128
|
||||
|
||||
pt = b'5' * LEN_PT
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
ct, tag = cipher.encrypt_and_digest(pt)
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt_and_digest, pt, output=b'0' * LEN_PT)
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag, output=b'0' * LEN_PT)
|
||||
|
||||
shorter_output = bytearray(LEN_PT - 1)
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.encrypt_and_digest, pt, output=shorter_output)
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
self.assertRaises(ValueError, cipher.decrypt_and_verify, ct, tag, output=shorter_output)
|
||||
|
||||
|
||||
class SivFSMTests(unittest.TestCase):
|
||||
|
||||
key_256 = get_tag_random("key_256", 32)
|
||||
nonce_96 = get_tag_random("nonce_96", 12)
|
||||
data = get_tag_random("data", 128)
|
||||
|
||||
def test_invalid_init_encrypt(self):
|
||||
# Path INIT->ENCRYPT fails
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV,
|
||||
nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.encrypt, b"xxx")
|
||||
|
||||
def test_invalid_init_decrypt(self):
|
||||
# Path INIT->DECRYPT fails
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV,
|
||||
nonce=self.nonce_96)
|
||||
self.assertRaises(TypeError, cipher.decrypt, b"xxx")
|
||||
|
||||
def test_valid_init_update_digest_verify(self):
|
||||
# No plaintext, fixed authenticated data
|
||||
# Verify path INIT->UPDATE->DIGEST
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
mac = cipher.digest()
|
||||
|
||||
# Verify path INIT->UPDATE->VERIFY
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV,
|
||||
nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_init_digest(self):
|
||||
# Verify path INIT->DIGEST
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.digest()
|
||||
|
||||
def test_valid_init_verify(self):
|
||||
# Verify path INIT->VERIFY
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
mac = cipher.digest()
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.verify(mac)
|
||||
|
||||
def test_valid_multiple_digest_or_verify(self):
|
||||
# Multiple calls to digest
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
first_mac = cipher.digest()
|
||||
for x in range(4):
|
||||
self.assertEqual(first_mac, cipher.digest())
|
||||
|
||||
# Multiple calls to verify
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
for x in range(5):
|
||||
cipher.verify(first_mac)
|
||||
|
||||
def test_valid_encrypt_and_digest_decrypt_and_verify(self):
|
||||
# encrypt_and_digest
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
ct, mac = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
# decrypt_and_verify
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.update(self.data)
|
||||
pt = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(self.data, pt)
|
||||
|
||||
def test_invalid_multiple_encrypt_and_digest(self):
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
ct, tag = cipher.encrypt_and_digest(self.data)
|
||||
self.assertRaises(TypeError, cipher.encrypt_and_digest, b'')
|
||||
|
||||
def test_invalid_multiple_decrypt_and_verify(self):
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
ct, tag = cipher.encrypt_and_digest(self.data)
|
||||
|
||||
cipher = AES.new(self.key_256, AES.MODE_SIV, nonce=self.nonce_96)
|
||||
cipher.decrypt_and_verify(ct, tag)
|
||||
self.assertRaises(TypeError, cipher.decrypt_and_verify, ct, tag)
|
||||
|
||||
|
||||
def transform(tv):
|
||||
new_tv = [[unhexlify(x) for x in tv[0].split("-")]]
|
||||
new_tv += [ unhexlify(x) for x in tv[1:5]]
|
||||
if tv[5]:
|
||||
nonce = unhexlify(tv[5])
|
||||
else:
|
||||
nonce = None
|
||||
new_tv += [ nonce ]
|
||||
return new_tv
|
||||
|
||||
|
||||
class TestVectors(unittest.TestCase):
|
||||
"""Class exercising the SIV test vectors found in RFC5297"""
|
||||
|
||||
# This is a list of tuples with 5 items:
|
||||
#
|
||||
# 1. Header + '|' + plaintext
|
||||
# 2. Header + '|' + ciphertext + '|' + MAC
|
||||
# 3. AES-128 key
|
||||
# 4. Description
|
||||
# 5. Dictionary of parameters to be passed to AES.new().
|
||||
# It must include the nonce.
|
||||
#
|
||||
# A "Header" is a dash ('-') separated sequece of components.
|
||||
#
|
||||
test_vectors_hex = [
|
||||
(
|
||||
'101112131415161718191a1b1c1d1e1f2021222324252627',
|
||||
'112233445566778899aabbccddee',
|
||||
'40c02b9690c4dc04daef7f6afe5c',
|
||||
'85632d07c6e8f37f950acd320a2ecc93',
|
||||
'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff',
|
||||
None
|
||||
),
|
||||
(
|
||||
'00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988' +
|
||||
'7766554433221100-102030405060708090a0',
|
||||
'7468697320697320736f6d6520706c61696e7465787420746f20656e63727970' +
|
||||
'74207573696e67205349562d414553',
|
||||
'cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829' +
|
||||
'ea64ad544a272e9c485b62a3fd5c0d',
|
||||
'7bdb6e3b432667eb06f4d14bff2fbd0f',
|
||||
'7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f',
|
||||
'09f911029d74e35bd84156c5635688c0'
|
||||
),
|
||||
]
|
||||
|
||||
test_vectors = [ transform(tv) for tv in test_vectors_hex ]
|
||||
|
||||
def runTest(self):
|
||||
for assoc_data, pt, ct, mac, key, nonce in self.test_vectors:
|
||||
|
||||
# Encrypt
|
||||
cipher = AES.new(key, AES.MODE_SIV, nonce=nonce)
|
||||
for x in assoc_data:
|
||||
cipher.update(x)
|
||||
ct2, mac2 = cipher.encrypt_and_digest(pt)
|
||||
self.assertEqual(ct, ct2)
|
||||
self.assertEqual(mac, mac2)
|
||||
|
||||
# Decrypt
|
||||
cipher = AES.new(key, AES.MODE_SIV, nonce=nonce)
|
||||
for x in assoc_data:
|
||||
cipher.update(x)
|
||||
pt2 = cipher.decrypt_and_verify(ct, mac)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
|
||||
class TestVectorsWycheproof(unittest.TestCase):
|
||||
|
||||
def __init__(self):
|
||||
unittest.TestCase.__init__(self)
|
||||
self._id = "None"
|
||||
|
||||
def setUp(self):
|
||||
self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
|
||||
"aes_siv_cmac_test.json",
|
||||
"Wycheproof AES SIV")
|
||||
|
||||
def shortDescription(self):
|
||||
return self._id
|
||||
|
||||
def test_encrypt(self, tv):
|
||||
self._id = "Wycheproof Encrypt AES-SIV Test #" + str(tv.id)
|
||||
|
||||
cipher = AES.new(tv.key, AES.MODE_SIV)
|
||||
cipher.update(tv.aad)
|
||||
ct, tag = cipher.encrypt_and_digest(tv.msg)
|
||||
if tv.valid:
|
||||
self.assertEqual(tag + ct, tv.ct)
|
||||
|
||||
def test_decrypt(self, tv):
|
||||
self._id = "Wycheproof Decrypt AES_SIV Test #" + str(tv.id)
|
||||
|
||||
cipher = AES.new(tv.key, AES.MODE_SIV)
|
||||
cipher.update(tv.aad)
|
||||
try:
|
||||
pt = cipher.decrypt_and_verify(tv.ct[16:], tv.ct[:16])
|
||||
except ValueError:
|
||||
assert not tv.valid
|
||||
else:
|
||||
assert tv.valid
|
||||
self.assertEqual(pt, tv.msg)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
for tv in self.tv:
|
||||
self.test_encrypt(tv)
|
||||
self.test_decrypt(tv)
|
||||
|
||||
|
||||
class TestVectorsWycheproof2(unittest.TestCase):
|
||||
|
||||
def __init__(self):
|
||||
unittest.TestCase.__init__(self)
|
||||
self._id = "None"
|
||||
|
||||
def setUp(self):
|
||||
self.tv = load_test_vectors_wycheproof(("Cipher", "wycheproof"),
|
||||
"aead_aes_siv_cmac_test.json",
|
||||
"Wycheproof AEAD SIV")
|
||||
|
||||
def shortDescription(self):
|
||||
return self._id
|
||||
|
||||
def test_encrypt(self, tv):
|
||||
self._id = "Wycheproof Encrypt AEAD-AES-SIV Test #" + str(tv.id)
|
||||
|
||||
cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv)
|
||||
cipher.update(tv.aad)
|
||||
ct, tag = cipher.encrypt_and_digest(tv.msg)
|
||||
if tv.valid:
|
||||
self.assertEqual(ct, tv.ct)
|
||||
self.assertEqual(tag, tv.tag)
|
||||
|
||||
def test_decrypt(self, tv):
|
||||
self._id = "Wycheproof Decrypt AEAD-AES-SIV Test #" + str(tv.id)
|
||||
|
||||
cipher = AES.new(tv.key, AES.MODE_SIV, nonce=tv.iv)
|
||||
cipher.update(tv.aad)
|
||||
try:
|
||||
pt = cipher.decrypt_and_verify(tv.ct, tv.tag)
|
||||
except ValueError:
|
||||
assert not tv.valid
|
||||
else:
|
||||
assert tv.valid
|
||||
self.assertEqual(pt, tv.msg)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
for tv in self.tv:
|
||||
self.test_encrypt(tv)
|
||||
self.test_decrypt(tv)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
wycheproof_warnings = config.get('wycheproof_warnings')
|
||||
|
||||
tests = []
|
||||
tests += list_test_cases(SivTests)
|
||||
tests += list_test_cases(SivFSMTests)
|
||||
tests += [ TestVectors() ]
|
||||
tests += [ TestVectorsWycheproof() ]
|
||||
tests += [ TestVectorsWycheproof2() ]
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
367
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_Salsa20.py
vendored
Normal file
367
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_Salsa20.py
vendored
Normal file
@ -0,0 +1,367 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/Salsa20.py: Self-test for the Salsa20 stream cipher
|
||||
#
|
||||
# Written in 2013 by Fabrizio Tarizzo <fabrizio@fabriziotarizzo.org>
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-test suite for Crypto.Cipher.Salsa20"""
|
||||
|
||||
import unittest
|
||||
|
||||
from Crypto.Util.py3compat import bchr
|
||||
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
|
||||
from Crypto.Cipher import Salsa20
|
||||
|
||||
from .common import make_stream_tests
|
||||
|
||||
# This is a list of (plaintext, ciphertext, key[, description[, params]])
|
||||
# tuples.
|
||||
test_data = [
|
||||
# Test vectors are taken from
|
||||
# http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors
|
||||
( '00' * 512,
|
||||
'4dfa5e481da23ea09a31022050859936da52fcee218005164f267cb65f5cfd7f'
|
||||
+ '2b4f97e0ff16924a52df269515110a07f9e460bc65ef95da58f740b7d1dbb0aa'
|
||||
+ 'd64cec189c7eb8c6bbf3d7376c80a481d43e628701f6a27afb9fe23919f24114'
|
||||
+ '8db44f70d7063efcc3dd55a0893a613c3c6fe1c127bd6f59910589293bb6ef9e'
|
||||
+ 'e24819066dee1a64f49b0bbad5988635272b169af861f85df881939f29ada6fd'
|
||||
+ '0241410e8d332ae4798d929434a2630de451ec4e0169694cbaa7ebb121ea6a2b'
|
||||
+ 'da9c1581f429e0a00f7d67e23b730676783b262e8eb43a25f55fb90b3e753aef'
|
||||
+ '8c6713ec66c51881111593ccb3e8cb8f8de124080501eeeb389c4bcb6977cf95'
|
||||
+ '7d5789631eb4554400e1e025935dfa7b3e9039d61bdc58a8697d36815bf1985c'
|
||||
+ 'efdf7ae112e5bb81e37ecf0616ce7147fc08a93a367e08631f23c03b00a8da2f'
|
||||
+ 'aa5024e5c8d30aca43fc2d5082067b21b234bc741d68fb292c6012c3764ccee3'
|
||||
+ '1e364a5403e00cfee338a21a01e7d3cefd5a770ca0ab48c435ea6116435f7ad8'
|
||||
+ '30b217b49f978a68e207ed9f462af7fb195b2115fe8f24f152e4ddc32202d6f2'
|
||||
+ 'b52fafbcfbc202d8a259a611e901d3f62d065eb13f09bbc45cd45119b843efaa'
|
||||
+ 'b375703739daced4dd4059fd71c3c47fc2f9939670fad4a46066adcc6a564578'
|
||||
+ '3308b90ffb72be04a6b147cbe38cc0c3b9267c296a92a7c69873f9f263be9703',
|
||||
'80000000000000000000000000000000',
|
||||
'128 bits key, set 1, vector 0',
|
||||
dict (iv='00'*8)),
|
||||
|
||||
( '00' * 512,
|
||||
'e3be8fdd8beca2e3ea8ef9475b29a6e7003951e1097a5c38d23b7a5fad9f6844'
|
||||
+ 'b22c97559e2723c7cbbd3fe4fc8d9a0744652a83e72a9c461876af4d7ef1a117'
|
||||
+ '8da2b74eef1b6283e7e20166abcae538e9716e4669e2816b6b20c5c356802001'
|
||||
+ 'cc1403a9a117d12a2669f456366d6ebb0f1246f1265150f793cdb4b253e348ae'
|
||||
+ '203d89bc025e802a7e0e00621d70aa36b7e07cb1e7d5b38d5e222b8b0e4b8407'
|
||||
+ '0142b1e29504767d76824850320b5368129fdd74e861b498e3be8d16f2d7d169'
|
||||
+ '57be81f47b17d9ae7c4ff15429a73e10acf250ed3a90a93c711308a74c6216a9'
|
||||
+ 'ed84cd126da7f28e8abf8bb63517e1ca98e712f4fb2e1a6aed9fdc73291faa17'
|
||||
+ '958211c4ba2ebd5838c635edb81f513a91a294e194f1c039aeec657dce40aa7e'
|
||||
+ '7c0af57cacefa40c9f14b71a4b3456a63e162ec7d8d10b8ffb1810d71001b618'
|
||||
+ '2f9f73da53b85405c11f7b2d890fa8ae0c7f2e926d8a98c7ec4e91b65120e988'
|
||||
+ '349631a700c6facec3471cb0413656e75e309456584084d7e12c5b43a41c43ed'
|
||||
+ '9a048abd9b880da65f6a665a20fe7b77cd292fe62cae644b7f7df69f32bdb331'
|
||||
+ '903e6505ce44fdc293920c6a9ec7057e23df7dad298f82ddf4efb7fdc7bfc622'
|
||||
+ '696afcfd0cddcc83c7e77f11a649d79acdc3354e9635ff137e929933a0bd6f53'
|
||||
+ '77efa105a3a4266b7c0d089d08f1e855cc32b15b93784a36e56a76cc64bc8477',
|
||||
'8000000000000000000000000000000000000000000000000000000000000000',
|
||||
'256 bits key, set 1, vector 0',
|
||||
dict (iv='00'*8)),
|
||||
|
||||
( '00' * 512,
|
||||
'169060ccb42bea7bee4d8012a02f3635eb7bca12859fa159cd559094b3507db8'
|
||||
+ '01735d1a1300102a9c9415546829cbd2021ba217b39b81d89c55b13d0c603359'
|
||||
+ '3f84159a3c84f4b4f4a0edcd9d38ff261a737909e0b66d68b5cac496f3a5be99'
|
||||
+ 'cb12c321ab711afaab36cc0947955e1a9bb952ed54425e7711279fbc81bb83f5'
|
||||
+ '6e55cea44e6daddb05858a153ea6213b3350c12aa1a83ef2726f09485fa71790'
|
||||
+ 'f9b9f922c7dda1113b1f9d56658ed3402803f511bc1f122601d5e7f0ff036e23'
|
||||
+ '23ef24bb24195b9fd574823cd8a40c29d86bd35c191e2038779ff696c712b6d8'
|
||||
+ '2e7014dbe1ac5d527af076c088c4a8d44317958189f6ef54933a7e0816b5b916'
|
||||
+ 'd8f12ed8afe9422b85e5cc9b8adec9d6cfabe8dbc1082bccc02f5a7266aa074c'
|
||||
+ 'a284e583a35837798cc0e69d4ce937653b8cdd65ce414b89138615ccb165ad19'
|
||||
+ '3c6b9c3d05eef4be921a10ea811fe61d11c6867600188e065daff90b509ec56b'
|
||||
+ 'd41e7e8968c478c78d590c2d2ee24ea009c8f49bc3d81672cfc47895a9e21c9a'
|
||||
+ '471ebf8e294bee5d2de436ac8d052bf31111b345f1da23c3a4d13b9fc5f0900a'
|
||||
+ 'a298f98f538973b8fad40d4d159777de2cfe2a3dead1645ddb49794827dba040'
|
||||
+ 'f70a0ff4ecd155e0f033604693a51e2363880e2ecf98699e7174af7c2c6b0fc6'
|
||||
+ '59ae329599a3949272a37b9b2183a0910922a3f325ae124dcbdd735364055ceb',
|
||||
'09090909090909090909090909090909',
|
||||
'128 bits key, set 2, vector 9',
|
||||
dict (iv='00'*8)),
|
||||
|
||||
( '00' * 512,
|
||||
'7041e747ceb22ed7812985465f50333124f971da1c5d6efe5ca201b886f31046'
|
||||
+ 'e757e5c3ec914f60ed1f6bce2819b6810953f12b8ba1199bf82d746a8b8a88f1'
|
||||
+ '142002978ec4c35b95dc2c82990f9e847a0ab45f2ca72625f5190c820f29f3aa'
|
||||
+ 'f5f0b5572b06b70a144f2a240c3b3098d4831fa1ce1459f8d1df226a6a79b0ab'
|
||||
+ '41e91799ef31b5ff3d756c19126b19025858ee70fbd69f2be955cb011c005e31'
|
||||
+ '32b271b378f39b0cb594e95c99ce6ff17735a541891845bbf0450afcb4a850b9'
|
||||
+ '4ee90afb713ae7e01295c74381180a3816d7020d5a396c0d97aaa783eaabb6ec'
|
||||
+ '44d5111157f2212d1b1b8fca7893e8b520cd482418c272ab119b569a2b9598eb'
|
||||
+ '355624d12e79adab81153b58cd22eaf1b2a32395dedc4a1c66f4d274070b9800'
|
||||
+ 'ea95766f0245a8295f8aadb36ddbbdfa936417c8dbc6235d19494036964d3e70'
|
||||
+ 'b125b0f800c3d53881d9d11e7970f827c2f9556935cd29e927b0aceb8cae5fd4'
|
||||
+ '0fd88a8854010a33db94c96c98735858f1c5df6844f864feaca8f41539313e7f'
|
||||
+ '3c0610214912cd5e6362197646207e2d64cd5b26c9dfe0822629dcbeb16662e8'
|
||||
+ '9ff5bf5cf2e499138a5e27bd5027329d0e68ddf53103e9e409523662e27f61f6'
|
||||
+ '5cf38c1232023e6a6ef66c315bcb2a4328642faabb7ca1e889e039e7c444b34b'
|
||||
+ 'b3443f596ac730f3df3dfcdb343c307c80f76e43e8898c5e8f43dc3bb280add0',
|
||||
'0909090909090909090909090909090909090909090909090909090909090909',
|
||||
'256 bits key, set 2, vector 9',
|
||||
dict (iv='00'*8)),
|
||||
|
||||
( '00' * 1024,
|
||||
'71daee5142d0728b41b6597933ebf467e43279e30978677078941602629cbf68'
|
||||
+ 'b73d6bd2c95f118d2b3e6ec955dabb6dc61c4143bc9a9b32b99dbe6866166dc0'
|
||||
+ '8631b7d6553050303d7252c264d3a90d26c853634813e09ad7545a6ce7e84a5d'
|
||||
+ 'fc75ec43431207d5319970b0faadb0e1510625bb54372c8515e28e2accf0a993'
|
||||
+ '0ad15f431874923d2a59e20d9f2a5367dba6051564f150287debb1db536ff9b0'
|
||||
+ '9ad981f25e5010d85d76ee0c305f755b25e6f09341e0812f95c94f42eead346e'
|
||||
+ '81f39c58c5faa2c88953dc0cac90469db2063cb5cdb22c9eae22afbf0506fca4'
|
||||
+ '1dc710b846fbdfe3c46883dd118f3a5e8b11b6afd9e71680d8666557301a2daa'
|
||||
+ 'fb9496c559784d35a035360885f9b17bd7191977deea932b981ebdb29057ae3c'
|
||||
+ '92cfeff5e6c5d0cb62f209ce342d4e35c69646ccd14e53350e488bb310a32f8b'
|
||||
+ '0248e70acc5b473df537ced3f81a014d4083932bedd62ed0e447b6766cd2604b'
|
||||
+ '706e9b346c4468beb46a34ecf1610ebd38331d52bf33346afec15eefb2a7699e'
|
||||
+ '8759db5a1f636a48a039688e39de34d995df9f27ed9edc8dd795e39e53d9d925'
|
||||
+ 'b278010565ff665269042f05096d94da3433d957ec13d2fd82a0066283d0d1ee'
|
||||
+ 'b81bf0ef133b7fd90248b8ffb499b2414cd4fa003093ff0864575a43749bf596'
|
||||
+ '02f26c717fa96b1d057697db08ebc3fa664a016a67dcef8807577cc3a09385d3'
|
||||
+ 'f4dc79b34364bb3b166ce65fe1dd28e3950fe6fa81063f7b16ce1c0e6daac1f8'
|
||||
+ '188455b77752045e863c9b256ad92bc6e2d08314c5bba191c274f42dfbb3d652'
|
||||
+ 'bb771956555e880f84cd8b827a4c5a52f3a099fa0259bd4aac3efd541f191170'
|
||||
+ '4412d6e85fbcc628b335875b9fef24807f6e1bc66c3186159e1e7f5a13913e02'
|
||||
+ 'd241ce2efdbcaa275039fb14eac5923d17ffbc7f1abd3b45e92127575bfbabf9'
|
||||
+ '3a257ebef0aa1437b326e41b585af572f7239c33b32981a1577a4f629b027e1e'
|
||||
+ 'b49d58cc497e944d79cef44357c2bf25442ab779651e991147bf79d6fd3a8868'
|
||||
+ '0cd3b1748e07fd10d78aceef6db8a5e563570d40127f754146c34a440f2a991a'
|
||||
+ '23fa39d365141f255041f2135c5cba4373452c114da1801bacca38610e3a6524'
|
||||
+ '2b822d32de4ab5a7d3cf9b61b37493c863bd12e2cae10530cddcda2cb7a5436b'
|
||||
+ 'ef8988d4d24e8cdc31b2d2a3586340bc5141f8f6632d0dd543bfed81eb471ba1'
|
||||
+ 'f3dc2225a15ffddcc03eb48f44e27e2aa390598adf83f15c6608a5f18d4dfcf0'
|
||||
+ 'f547d467a4d70b281c83a595d7660d0b62de78b9cca023cca89d7b1f83484638'
|
||||
+ '0e228c25f049184a612ef5bb3d37454e6cfa5b10dceda619d898a699b3c8981a'
|
||||
+ '173407844bb89b4287bf57dd6600c79e352c681d74b03fa7ea0d7bf6ad69f8a6'
|
||||
+ '8ecb001963bd2dd8a2baa0083ec09751cd9742402ad716be16d5c052304cfca1',
|
||||
'0F62B5085BAE0154A7FA4DA0F34699EC',
|
||||
'128 bits key, Set 6, vector# 3',
|
||||
dict (iv='288FF65DC42B92F9')),
|
||||
|
||||
( '00' * 1024,
|
||||
'5e5e71f90199340304abb22a37b6625bf883fb89ce3b21f54a10b81066ef87da'
|
||||
+ '30b77699aa7379da595c77dd59542da208e5954f89e40eb7aa80a84a6176663f'
|
||||
+ 'd910cde567cf1ff60f7040548d8f376bfd1f44c4774aac37410ede7d5c3463fc'
|
||||
+ '4508a603201d8495ad257894e5eb1914b53e8da5e4bf2bc83ac87ce55cc67df7'
|
||||
+ '093d9853d2a83a9c8be969175df7c807a17156df768445dd0874a9271c6537f5'
|
||||
+ 'ce0466473582375f067fa4fcdaf65dbc0139cd75e8c21a482f28c0fb8c3d9f94'
|
||||
+ '22606cc8e88fe28fe73ec3cb10ff0e8cc5f2a49e540f007265c65b7130bfdb98'
|
||||
+ '795b1df9522da46e48b30e55d9f0d787955ece720205b29c85f3ad9be33b4459'
|
||||
+ '7d21b54d06c9a60b04b8e640c64e566e51566730e86cf128ab14174f91bd8981'
|
||||
+ 'a6fb00fe587bbd6c38b5a1dfdb04ea7e61536fd229f957aa9b070ca931358e85'
|
||||
+ '11b92c53c523cb54828fb1513c5636fa9a0645b4a3c922c0db94986d92f314ff'
|
||||
+ '7852c03b231e4dceea5dd8cced621869cff818daf3c270ff3c8be2e5c74be767'
|
||||
+ 'a4e1fdf3327a934fe31e46df5a74ae2021cee021d958c4f615263d99a5ddae7f'
|
||||
+ 'eab45e6eccbafefe4761c57750847b7e75ee2e2f14333c0779ce4678f47b1e1b'
|
||||
+ '760a03a5f17d6e91d4b42313b3f1077ee270e432fe04917ed1fc8babebf7c941'
|
||||
+ '42b80dfb44a28a2a3e59093027606f6860bfb8c2e5897078cfccda7314c70035'
|
||||
+ 'f137de6f05daa035891d5f6f76e1df0fce1112a2ff0ac2bd3534b5d1bf4c7165'
|
||||
+ 'fb40a1b6eacb7f295711c4907ae457514a7010f3a342b4427593d61ba993bc59'
|
||||
+ '8bd09c56b9ee53aac5dd861fa4b4bb53888952a4aa9d8ca8671582de716270e1'
|
||||
+ '97375b3ee49e51fa2bf4ef32015dd9a764d966aa2ae541592d0aa650849e99ca'
|
||||
+ '5c6c39beebf516457cc32fe4c105bff314a12f1ec94bdf4d626f5d9b1cbbde42'
|
||||
+ 'e5733f0885765ba29e2e82c829d312f5fc7e180679ac84826c08d0a644b326d0'
|
||||
+ '44da0fdcc75fa53cfe4ced0437fa4df5a7ecbca8b4cb7c4a9ecf9a60d00a56eb'
|
||||
+ '81da52adc21f508dbb60a9503a3cc94a896616d86020d5b0e5c637329b6d396a'
|
||||
+ '41a21ba2c4a9493cf33fa2d4f10f77d5b12fdad7e478ccfe79b74851fc96a7ca'
|
||||
+ '6320c5efd561a222c0ab0fb44bbda0e42149611d2262bb7d1719150fa798718a'
|
||||
+ '0eec63ee297cad459869c8b0f06c4e2b56cbac03cd2605b2a924efedf85ec8f1'
|
||||
+ '9b0b6c90e7cbd933223ffeb1b3a3f9677657905829294c4c70acdb8b0891b47d'
|
||||
+ '0875d0cd6c0f4efe2917fc44b581ef0d1e4280197065d07da34ab33283364552'
|
||||
+ 'efad0bd9257b059acdd0a6f246812feb69e7e76065f27dbc2eee94da9cc41835'
|
||||
+ 'bf826e36e5cebe5d4d6a37a6a666246290ce51a0c082718ab0ec855668db1add'
|
||||
+ 'a658e5f257e0db39384d02e6145c4c00eaa079098f6d820d872de711b6ed08cf',
|
||||
'0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C',
|
||||
'256 bits key, Set 6, vector# 3',
|
||||
dict (iv='288FF65DC42B92F9')),
|
||||
|
||||
]
|
||||
|
||||
|
||||
class KeyLength(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
|
||||
nonce = bchr(0) * 8
|
||||
for key_length in (15, 30, 33):
|
||||
key = bchr(1) * key_length
|
||||
self.assertRaises(ValueError, Salsa20.new, key, nonce)
|
||||
|
||||
|
||||
class NonceTests(unittest.TestCase):
|
||||
|
||||
def test_invalid_nonce_length(self):
|
||||
key = bchr(1) * 16
|
||||
self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 7)
|
||||
self.assertRaises(ValueError, Salsa20.new, key, bchr(0) * 9)
|
||||
|
||||
def test_default_nonce(self):
|
||||
|
||||
cipher1 = Salsa20.new(bchr(1) * 16)
|
||||
cipher2 = Salsa20.new(bchr(1) * 16)
|
||||
self.assertEqual(len(cipher1.nonce), 8)
|
||||
self.assertNotEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
|
||||
class ByteArrayTest(unittest.TestCase):
|
||||
"""Verify we can encrypt or decrypt bytearrays"""
|
||||
|
||||
def runTest(self):
|
||||
|
||||
data = b"0123"
|
||||
key = b"9" * 32
|
||||
nonce = b"t" * 8
|
||||
|
||||
# Encryption
|
||||
data_ba = bytearray(data)
|
||||
key_ba = bytearray(key)
|
||||
nonce_ba = bytearray(nonce)
|
||||
|
||||
cipher1 = Salsa20.new(key=key, nonce=nonce)
|
||||
ct = cipher1.encrypt(data)
|
||||
|
||||
cipher2 = Salsa20.new(key=key_ba, nonce=nonce_ba)
|
||||
key_ba[:1] = b'\xFF'
|
||||
nonce_ba[:1] = b'\xFF'
|
||||
ct_test = cipher2.encrypt(data_ba)
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decryption
|
||||
key_ba = bytearray(key)
|
||||
nonce_ba = bytearray(nonce)
|
||||
ct_ba = bytearray(ct)
|
||||
|
||||
cipher3 = Salsa20.new(key=key_ba, nonce=nonce_ba)
|
||||
key_ba[:1] = b'\xFF'
|
||||
nonce_ba[:1] = b'\xFF'
|
||||
pt_test = cipher3.decrypt(ct_ba)
|
||||
|
||||
self.assertEqual(data, pt_test)
|
||||
|
||||
|
||||
class MemoryviewTest(unittest.TestCase):
|
||||
"""Verify we can encrypt or decrypt bytearrays"""
|
||||
|
||||
def runTest(self):
|
||||
|
||||
data = b"0123"
|
||||
key = b"9" * 32
|
||||
nonce = b"t" * 8
|
||||
|
||||
# Encryption
|
||||
data_mv = memoryview(bytearray(data))
|
||||
key_mv = memoryview(bytearray(key))
|
||||
nonce_mv = memoryview(bytearray(nonce))
|
||||
|
||||
cipher1 = Salsa20.new(key=key, nonce=nonce)
|
||||
ct = cipher1.encrypt(data)
|
||||
|
||||
cipher2 = Salsa20.new(key=key_mv, nonce=nonce_mv)
|
||||
key_mv[:1] = b'\xFF'
|
||||
nonce_mv[:1] = b'\xFF'
|
||||
ct_test = cipher2.encrypt(data_mv)
|
||||
|
||||
self.assertEqual(ct, ct_test)
|
||||
self.assertEqual(cipher1.nonce, cipher2.nonce)
|
||||
|
||||
# Decryption
|
||||
key_mv = memoryview(bytearray(key))
|
||||
nonce_mv = memoryview(bytearray(nonce))
|
||||
ct_mv = memoryview(bytearray(ct))
|
||||
|
||||
cipher3 = Salsa20.new(key=key_mv, nonce=nonce_mv)
|
||||
key_mv[:1] = b'\xFF'
|
||||
nonce_mv[:1] = b'\xFF'
|
||||
pt_test = cipher3.decrypt(ct_mv)
|
||||
|
||||
self.assertEqual(data, pt_test)
|
||||
|
||||
|
||||
class TestOutput(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
# Encrypt/Decrypt data and test output parameter
|
||||
|
||||
key = b'4' * 32
|
||||
nonce = b'5' * 8
|
||||
cipher = Salsa20.new(key=key, nonce=nonce)
|
||||
|
||||
pt = b'5' * 300
|
||||
ct = cipher.encrypt(pt)
|
||||
|
||||
output = bytearray(len(pt))
|
||||
cipher = Salsa20.new(key=key, nonce=nonce)
|
||||
res = cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
cipher = Salsa20.new(key=key, nonce=nonce)
|
||||
res = cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
output = memoryview(bytearray(len(pt)))
|
||||
cipher = Salsa20.new(key=key, nonce=nonce)
|
||||
cipher.encrypt(pt, output=output)
|
||||
self.assertEqual(ct, output)
|
||||
|
||||
cipher = Salsa20.new(key=key, nonce=nonce)
|
||||
cipher.decrypt(ct, output=output)
|
||||
self.assertEqual(pt, output)
|
||||
|
||||
cipher = Salsa20.new(key=key, nonce=nonce)
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt, output=b'0'*len(pt))
|
||||
|
||||
cipher = Salsa20.new(key=key, nonce=nonce)
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct, output=b'0'*len(ct))
|
||||
|
||||
shorter_output = bytearray(len(pt) - 1)
|
||||
|
||||
cipher = Salsa20.new(key=key, nonce=nonce)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt, output=shorter_output)
|
||||
|
||||
cipher = Salsa20.new(key=key, nonce=nonce)
|
||||
self.assertRaises(ValueError, cipher.decrypt, ct, output=shorter_output)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = make_stream_tests(Salsa20, "Salsa20", test_data)
|
||||
tests.append(KeyLength())
|
||||
tests += list_test_cases(NonceTests)
|
||||
tests.append(ByteArrayTest())
|
||||
tests.append(MemoryviewTest())
|
||||
tests.append(TestOutput())
|
||||
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
283
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_pkcs1_15.py
vendored
Normal file
283
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_pkcs1_15.py
vendored
Normal file
@ -0,0 +1,283 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/test_pkcs1_15.py: Self-test for PKCS#1 v1.5 encryption
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import unittest
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex
|
||||
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.SelfTest.loader import load_test_vectors_wycheproof
|
||||
|
||||
|
||||
def rws(t):
|
||||
"""Remove white spaces, tabs, and new lines from a string"""
|
||||
for c in ['\n', '\t', ' ']:
|
||||
t = t.replace(c, '')
|
||||
return t
|
||||
|
||||
|
||||
def t2b(t):
|
||||
"""Convert a text string with bytes in hex form to a byte string"""
|
||||
clean = b(rws(t))
|
||||
if len(clean) % 2 == 1:
|
||||
raise ValueError("Even number of characters expected")
|
||||
return a2b_hex(clean)
|
||||
|
||||
|
||||
class PKCS1_15_Tests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.rng = Random.new().read
|
||||
self.key1024 = RSA.generate(1024, self.rng)
|
||||
|
||||
# List of tuples with test data for PKCS#1 v1.5.
|
||||
# Each tuple is made up by:
|
||||
# Item #0: dictionary with RSA key component, or key to import
|
||||
# Item #1: plaintext
|
||||
# Item #2: ciphertext
|
||||
# Item #3: random data
|
||||
|
||||
_testData = (
|
||||
|
||||
#
|
||||
# Generated with openssl 0.9.8o
|
||||
#
|
||||
(
|
||||
# Private key
|
||||
'''-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQDAiAnvIAOvqVwJTaYzsKnefZftgtXGE2hPJppGsWl78yz9jeXY
|
||||
W/FxX/gTPURArNhdnhP6n3p2ZaDIBrO2zizbgIXs0IsljTTcr4vnI8fMXzyNUOjA
|
||||
zP3nzMqZDZK6757XQAobOssMkBFqRWwilT/3DsBhRpl3iMUhF+wvpTSHewIDAQAB
|
||||
AoGAC4HV/inOrpgTvSab8Wj0riyZgQOZ3U3ZpSlsfR8ra9Ib9Uee3jCYnKscu6Gk
|
||||
y6zI/cdt8EPJ4PuwAWSNJzbpbVaDvUq25OD+CX8/uRT08yBS4J8TzBitZJTD4lS7
|
||||
atdTnKT0Wmwk+u8tDbhvMKwnUHdJLcuIsycts9rwJVapUtkCQQDvDpx2JMun0YKG
|
||||
uUttjmL8oJ3U0m3ZvMdVwBecA0eebZb1l2J5PvI3EJD97eKe91Nsw8T3lwpoN40k
|
||||
IocSVDklAkEAzi1HLHE6EzVPOe5+Y0kGvrIYRRhncOb72vCvBZvD6wLZpQgqo6c4
|
||||
d3XHFBBQWA6xcvQb5w+VVEJZzw64y25sHwJBAMYReRl6SzL0qA0wIYrYWrOt8JeQ
|
||||
8mthulcWHXmqTgC6FEXP9Es5GD7/fuKl4wqLKZgIbH4nqvvGay7xXLCXD/ECQH9a
|
||||
1JYNMtRen5unSAbIOxRcKkWz92F0LKpm9ZW/S9vFHO+mBcClMGoKJHiuQxLBsLbT
|
||||
NtEZfSJZAeS2sUtn3/0CQDb2M2zNBTF8LlM0nxmh0k9VGm5TVIyBEMcipmvOgqIs
|
||||
HKukWBcq9f/UOmS0oEhai/6g+Uf7VHJdWaeO5LzuvwU=
|
||||
-----END RSA PRIVATE KEY-----''',
|
||||
# Plaintext
|
||||
'''THIS IS PLAINTEXT\x0A''',
|
||||
# Ciphertext
|
||||
'''3f dc fd 3c cd 5c 9b 12 af 65 32 e3 f7 d0 da 36
|
||||
8f 8f d9 e3 13 1c 7f c8 b3 f9 c1 08 e4 eb 79 9c
|
||||
91 89 1f 96 3b 94 77 61 99 a4 b1 ee 5d e6 17 c9
|
||||
5d 0a b5 63 52 0a eb 00 45 38 2a fb b0 71 3d 11
|
||||
f7 a1 9e a7 69 b3 af 61 c0 bb 04 5b 5d 4b 27 44
|
||||
1f 5b 97 89 ba 6a 08 95 ee 4f a2 eb 56 64 e5 0f
|
||||
da 7c f9 9a 61 61 06 62 ed a0 bc 5f aa 6c 31 78
|
||||
70 28 1a bb 98 3c e3 6a 60 3c d1 0b 0f 5a f4 75''',
|
||||
# Random data
|
||||
'''eb d7 7d 86 a4 35 23 a3 54 7e 02 0b 42 1d
|
||||
61 6c af 67 b8 4e 17 56 80 66 36 04 64 34 26 8a
|
||||
47 dd 44 b3 1a b2 17 60 f4 91 2e e2 b5 95 64 cc
|
||||
f9 da c8 70 94 54 86 4c ef 5b 08 7d 18 c4 ab 8d
|
||||
04 06 33 8f ca 15 5f 52 60 8a a1 0c f5 08 b5 4c
|
||||
bb 99 b8 94 25 04 9c e6 01 75 e6 f9 63 7a 65 61
|
||||
13 8a a7 47 77 81 ae 0d b8 2c 4d 50 a5'''
|
||||
),
|
||||
)
|
||||
|
||||
def testEncrypt1(self):
|
||||
for test in self._testData:
|
||||
# Build the key
|
||||
key = RSA.importKey(test[0])
|
||||
# RNG that takes its random numbers from a pool given
|
||||
# at initialization
|
||||
class randGen:
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.idx = 0
|
||||
def __call__(self, N):
|
||||
r = self.data[self.idx:self.idx+N]
|
||||
self.idx += N
|
||||
return r
|
||||
# The real test
|
||||
cipher = PKCS.new(key, randfunc=randGen(t2b(test[3])))
|
||||
ct = cipher.encrypt(b(test[1]))
|
||||
self.assertEqual(ct, t2b(test[2]))
|
||||
|
||||
def testEncrypt2(self):
|
||||
# Verify that encryption fail if plaintext is too long
|
||||
pt = '\x00'*(128-11+1)
|
||||
cipher = PKCS.new(self.key1024)
|
||||
self.assertRaises(ValueError, cipher.encrypt, pt)
|
||||
|
||||
def testVerify1(self):
|
||||
for test in self._testData:
|
||||
key = RSA.importKey(test[0])
|
||||
expected_pt = b(test[1])
|
||||
ct = t2b(test[2])
|
||||
cipher = PKCS.new(key)
|
||||
|
||||
# The real test
|
||||
pt = cipher.decrypt(ct, None)
|
||||
self.assertEqual(pt, expected_pt)
|
||||
|
||||
pt = cipher.decrypt(ct, b'\xFF' * len(expected_pt))
|
||||
self.assertEqual(pt, expected_pt)
|
||||
|
||||
def testVerify2(self):
|
||||
# Verify that decryption fails if ciphertext is not as long as
|
||||
# RSA modulus
|
||||
cipher = PKCS.new(self.key1024)
|
||||
self.assertRaises(ValueError, cipher.decrypt, '\x00'*127, "---")
|
||||
self.assertRaises(ValueError, cipher.decrypt, '\x00'*129, "---")
|
||||
|
||||
# Verify that decryption fails if there are less then 8 non-zero padding
|
||||
# bytes
|
||||
pt = b('\x00\x02' + '\xFF'*7 + '\x00' + '\x45'*118)
|
||||
pt_int = bytes_to_long(pt)
|
||||
ct_int = self.key1024._encrypt(pt_int)
|
||||
ct = long_to_bytes(ct_int, 128)
|
||||
self.assertEqual(b"---", cipher.decrypt(ct, b"---"))
|
||||
|
||||
def testEncryptVerify1(self):
|
||||
# Encrypt/Verify messages of length [0..RSAlen-11]
|
||||
# and therefore padding [8..117]
|
||||
for pt_len in range(0, 128 - 11 + 1):
|
||||
pt = self.rng(pt_len)
|
||||
cipher = PKCS.new(self.key1024)
|
||||
ct = cipher.encrypt(pt)
|
||||
pt2 = cipher.decrypt(ct, b'\xAA' * pt_len)
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_encrypt_verify_exp_pt_len(self):
|
||||
|
||||
cipher = PKCS.new(self.key1024)
|
||||
pt = b'5' * 16
|
||||
ct = cipher.encrypt(pt)
|
||||
sentinel = b'\xAA' * 16
|
||||
|
||||
pt_A = cipher.decrypt(ct, sentinel, 16)
|
||||
self.assertEqual(pt, pt_A)
|
||||
|
||||
pt_B = cipher.decrypt(ct, sentinel, 15)
|
||||
self.assertEqual(sentinel, pt_B)
|
||||
|
||||
pt_C = cipher.decrypt(ct, sentinel, 17)
|
||||
self.assertEqual(sentinel, pt_C)
|
||||
|
||||
def testByteArray(self):
|
||||
pt = b"XER"
|
||||
cipher = PKCS.new(self.key1024)
|
||||
ct = cipher.encrypt(bytearray(pt))
|
||||
pt2 = cipher.decrypt(bytearray(ct), '\xFF' * len(pt))
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def testMemoryview(self):
|
||||
pt = b"XER"
|
||||
cipher = PKCS.new(self.key1024)
|
||||
ct = cipher.encrypt(memoryview(bytearray(pt)))
|
||||
pt2 = cipher.decrypt(memoryview(bytearray(ct)), b'\xFF' * len(pt))
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def test_return_type(self):
|
||||
pt = b"XYZ"
|
||||
cipher = PKCS.new(self.key1024)
|
||||
ct = cipher.encrypt(pt)
|
||||
self.assertTrue(isinstance(ct, bytes))
|
||||
pt2 = cipher.decrypt(ct, b'\xAA' * 3)
|
||||
self.assertTrue(isinstance(pt2, bytes))
|
||||
|
||||
|
||||
class TestVectorsWycheproof(unittest.TestCase):
|
||||
|
||||
def __init__(self, wycheproof_warnings, skip_slow_tests):
|
||||
unittest.TestCase.__init__(self)
|
||||
self._wycheproof_warnings = wycheproof_warnings
|
||||
self._skip_slow_tests = skip_slow_tests
|
||||
self._id = "None"
|
||||
|
||||
def load_tests(self, filename):
|
||||
|
||||
def filter_rsa(group):
|
||||
return RSA.import_key(group['privateKeyPem'])
|
||||
|
||||
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):
|
||||
self.tv = []
|
||||
self.tv.extend(self.load_tests("rsa_pkcs1_2048_test.json"))
|
||||
if not self._skip_slow_tests:
|
||||
self.tv.extend(self.load_tests("rsa_pkcs1_3072_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_pkcs1_4096_test.json"))
|
||||
|
||||
def shortDescription(self):
|
||||
return self._id
|
||||
|
||||
def warn(self, tv):
|
||||
if tv.warning and self._wycheproof_warnings:
|
||||
import warnings
|
||||
warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment))
|
||||
|
||||
def test_decrypt(self, tv):
|
||||
self._id = "Wycheproof Decrypt PKCS#1v1.5 Test #%s" % tv.id
|
||||
sentinel = b'\xAA' * max(3, len(tv.msg))
|
||||
cipher = PKCS.new(tv.rsa_key)
|
||||
try:
|
||||
pt = cipher.decrypt(tv.ct, sentinel=sentinel)
|
||||
except ValueError:
|
||||
assert not tv.valid
|
||||
else:
|
||||
if pt == sentinel:
|
||||
assert not tv.valid
|
||||
else:
|
||||
assert tv.valid
|
||||
self.assertEqual(pt, tv.msg)
|
||||
self.warn(tv)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
for tv in self.tv:
|
||||
self.test_decrypt(tv)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
skip_slow_tests = not config.get('slow_tests')
|
||||
wycheproof_warnings = config.get('wycheproof_warnings')
|
||||
|
||||
tests = []
|
||||
tests += list_test_cases(PKCS1_15_Tests)
|
||||
tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)]
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def suite():
|
||||
return unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
506
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py
vendored
Normal file
506
env/lib/python3.11/site-packages/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py
vendored
Normal file
@ -0,0 +1,506 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Cipher/test_pkcs1_oaep.py: Self-test for PKCS#1 OAEP encryption
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
import unittest
|
||||
|
||||
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
|
||||
from Crypto.Hash import MD2, MD5, SHA1, SHA256, RIPEMD160, SHA224, SHA384, SHA512
|
||||
from Crypto import Random
|
||||
from Crypto.Signature.pss import MGF1
|
||||
|
||||
from Crypto.Util.py3compat import b, bchr
|
||||
|
||||
|
||||
def rws(t):
|
||||
"""Remove white spaces, tabs, and new lines from a string"""
|
||||
for c in ['\n', '\t', ' ']:
|
||||
t = t.replace(c, '')
|
||||
return t
|
||||
|
||||
|
||||
def t2b(t):
|
||||
"""Convert a text string with bytes in hex form to a byte string"""
|
||||
clean = rws(t)
|
||||
if len(clean) % 2 == 1:
|
||||
raise ValueError("Even number of characters expected")
|
||||
return a2b_hex(clean)
|
||||
|
||||
|
||||
class PKCS1_OAEP_Tests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.rng = Random.new().read
|
||||
self.key1024 = RSA.generate(1024, self.rng)
|
||||
|
||||
# List of tuples with test data for PKCS#1 OAEP
|
||||
# Each tuple is made up by:
|
||||
# Item #0: dictionary with RSA key component
|
||||
# Item #1: plaintext
|
||||
# Item #2: ciphertext
|
||||
# Item #3: random data (=seed)
|
||||
# Item #4: hash object
|
||||
|
||||
_testData = (
|
||||
|
||||
#
|
||||
# From in oaep-int.txt to be found in
|
||||
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
|
||||
#
|
||||
(
|
||||
# Private key
|
||||
{
|
||||
'n':'''bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7
|
||||
36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f
|
||||
b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48
|
||||
76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f
|
||||
af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84
|
||||
ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e
|
||||
e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f
|
||||
e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb''',
|
||||
# Public key
|
||||
'e':'11',
|
||||
# In the test vector, only p and q were given...
|
||||
# d is computed offline as e^{-1} mod (p-1)(q-1)
|
||||
'd':'''a5dafc5341faf289c4b988db30c1cdf83f31251e0
|
||||
668b42784813801579641b29410b3c7998d6bc465745e5c3
|
||||
92669d6870da2c082a939e37fdcb82ec93edac97ff3ad595
|
||||
0accfbc111c76f1a9529444e56aaf68c56c092cd38dc3bef
|
||||
5d20a939926ed4f74a13eddfbe1a1cecc4894af9428c2b7b
|
||||
8883fe4463a4bc85b1cb3c1'''
|
||||
}
|
||||
,
|
||||
# Plaintext
|
||||
'''d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49''',
|
||||
# Ciphertext
|
||||
'''12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0
|
||||
39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7
|
||||
63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6
|
||||
53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb
|
||||
6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0
|
||||
24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48
|
||||
da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d
|
||||
51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55''',
|
||||
# Random
|
||||
'''aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2
|
||||
f0 6c b5 8f''',
|
||||
# Hash
|
||||
SHA1,
|
||||
),
|
||||
|
||||
#
|
||||
# From in oaep-vect.txt to be found in Example 1.1
|
||||
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
|
||||
#
|
||||
(
|
||||
# Private key
|
||||
{
|
||||
'n':'''a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4
|
||||
91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab
|
||||
c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85
|
||||
12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72
|
||||
f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97
|
||||
c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14
|
||||
8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24
|
||||
76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb''',
|
||||
'e':'''01 00 01''',
|
||||
'd':'''53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c
|
||||
55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd
|
||||
8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b
|
||||
15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55
|
||||
fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73
|
||||
2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf
|
||||
b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de
|
||||
f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 '''
|
||||
}
|
||||
,
|
||||
# Plaintext
|
||||
'''66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23
|
||||
97 d5 0d ba 79 b9 87 00 4a fe fe 34''',
|
||||
# Ciphertext
|
||||
'''35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f
|
||||
7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb
|
||||
21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01
|
||||
03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f
|
||||
a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22
|
||||
d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26
|
||||
d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c
|
||||
40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a''',
|
||||
# Random
|
||||
'''18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1
|
||||
dd a0 a5 ef''',
|
||||
SHA1
|
||||
),
|
||||
|
||||
#
|
||||
# From in oaep-vect.txt to be found in Example 2.1
|
||||
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
|
||||
#
|
||||
(
|
||||
# Private key
|
||||
{
|
||||
'n':'''01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5
|
||||
e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e
|
||||
49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba
|
||||
7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d
|
||||
0a 67 f1 4b 16 94 c5 f0 37 94 51 a4 3e 49 a3 2d
|
||||
de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05
|
||||
5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66
|
||||
32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f
|
||||
45''',
|
||||
'e':'''01 00 01''',
|
||||
'd':'''08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa
|
||||
4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93
|
||||
c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47
|
||||
39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc
|
||||
d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0
|
||||
8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59
|
||||
41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25
|
||||
25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39'''
|
||||
},
|
||||
# Plaintext
|
||||
'''8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6
|
||||
52 b5 8c f1 d9 2f ec 57 0b ee e7''',
|
||||
# Ciphertext
|
||||
'''01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99
|
||||
2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a
|
||||
5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a
|
||||
ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34
|
||||
56 65 3a a6 38 2e 9a e5 9b 54 45 52 57 eb 09 9d
|
||||
56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a
|
||||
bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f
|
||||
ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72
|
||||
0e''',
|
||||
# Random
|
||||
'''8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94
|
||||
e7 1b 17 82''',
|
||||
SHA1
|
||||
),
|
||||
|
||||
#
|
||||
# From in oaep-vect.txt to be found in Example 10.1
|
||||
# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
|
||||
#
|
||||
(
|
||||
# Private key
|
||||
{
|
||||
'n':'''ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d
|
||||
db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8
|
||||
df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4
|
||||
02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5
|
||||
40 4b 56 9e 4e e1 bd cf 3c 1f b0 3e f1 13 80 2d
|
||||
4f 85 5e b9 b5 13 4b 5a 7c 80 85 ad ca e6 fa 2f
|
||||
a1 41 7e c3 76 3b e1 71 b0 c6 2b 76 0e de 23 c1
|
||||
2a d9 2b 98 08 84 c6 41 f5 a8 fa c2 6b da d4 a0
|
||||
33 81 a2 2f e1 b7 54 88 50 94 c8 25 06 d4 01 9a
|
||||
53 5a 28 6a fe b2 71 bb 9b a5 92 de 18 dc f6 00
|
||||
c2 ae ea e5 6e 02 f7 cf 79 fc 14 cf 3b dc 7c d8
|
||||
4f eb bb f9 50 ca 90 30 4b 22 19 a7 aa 06 3a ef
|
||||
a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76
|
||||
57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88
|
||||
d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc
|
||||
36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb''',
|
||||
'e':'''01 00 01''',
|
||||
'd':'''05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85
|
||||
25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59
|
||||
6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0
|
||||
d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d
|
||||
19 e6 1d b7 c7 41 0a 6b 26 75 df bf 5d 34 5b 80
|
||||
4d 20 1a dd 50 2d 5c e2 df cb 09 1c e9 99 7b be
|
||||
be 57 30 6f 38 3e 4d 58 81 03 f0 36 f7 e8 5d 19
|
||||
34 d1 52 a3 23 e4 a8 db 45 1d 6f 4a 5b 1b 0f 10
|
||||
2c c1 50 e0 2f ee e2 b8 8d ea 4a d4 c1 ba cc b2
|
||||
4d 84 07 2d 14 e1 d2 4a 67 71 f7 40 8e e3 05 64
|
||||
fb 86 d4 39 3a 34 bc f0 b7 88 50 1d 19 33 03 f1
|
||||
3a 22 84 b0 01 f0 f6 49 ea f7 93 28 d4 ac 5c 43
|
||||
0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87
|
||||
6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01
|
||||
84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e
|
||||
97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79'''
|
||||
},
|
||||
# Plaintext
|
||||
'''8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70
|
||||
b0 89 53 b0 6b 4e b2 05 bc 16 94 ee''',
|
||||
# Ciphertext
|
||||
'''53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15
|
||||
52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19
|
||||
ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee
|
||||
e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14
|
||||
4e 2d 0e 60 74 1f 89 93 c3 01 4b 58 b9 b1 95 7a
|
||||
8b ab cd 23 af 85 4f 4c 35 6f b1 66 2a a7 2b fc
|
||||
c7 e5 86 55 9d c4 28 0d 16 0c 12 67 85 a7 23 eb
|
||||
ee be ff 71 f1 15 94 44 0a ae f8 7d 10 79 3a 87
|
||||
74 a2 39 d4 a0 4c 87 fe 14 67 b9 da f8 52 08 ec
|
||||
6c 72 55 79 4a 96 cc 29 14 2f 9a 8b d4 18 e3 c1
|
||||
fd 67 34 4b 0c d0 82 9d f3 b2 be c6 02 53 19 62
|
||||
93 c6 b3 4d 3f 75 d3 2f 21 3d d4 5c 62 73 d5 05
|
||||
ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55
|
||||
ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64
|
||||
73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54
|
||||
bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc''',
|
||||
# Random
|
||||
'''47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0
|
||||
aa 63 bd 33''',
|
||||
SHA1
|
||||
),
|
||||
)
|
||||
|
||||
def testEncrypt1(self):
|
||||
# Verify encryption using all test vectors
|
||||
for test in self._testData:
|
||||
# Build the key
|
||||
comps = [int(rws(test[0][x]), 16) for x in ('n', 'e')]
|
||||
key = RSA.construct(comps)
|
||||
|
||||
# RNG that takes its random numbers from a pool given
|
||||
# at initialization
|
||||
class randGen:
|
||||
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.idx = 0
|
||||
|
||||
def __call__(self, N):
|
||||
r = self.data[self.idx:N]
|
||||
self.idx += N
|
||||
return r
|
||||
|
||||
# The real test
|
||||
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)
|
||||
|
||||
def testDecrypt1(self):
|
||||
# Verify decryption using all test vectors
|
||||
for test in self._testData:
|
||||
# Build the key
|
||||
comps = [int(rws(test[0][x]),16) for x in ('n', 'e', 'd')]
|
||||
key = RSA.construct(comps)
|
||||
# The real test
|
||||
cipher = PKCS.new(key, test[4])
|
||||
pt = cipher.decrypt(t2b(test[2]))
|
||||
self.assertEqual(pt, t2b(test[1]))
|
||||
|
||||
def testDecrypt2(self):
|
||||
# Simplest possible negative tests
|
||||
for ct_size in (127, 128, 129):
|
||||
cipher = PKCS.new(self.key1024)
|
||||
self.assertRaises(ValueError, cipher.decrypt, bchr(0x00)*ct_size)
|
||||
|
||||
def testEncryptDecrypt1(self):
|
||||
# Encrypt/Decrypt messages of length [0..128-2*20-2]
|
||||
for pt_len in range(0, 128-2*20-2):
|
||||
pt = self.rng(pt_len)
|
||||
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
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
def testEncryptDecrypt4(self):
|
||||
# Verify that encrypt() uses the custom MGF
|
||||
global mgfcalls
|
||||
# Helper function to monitor what's requested from MGF
|
||||
|
||||
def newMGF(seed, maskLen):
|
||||
global mgfcalls
|
||||
mgfcalls += 1
|
||||
return 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")
|
||||
cipher = PKCS.new(self.key1024)
|
||||
ct = cipher.encrypt(bytearray(pt))
|
||||
pt2 = cipher.decrypt(bytearray(ct))
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
def testMemoryview(self):
|
||||
pt = b("XER")
|
||||
cipher = PKCS.new(self.key1024)
|
||||
ct = cipher.encrypt(memoryview(bytearray(pt)))
|
||||
pt2 = cipher.decrypt(memoryview(bytearray(ct)))
|
||||
self.assertEqual(pt, pt2)
|
||||
|
||||
|
||||
class TestVectorsWycheproof(unittest.TestCase):
|
||||
|
||||
def __init__(self, wycheproof_warnings, skip_slow_tests):
|
||||
unittest.TestCase.__init__(self)
|
||||
self._wycheproof_warnings = wycheproof_warnings
|
||||
self._skip_slow_tests = skip_slow_tests
|
||||
self._id = "None"
|
||||
|
||||
def load_tests(self, filename):
|
||||
|
||||
def filter_rsa(group):
|
||||
return RSA.import_key(group['privateKeyPem'])
|
||||
|
||||
def filter_sha(group):
|
||||
if group['sha'] == "SHA-1":
|
||||
return SHA1
|
||||
elif group['sha'] == "SHA-224":
|
||||
return SHA224
|
||||
elif group['sha'] == "SHA-256":
|
||||
return SHA256
|
||||
elif group['sha'] == "SHA-384":
|
||||
return SHA384
|
||||
elif group['sha'] == "SHA-512":
|
||||
return SHA512
|
||||
else:
|
||||
raise ValueError("Unknown sha " + group['sha'])
|
||||
|
||||
def filter_mgf(group):
|
||||
if group['mgfSha'] == "SHA-1":
|
||||
return lambda x, y: MGF1(x, y, SHA1)
|
||||
elif group['mgfSha'] == "SHA-224":
|
||||
return lambda x, y: MGF1(x, y, SHA224)
|
||||
elif group['mgfSha'] == "SHA-256":
|
||||
return lambda x, y: MGF1(x, y, SHA256)
|
||||
elif group['mgfSha'] == "SHA-384":
|
||||
return lambda x, y: MGF1(x, y, SHA384)
|
||||
elif group['mgfSha'] == "SHA-512":
|
||||
return lambda x, y: MGF1(x, y, SHA512)
|
||||
else:
|
||||
raise ValueError("Unknown mgf/sha " + group['mgfSha'])
|
||||
|
||||
def filter_algo(group):
|
||||
return "%s with MGF1/%s" % (group['sha'], group['mgfSha'])
|
||||
|
||||
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):
|
||||
self.tv = []
|
||||
self.tv.extend(self.load_tests("rsa_oaep_2048_sha1_mgf1sha1_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha1_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_2048_sha224_mgf1sha224_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha1_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_2048_sha256_mgf1sha256_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha1_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_2048_sha384_mgf1sha384_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha1_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_2048_sha512_mgf1sha512_test.json"))
|
||||
if not self._skip_slow_tests:
|
||||
self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha1_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_3072_sha256_mgf1sha256_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha1_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_3072_sha512_mgf1sha512_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha1_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_4096_sha256_mgf1sha256_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha1_test.json"))
|
||||
self.tv.extend(self.load_tests("rsa_oaep_4096_sha512_mgf1sha512_test.json"))
|
||||
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
|
||||
|
||||
def warn(self, tv):
|
||||
if tv.warning and self._wycheproof_warnings:
|
||||
import warnings
|
||||
warnings.warn("Wycheproof warning: %s (%s)" % (self._id, tv.comment))
|
||||
|
||||
def test_decrypt(self, tv):
|
||||
self._id = "Wycheproof Decrypt %s Test #%s" % (tv.algo, tv.id)
|
||||
|
||||
cipher = PKCS.new(tv.rsa_key, hashAlgo=tv.hash_mod, mgfunc=tv.mgf, label=tv.label)
|
||||
try:
|
||||
pt = cipher.decrypt(tv.ct)
|
||||
except ValueError:
|
||||
assert not tv.valid
|
||||
else:
|
||||
assert tv.valid
|
||||
self.assertEqual(pt, tv.msg)
|
||||
self.warn(tv)
|
||||
|
||||
def runTest(self):
|
||||
|
||||
for tv in self.tv:
|
||||
self.test_decrypt(tv)
|
||||
|
||||
|
||||
def get_tests(config={}):
|
||||
skip_slow_tests = not config.get('slow_tests')
|
||||
wycheproof_warnings = config.get('wycheproof_warnings')
|
||||
|
||||
tests = []
|
||||
tests += list_test_cases(PKCS1_OAEP_Tests)
|
||||
tests += [TestVectorsWycheproof(wycheproof_warnings, skip_slow_tests)]
|
||||
return tests
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def suite():
|
||||
unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
Reference in New Issue
Block a user